summaryrefslogtreecommitdiff
path: root/third_party/llvm-project/include/llvm/Support
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/llvm-project/include/llvm/Support')
-rw-r--r--third_party/llvm-project/include/llvm/Support/AArch64TargetParser.def151
-rw-r--r--third_party/llvm-project/include/llvm/Support/AArch64TargetParser.h129
-rw-r--r--third_party/llvm-project/include/llvm/Support/ARMAttributeParser.h141
-rw-r--r--third_party/llvm-project/include/llvm/Support/ARMBuildAttributes.h253
-rw-r--r--third_party/llvm-project/include/llvm/Support/ARMTargetParser.def293
-rw-r--r--third_party/llvm-project/include/llvm/Support/ARMTargetParser.h267
-rw-r--r--third_party/llvm-project/include/llvm/Support/AlignOf.h55
-rw-r--r--third_party/llvm-project/include/llvm/Support/Alignment.h403
-rw-r--r--third_party/llvm-project/include/llvm/Support/Allocator.h523
-rw-r--r--third_party/llvm-project/include/llvm/Support/BinaryByteStream.h273
-rw-r--r--third_party/llvm-project/include/llvm/Support/BinaryStream.h101
-rw-r--r--third_party/llvm-project/include/llvm/Support/BinaryStreamError.h47
-rw-r--r--third_party/llvm-project/include/llvm/Support/CBindingWrapping.h46
-rw-r--r--third_party/llvm-project/include/llvm/Support/Casting.h408
-rw-r--r--third_party/llvm-project/include/llvm/Support/Chrono.h171
-rw-r--r--third_party/llvm-project/include/llvm/Support/CodeGen.h67
-rw-r--r--third_party/llvm-project/include/llvm/Support/CommandLine.h1
-rw-r--r--third_party/llvm-project/include/llvm/Support/Compiler.h585
-rw-r--r--third_party/llvm-project/include/llvm/Support/ConvertUTF.h306
-rw-r--r--third_party/llvm-project/include/llvm/Support/DJB.h32
-rw-r--r--third_party/llvm-project/include/llvm/Support/DataExtractor.h575
-rw-r--r--third_party/llvm-project/include/llvm/Support/DataTypes.h16
-rw-r--r--third_party/llvm-project/include/llvm/Support/Debug.h126
-rw-r--r--third_party/llvm-project/include/llvm/Support/Endian.h429
-rw-r--r--third_party/llvm-project/include/llvm/Support/Errc.h86
-rw-r--r--third_party/llvm-project/include/llvm/Support/Errno.h46
-rw-r--r--third_party/llvm-project/include/llvm/Support/Error.h1351
-rw-r--r--third_party/llvm-project/include/llvm/Support/ErrorHandling.h143
-rw-r--r--third_party/llvm-project/include/llvm/Support/ErrorOr.h278
-rw-r--r--third_party/llvm-project/include/llvm/Support/FileOutputBuffer.h88
-rw-r--r--third_party/llvm-project/include/llvm/Support/FileSystem.h1444
-rw-r--r--third_party/llvm-project/include/llvm/Support/Format.h257
-rw-r--r--third_party/llvm-project/include/llvm/Support/FormatAdapters.h108
-rw-r--r--third_party/llvm-project/include/llvm/Support/FormatCommon.h76
-rw-r--r--third_party/llvm-project/include/llvm/Support/FormatProviders.h422
-rw-r--r--third_party/llvm-project/include/llvm/Support/FormatVariadic.h264
-rw-r--r--third_party/llvm-project/include/llvm/Support/FormatVariadicDetails.h164
-rw-r--r--third_party/llvm-project/include/llvm/Support/FormattedStream.h161
-rw-r--r--third_party/llvm-project/include/llvm/Support/Host.h70
-rw-r--r--third_party/llvm-project/include/llvm/Support/LEB128.h198
-rw-r--r--third_party/llvm-project/include/llvm/Support/LICENSE.TXT6
-rw-r--r--third_party/llvm-project/include/llvm/Support/LineIterator.h87
-rw-r--r--third_party/llvm-project/include/llvm/Support/Locale.h17
-rw-r--r--third_party/llvm-project/include/llvm/Support/MD5.h122
-rw-r--r--third_party/llvm-project/include/llvm/Support/ManagedStatic.h1
-rw-r--r--third_party/llvm-project/include/llvm/Support/MathExtras.h951
-rw-r--r--third_party/llvm-project/include/llvm/Support/MemAlloc.h66
-rw-r--r--third_party/llvm-project/include/llvm/Support/MemoryBuffer.h286
-rw-r--r--third_party/llvm-project/include/llvm/Support/NativeFormatting.h48
-rw-r--r--third_party/llvm-project/include/llvm/Support/Path.h464
-rw-r--r--third_party/llvm-project/include/llvm/Support/PointerLikeTypeTraits.h149
-rw-r--r--third_party/llvm-project/include/llvm/Support/Printable.h51
-rw-r--r--third_party/llvm-project/include/llvm/Support/Process.h209
-rw-r--r--third_party/llvm-project/include/llvm/Support/Program.h208
-rw-r--r--third_party/llvm-project/include/llvm/Support/Regex.h109
-rw-r--r--third_party/llvm-project/include/llvm/Support/ReverseIteration.h19
-rw-r--r--third_party/llvm-project/include/llvm/Support/SMLoc.h64
-rw-r--r--third_party/llvm-project/include/llvm/Support/ScopedPrinter.h388
-rw-r--r--third_party/llvm-project/include/llvm/Support/Signals.h90
-rw-r--r--third_party/llvm-project/include/llvm/Support/SmallVectorMemoryBuffer.h65
-rw-r--r--third_party/llvm-project/include/llvm/Support/SourceMgr.h310
-rw-r--r--third_party/llvm-project/include/llvm/Support/SwapByteOrder.h160
-rw-r--r--third_party/llvm-project/include/llvm/Support/TargetParser.h174
-rw-r--r--third_party/llvm-project/include/llvm/Support/TargetRegistry.h1209
-rw-r--r--third_party/llvm-project/include/llvm/Support/Threading.h0
-rw-r--r--third_party/llvm-project/include/llvm/Support/TypeSize.h201
-rw-r--r--third_party/llvm-project/include/llvm/Support/Unicode.h70
-rw-r--r--third_party/llvm-project/include/llvm/Support/UnicodeCharRanges.h103
-rw-r--r--third_party/llvm-project/include/llvm/Support/WindowsError.h18
-rw-r--r--third_party/llvm-project/include/llvm/Support/WithColor.h118
-rw-r--r--third_party/llvm-project/include/llvm/Support/X86TargetParser.def173
-rw-r--r--third_party/llvm-project/include/llvm/Support/YAMLParser.h619
-rw-r--r--third_party/llvm-project/include/llvm/Support/YAMLTraits.h2043
-rw-r--r--third_party/llvm-project/include/llvm/Support/circular_raw_ostream.h159
-rw-r--r--third_party/llvm-project/include/llvm/Support/raw_ostream.h587
-rw-r--r--third_party/llvm-project/include/llvm/Support/type_traits.h192
76 files changed, 20090 insertions, 0 deletions
diff --git a/third_party/llvm-project/include/llvm/Support/AArch64TargetParser.def b/third_party/llvm-project/include/llvm/Support/AArch64TargetParser.def
new file mode 100644
index 000000000..7e8ba9122
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/AArch64TargetParser.def
@@ -0,0 +1,151 @@
+//===- AARCH64TargetParser.def - AARCH64 target parsing defines ---------*- 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 defines to build up the AARCH64 target parser's logic.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+#ifndef AARCH64_ARCH
+#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)
+#endif
+AARCH64_ARCH("invalid", INVALID, "", "",
+ ARMBuildAttrs::CPUArch::v8_A, FK_NONE, AArch64::AEK_NONE)
+AARCH64_ARCH("armv8-a", ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A,
+ FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_SIMD))
+AARCH64_ARCH("armv8.1-a", ARMV8_1A, "8.1-A", "v8.1a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_LSE | AArch64::AEK_RDM))
+AARCH64_ARCH("armv8.2-a", ARMV8_2A, "8.2-A", "v8.2a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
+ AArch64::AEK_RDM))
+AARCH64_ARCH("armv8.3-a", ARMV8_3A, "8.3-A", "v8.3a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
+ AArch64::AEK_RDM | AArch64::AEK_RCPC))
+AARCH64_ARCH("armv8.4-a", ARMV8_4A, "8.4-A", "v8.4a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
+ AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD))
+AARCH64_ARCH("armv8.5-a", ARMV8_5A, "8.5-A", "v8.5a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
+ AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD))
+#undef AARCH64_ARCH
+
+#ifndef AARCH64_ARCH_EXT_NAME
+#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE)
+#endif
+// FIXME: This would be nicer were it tablegen
+AARCH64_ARCH_EXT_NAME("invalid", AArch64::AEK_INVALID, nullptr, nullptr)
+AARCH64_ARCH_EXT_NAME("none", AArch64::AEK_NONE, nullptr, nullptr)
+AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc")
+AARCH64_ARCH_EXT_NAME("lse", AArch64::AEK_LSE, "+lse", "-lse")
+AARCH64_ARCH_EXT_NAME("rdm", AArch64::AEK_RDM, "+rdm", "-rdm")
+AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto")
+AARCH64_ARCH_EXT_NAME("sm4", AArch64::AEK_SM4, "+sm4", "-sm4")
+AARCH64_ARCH_EXT_NAME("sha3", AArch64::AEK_SHA3, "+sha3", "-sha3")
+AARCH64_ARCH_EXT_NAME("sha2", AArch64::AEK_SHA2, "+sha2", "-sha2")
+AARCH64_ARCH_EXT_NAME("aes", AArch64::AEK_AES, "+aes", "-aes")
+AARCH64_ARCH_EXT_NAME("dotprod", AArch64::AEK_DOTPROD, "+dotprod","-dotprod")
+AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8")
+AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon")
+AARCH64_ARCH_EXT_NAME("fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16")
+AARCH64_ARCH_EXT_NAME("fp16fml", AArch64::AEK_FP16FML, "+fp16fml", "-fp16fml")
+AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe")
+AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras")
+AARCH64_ARCH_EXT_NAME("sve", AArch64::AEK_SVE, "+sve", "-sve")
+AARCH64_ARCH_EXT_NAME("sve2", AArch64::AEK_SVE2, "+sve2", "-sve2")
+AARCH64_ARCH_EXT_NAME("sve2-aes", AArch64::AEK_SVE2AES, "+sve2-aes", "-sve2-aes")
+AARCH64_ARCH_EXT_NAME("sve2-sm4", AArch64::AEK_SVE2SM4, "+sve2-sm4", "-sve2-sm4")
+AARCH64_ARCH_EXT_NAME("sve2-sha3", AArch64::AEK_SVE2SHA3, "+sve2-sha3", "-sve2-sha3")
+AARCH64_ARCH_EXT_NAME("sve2-bitperm", AArch64::AEK_SVE2BITPERM, "+sve2-bitperm", "-sve2-bitperm")
+AARCH64_ARCH_EXT_NAME("rcpc", AArch64::AEK_RCPC, "+rcpc", "-rcpc")
+AARCH64_ARCH_EXT_NAME("rng", AArch64::AEK_RAND, "+rand", "-rand")
+AARCH64_ARCH_EXT_NAME("memtag", AArch64::AEK_MTE, "+mte", "-mte")
+AARCH64_ARCH_EXT_NAME("ssbs", AArch64::AEK_SSBS, "+ssbs", "-ssbs")
+AARCH64_ARCH_EXT_NAME("sb", AArch64::AEK_SB, "+sb", "-sb")
+AARCH64_ARCH_EXT_NAME("predres", AArch64::AEK_PREDRES, "+predres", "-predres")
+AARCH64_ARCH_EXT_NAME("tme", AArch64::AEK_TME, "+tme", "-tme")
+#undef AARCH64_ARCH_EXT_NAME
+
+#ifndef AARCH64_CPU_NAME
+#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_CPU_NAME("cortex-a53", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true,
+ (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_CPU_NAME("cortex-a65", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_RAS |
+ AArch64::AEK_RCPC | AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("cortex-a65ae", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_RAS |
+ AArch64::AEK_RCPC | AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("cortex-a72", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC))
+AARCH64_CPU_NAME("cortex-a73", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (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("neoverse-e1", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_RAS |
+ AArch64::AEK_RCPC | AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("neoverse-n1", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 |
+ AArch64::AEK_PROFILE | AArch64::AEK_RAS | AArch64::AEK_RCPC |
+ AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("cyclone", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_NONE))
+AARCH64_CPU_NAME("exynos-m3", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC))
+AARCH64_CPU_NAME("exynos-m4", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (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_CPU_NAME("saphira", ARMV8_3A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_PROFILE))
+AARCH64_CPU_NAME("kryo", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC))
+AARCH64_CPU_NAME("thunderx2t99", ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_NONE))
+AARCH64_CPU_NAME("thunderx", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
+AARCH64_CPU_NAME("thunderxt88", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
+AARCH64_CPU_NAME("thunderxt81", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
+AARCH64_CPU_NAME("thunderxt83", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
+AARCH64_CPU_NAME("tsv110", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (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/third_party/llvm-project/include/llvm/Support/AArch64TargetParser.h b/third_party/llvm-project/include/llvm/Support/AArch64TargetParser.h
new file mode 100644
index 000000000..94f341c83
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/AArch64TargetParser.h
@@ -0,0 +1,129 @@
+//===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise AArch64 hardware features
+// such as FPU/CPU/ARCH and extension names.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_AARCH64TARGETPARSERCOMMON_H
+#define LLVM_SUPPORT_AARCH64TARGETPARSERCOMMON_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/ARMTargetParser.h"
+#include <vector>
+
+// FIXME:This should be made into class design,to avoid dupplication.
+namespace llvm {
+namespace AArch64 {
+
+// Arch extension modifiers for CPUs.
+enum ArchExtKind : unsigned {
+ AEK_INVALID = 0,
+ AEK_NONE = 1,
+ AEK_CRC = 1 << 1,
+ AEK_CRYPTO = 1 << 2,
+ AEK_FP = 1 << 3,
+ AEK_SIMD = 1 << 4,
+ AEK_FP16 = 1 << 5,
+ AEK_PROFILE = 1 << 6,
+ AEK_RAS = 1 << 7,
+ AEK_LSE = 1 << 8,
+ AEK_SVE = 1 << 9,
+ AEK_DOTPROD = 1 << 10,
+ AEK_RCPC = 1 << 11,
+ AEK_RDM = 1 << 12,
+ AEK_SM4 = 1 << 13,
+ AEK_SHA3 = 1 << 14,
+ AEK_SHA2 = 1 << 15,
+ AEK_AES = 1 << 16,
+ AEK_FP16FML = 1 << 17,
+ AEK_RAND = 1 << 18,
+ AEK_MTE = 1 << 19,
+ 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_SVE2BITPERM = 1 << 27,
+ AEK_TME = 1 << 28,
+};
+
+enum class ArchKind {
+#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) ID,
+#include "AArch64TargetParser.def"
+};
+
+const ARM::ArchNames<ArchKind> AArch64ARCHNames[] = {
+#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, \
+ ARCH_BASE_EXT) \
+ {NAME, \
+ sizeof(NAME) - 1, \
+ CPU_ATTR, \
+ sizeof(CPU_ATTR) - 1, \
+ SUB_ARCH, \
+ sizeof(SUB_ARCH) - 1, \
+ ARM::FPUKind::ARCH_FPU, \
+ ARCH_BASE_EXT, \
+ AArch64::ArchKind::ID, \
+ ARCH_ATTR},
+#include "AArch64TargetParser.def"
+};
+
+const ARM::ExtName AArch64ARCHExtNames[] = {
+#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
+ {NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE},
+#include "AArch64TargetParser.def"
+};
+
+const ARM::CpuNames<ArchKind> AArch64CPUNames[] = {
+#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
+ {NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT},
+#include "AArch64TargetParser.def"
+};
+
+const ArchKind ArchKinds[] = {
+#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \
+ ArchKind::ID,
+#include "AArch64TargetParser.def"
+};
+
+// FIXME: These should be moved to TargetTuple once it exists
+bool getExtensionFeatures(unsigned Extensions,
+ std::vector<StringRef> &Features);
+bool getArchFeatures(ArchKind AK, std::vector<StringRef> &Features);
+
+StringRef getArchName(ArchKind AK);
+unsigned getArchAttr(ArchKind AK);
+StringRef getCPUAttr(ArchKind AK);
+StringRef getSubArch(ArchKind AK);
+StringRef getArchExtName(unsigned ArchExtKind);
+StringRef getArchExtFeature(StringRef ArchExt);
+
+// Information by Name
+unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
+unsigned getDefaultExtensions(StringRef CPU, ArchKind AK);
+StringRef getDefaultCPU(StringRef Arch);
+ArchKind getCPUArchKind(StringRef CPU);
+
+// Parser
+ArchKind parseArch(StringRef Arch);
+ArchExtKind parseArchExt(StringRef ArchExt);
+ArchKind parseCPUArch(StringRef CPU);
+// Used by target parser tests
+void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
+
+bool isX18ReservedByDefault(const Triple &TT);
+
+} // namespace AArch64
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/ARMAttributeParser.h b/third_party/llvm-project/include/llvm/Support/ARMAttributeParser.h
new file mode 100644
index 000000000..f6c39abb4
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/ARMAttributeParser.h
@@ -0,0 +1,141 @@
+//===--- ARMAttributeParser.h - ARM Attribute Information Printer ---------===//
+//
+// 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_ARMATTRIBUTEPARSER_H
+#define LLVM_SUPPORT_ARMATTRIBUTEPARSER_H
+
+#include "ARMBuildAttributes.h"
+#include "ScopedPrinter.h"
+
+#include <map>
+
+namespace llvm {
+class StringRef;
+
+class ARMAttributeParser {
+ ScopedPrinter *SW;
+
+ std::map<unsigned, unsigned> Attributes;
+
+ struct DisplayHandler {
+ ARMBuildAttrs::AttrType Attribute;
+ void (ARMAttributeParser::*Routine)(ARMBuildAttrs::AttrType,
+ const uint8_t *, uint32_t &);
+ };
+ static const DisplayHandler DisplayRoutines[];
+
+ uint64_t ParseInteger(const uint8_t *Data, uint32_t &Offset);
+ StringRef ParseString(const uint8_t *Data, uint32_t &Offset);
+
+ void IntegerAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void StringAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+
+ void PrintAttribute(unsigned Tag, unsigned Value, StringRef ValueDesc);
+
+ void CPU_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void CPU_arch_profile(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ARM_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void THUMB_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void FP_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void WMMX_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void Advanced_SIMD_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void MVE_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void PCS_config(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_R9_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_RW_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_RO_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_GOT_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_wchar_t(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_rounding(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_denormal(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_user_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_number_model(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_align_needed(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_align_preserved(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_enum_size(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_HardFP_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_VFP_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_WMMX_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_optimization_goals(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_optimization_goals(ARMBuildAttrs::AttrType Tag,
+ const uint8_t *Data, uint32_t &Offset);
+ void compatibility(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void CPU_unaligned_access(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void FP_HP_extension(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_16bit_format(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void MPextension_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void DIV_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void DSP_extension(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void T2EE_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void Virtualization_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void nodefaults(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+
+ void ParseAttributeList(const uint8_t *Data, uint32_t &Offset,
+ uint32_t Length);
+ void ParseIndexList(const uint8_t *Data, uint32_t &Offset,
+ SmallVectorImpl<uint8_t> &IndexList);
+ void ParseSubsection(const uint8_t *Data, uint32_t Length);
+public:
+ ARMAttributeParser(ScopedPrinter *SW) : SW(SW) {}
+
+ ARMAttributeParser() : SW(nullptr) { }
+
+ void Parse(ArrayRef<uint8_t> Section, bool isLittle);
+
+ bool hasAttribute(unsigned Tag) const {
+ return Attributes.count(Tag);
+ }
+
+ unsigned getAttributeValue(unsigned Tag) const {
+ return Attributes.find(Tag)->second;
+ }
+};
+
+}
+
+#endif
+
diff --git a/third_party/llvm-project/include/llvm/Support/ARMBuildAttributes.h b/third_party/llvm-project/include/llvm/Support/ARMBuildAttributes.h
new file mode 100644
index 000000000..90481eaa1
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/ARMBuildAttributes.h
@@ -0,0 +1,253 @@
+//===-- ARMBuildAttributes.h - ARM Build Attributes -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains enumerations and support routines for ARM build attributes
+// as defined in ARM ABI addenda document (ABI release 2.08).
+//
+// ELF for the ARM Architecture r2.09 - November 30, 2012
+//
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ARMBUILDATTRIBUTES_H
+#define LLVM_SUPPORT_ARMBUILDATTRIBUTES_H
+
+namespace llvm {
+class StringRef;
+
+namespace ARMBuildAttrs {
+
+enum SpecialAttr {
+ // This is for the .cpu asm attr. It translates into one or more
+ // AttrType (below) entries in the .ARM.attributes section in the ELF.
+ SEL_CPU
+};
+
+enum AttrType {
+ // Rest correspond to ELF/.ARM.attributes
+ File = 1,
+ CPU_raw_name = 4,
+ CPU_name = 5,
+ CPU_arch = 6,
+ CPU_arch_profile = 7,
+ ARM_ISA_use = 8,
+ THUMB_ISA_use = 9,
+ FP_arch = 10,
+ WMMX_arch = 11,
+ Advanced_SIMD_arch = 12,
+ PCS_config = 13,
+ ABI_PCS_R9_use = 14,
+ ABI_PCS_RW_data = 15,
+ ABI_PCS_RO_data = 16,
+ ABI_PCS_GOT_use = 17,
+ ABI_PCS_wchar_t = 18,
+ ABI_FP_rounding = 19,
+ ABI_FP_denormal = 20,
+ ABI_FP_exceptions = 21,
+ ABI_FP_user_exceptions = 22,
+ ABI_FP_number_model = 23,
+ ABI_align_needed = 24,
+ ABI_align_preserved = 25,
+ ABI_enum_size = 26,
+ ABI_HardFP_use = 27,
+ ABI_VFP_args = 28,
+ ABI_WMMX_args = 29,
+ ABI_optimization_goals = 30,
+ ABI_FP_optimization_goals = 31,
+ compatibility = 32,
+ CPU_unaligned_access = 34,
+ FP_HP_extension = 36,
+ ABI_FP_16bit_format = 38,
+ MPextension_use = 42, // recoded from 70 (ABI r2.08)
+ DIV_use = 44,
+ DSP_extension = 46,
+ MVE_arch = 48,
+ also_compatible_with = 65,
+ conformance = 67,
+ Virtualization_use = 68,
+
+ /// Legacy Tags
+ Section = 2, // deprecated (ABI r2.09)
+ Symbol = 3, // deprecated (ABI r2.09)
+ ABI_align8_needed = 24, // renamed to ABI_align_needed (ABI r2.09)
+ ABI_align8_preserved = 25, // renamed to ABI_align_preserved (ABI r2.09)
+ nodefaults = 64, // deprecated (ABI r2.09)
+ T2EE_use = 66, // deprecated (ABI r2.09)
+ MPextension_use_old = 70 // recoded to MPextension_use (ABI r2.08)
+};
+
+StringRef AttrTypeAsString(unsigned Attr, bool HasTagPrefix = true);
+StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix = true);
+int AttrTypeFromString(StringRef Tag);
+
+// Magic numbers for .ARM.attributes
+enum AttrMagic {
+ Format_Version = 0x41
+};
+
+// Legal Values for CPU_arch, (=6), uleb128
+enum CPUArch {
+ Pre_v4 = 0,
+ v4 = 1, // e.g. SA110
+ v4T = 2, // e.g. ARM7TDMI
+ v5T = 3, // e.g. ARM9TDMI
+ v5TE = 4, // e.g. ARM946E_S
+ v5TEJ = 5, // e.g. ARM926EJ_S
+ v6 = 6, // e.g. ARM1136J_S
+ v6KZ = 7, // e.g. ARM1176JZ_S
+ v6T2 = 8, // e.g. ARM1156T2_S
+ v6K = 9, // e.g. ARM1176JZ_S
+ v7 = 10, // e.g. Cortex A8, Cortex M3
+ v6_M = 11, // e.g. Cortex M1
+ v6S_M = 12, // v6_M with the System extensions
+ v7E_M = 13, // v7_M with DSP extensions
+ v8_A = 14, // v8_A AArch32
+ 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
+ Not_Applicable = 0, // pre v7, or cross-profile code
+ ApplicationProfile = (0x41), // 'A' (e.g. for Cortex A8)
+ RealTimeProfile = (0x52), // 'R' (e.g. for Cortex R4)
+ MicroControllerProfile = (0x4D), // 'M' (e.g. for Cortex M3)
+ SystemProfile = (0x53) // 'S' Application or real-time profile
+};
+
+// The following have a lot of common use cases
+enum {
+ Not_Allowed = 0,
+ Allowed = 1,
+
+ // Tag_ARM_ISA_use (=8), uleb128
+
+ // Tag_THUMB_ISA_use, (=9), uleb128
+ AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions)
+ AllowThumbDerived = 3, // Thumb allowed, derived from arch/profile
+
+ // Tag_FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10)
+ AllowFPv2 = 2, // v2 FP ISA permitted (implies use of the v1 FP ISA)
+ AllowFPv3A = 3, // v3 FP ISA permitted (implies use of the v2 FP ISA)
+ AllowFPv3B = 4, // v3 FP ISA permitted, but only D0-D15, S0-S31
+ AllowFPv4A = 5, // v4 FP ISA permitted (implies use of v3 FP ISA)
+ AllowFPv4B = 6, // v4 FP ISA was permitted, but only D0-D15, S0-S31
+ AllowFPARMv8A = 7, // Use of the ARM v8-A FP ISA was permitted
+ AllowFPARMv8B = 8, // Use of the ARM v8-A FP ISA was permitted, but only
+ // D0-D15, S0-S31
+
+ // Tag_WMMX_arch, (=11), uleb128
+ AllowWMMXv1 = 1, // The user permitted this entity to use WMMX v1
+ AllowWMMXv2 = 2, // The user permitted this entity to use WMMX v2
+
+ // Tag_Advanced_SIMD_arch, (=12), uleb128
+ AllowNeon = 1, // SIMDv1 was permitted
+ AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations)
+ AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted
+ 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
+ R9IsTLSPointer = 2, // R9 used as a thread local storage pointer
+ R9Reserved = 3, // R9 not used by code associated with attributed entity
+
+ // Tag_ABI_PCS_RW_data, (=15), uleb128
+ AddressRWPCRel = 1, // Address RW static data PC-relative
+ AddressRWSBRel = 2, // Address RW static data SB-relative
+ AddressRWNone = 3, // No RW static data permitted
+
+ // Tag_ABI_PCS_RO_data, (=14), uleb128
+ AddressROPCRel = 1, // Address RO static data PC-relative
+ AddressRONone = 2, // No RO static data permitted
+
+ // Tag_ABI_PCS_GOT_use, (=17), uleb128
+ AddressDirect = 1, // Address imported data directly
+ AddressGOT = 2, // Address imported data indirectly (via GOT)
+
+ // Tag_ABI_PCS_wchar_t, (=18), uleb128
+ WCharProhibited = 0, // wchar_t is not used
+ WCharWidth2Bytes = 2, // sizeof(wchar_t) == 2
+ WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4
+
+ // Tag_ABI_align_needed, (=24), uleb128
+ Align8Byte = 1,
+ Align4Byte = 2,
+ AlignReserved = 3,
+
+ // Tag_ABI_align_needed, (=25), uleb128
+ AlignNotPreserved = 0,
+ AlignPreserve8Byte = 1,
+ AlignPreserveAll = 2,
+
+ // Tag_ABI_FP_denormal, (=20), uleb128
+ PositiveZero = 0,
+ IEEEDenormals = 1,
+ PreserveFPSign = 2, // sign when flushed-to-zero is preserved
+
+ // Tag_ABI_FP_number_model, (=23), uleb128
+ AllowIEEENormal = 1,
+ AllowRTABI = 2, // numbers, infinities, and one quiet NaN (see [RTABI])
+ AllowIEEE754 = 3, // this code to use all the IEEE 754-defined FP encodings
+
+ // Tag_ABI_enum_size, (=26), uleb128
+ EnumProhibited = 0, // The user prohibited the use of enums when building
+ // this entity.
+ EnumSmallest = 1, // Enum is smallest container big enough to hold all
+ // values.
+ Enum32Bit = 2, // Enum is at least 32 bits.
+ Enum32BitABI = 3, // Every enumeration visible across an ABI-complying
+ // interface contains a value needing 32 bits to encode
+ // it; other enums can be containerized.
+
+ // Tag_ABI_HardFP_use, (=27), uleb128
+ HardFPImplied = 0, // FP use should be implied by Tag_FP_arch
+ HardFPSinglePrecision = 1, // Single-precision only
+
+ // Tag_ABI_VFP_args, (=28), uleb128
+ BaseAAPCS = 0,
+ HardFPAAPCS = 1,
+ ToolChainFPPCS = 2,
+ CompatibleFPAAPCS = 3,
+
+ // Tag_FP_HP_extension, (=36), uleb128
+ AllowHPFP = 1, // Allow use of Half Precision FP
+
+ // Tag_FP_16bit_format, (=38), uleb128
+ FP16FormatIEEE = 1,
+ FP16VFP3 = 2,
+
+ // Tag_MPextension_use, (=42), uleb128
+ AllowMP = 1, // Allow use of MP extensions
+
+ // Tag_DIV_use, (=44), uleb128
+ // Note: AllowDIVExt must be emitted if and only if the permission to use
+ // hardware divide cannot be conveyed using AllowDIVIfExists or DisallowDIV
+ AllowDIVIfExists = 0, // Allow hardware divide if available in arch, or no
+ // info exists.
+ DisallowDIV = 1, // Hardware divide explicitly disallowed.
+ AllowDIVExt = 2, // Allow hardware divide as optional architecture
+ // extension above the base arch specified by
+ // Tag_CPU_arch and Tag_CPU_arch_profile.
+
+ // Tag_Virtualization_use, (=68), uleb128
+ AllowTZ = 1,
+ AllowVirtualization = 2,
+ AllowTZVirtualization = 3
+};
+
+} // namespace ARMBuildAttrs
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/ARMTargetParser.def b/third_party/llvm-project/include/llvm/Support/ARMTargetParser.def
new file mode 100644
index 000000000..7f03d9a13
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/ARMTargetParser.def
@@ -0,0 +1,293 @@
+//===- ARMTargetParser.def - ARM target parsing defines ---------*- 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 defines to build up the ARM target parser's logic.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+#ifndef ARM_FPU
+#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION)
+#endif
+ARM_FPU("invalid", FK_INVALID, FPUVersion::NONE, NeonSupportLevel::None, FPURestriction::None)
+ARM_FPU("none", FK_NONE, FPUVersion::NONE, NeonSupportLevel::None, FPURestriction::None)
+ARM_FPU("vfp", FK_VFP, FPUVersion::VFPV2, NeonSupportLevel::None, FPURestriction::None)
+ARM_FPU("vfpv2", FK_VFPV2, FPUVersion::VFPV2, NeonSupportLevel::None, FPURestriction::None)
+ARM_FPU("vfpv3", FK_VFPV3, FPUVersion::VFPV3, NeonSupportLevel::None, FPURestriction::None)
+ARM_FPU("vfpv3-fp16", FK_VFPV3_FP16, FPUVersion::VFPV3_FP16, NeonSupportLevel::None, FPURestriction::None)
+ARM_FPU("vfpv3-d16", FK_VFPV3_D16, FPUVersion::VFPV3, NeonSupportLevel::None, FPURestriction::D16)
+ARM_FPU("vfpv3-d16-fp16", FK_VFPV3_D16_FP16, FPUVersion::VFPV3_FP16, NeonSupportLevel::None, FPURestriction::D16)
+ARM_FPU("vfpv3xd", FK_VFPV3XD, FPUVersion::VFPV3, NeonSupportLevel::None, FPURestriction::SP_D16)
+ARM_FPU("vfpv3xd-fp16", FK_VFPV3XD_FP16, FPUVersion::VFPV3_FP16, NeonSupportLevel::None, FPURestriction::SP_D16)
+ARM_FPU("vfpv4", FK_VFPV4, FPUVersion::VFPV4, NeonSupportLevel::None, FPURestriction::None)
+ARM_FPU("vfpv4-d16", FK_VFPV4_D16, FPUVersion::VFPV4, NeonSupportLevel::None, FPURestriction::D16)
+ARM_FPU("fpv4-sp-d16", FK_FPV4_SP_D16, FPUVersion::VFPV4, NeonSupportLevel::None, FPURestriction::SP_D16)
+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)
+ARM_FPU("neon-fp-armv8", FK_NEON_FP_ARMV8, FPUVersion::VFPV5, NeonSupportLevel::Neon, FPURestriction::None)
+ARM_FPU("crypto-neon-fp-armv8", FK_CRYPTO_NEON_FP_ARMV8, FPUVersion::VFPV5, NeonSupportLevel::Crypto,
+ FPURestriction::None)
+ARM_FPU("softvfp", FK_SOFTVFP, FPUVersion::NONE, NeonSupportLevel::None, FPURestriction::None)
+#undef ARM_FPU
+
+#ifndef ARM_ARCH
+#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)
+#endif
+ARM_ARCH("invalid", INVALID, "", "",
+ ARMBuildAttrs::CPUArch::Pre_v4, FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv2", ARMV2, "2", "v2", ARMBuildAttrs::CPUArch::Pre_v4,
+ FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv2a", ARMV2A, "2A", "v2a", ARMBuildAttrs::CPUArch::Pre_v4,
+ FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv3", ARMV3, "3", "v3", ARMBuildAttrs::CPUArch::Pre_v4,
+ FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv3m", ARMV3M, "3M", "v3m", ARMBuildAttrs::CPUArch::Pre_v4,
+ FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv4", ARMV4, "4", "v4", ARMBuildAttrs::CPUArch::v4,
+ FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv4t", ARMV4T, "4T", "v4t", ARMBuildAttrs::CPUArch::v4T,
+ FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv5t", ARMV5T, "5T", "v5", ARMBuildAttrs::CPUArch::v5T,
+ FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv5te", ARMV5TE, "5TE", "v5e", ARMBuildAttrs::CPUArch::v5TE,
+ FK_NONE, ARM::AEK_DSP)
+ARM_ARCH("armv5tej", ARMV5TEJ, "5TEJ", "v5e", ARMBuildAttrs::CPUArch::v5TEJ,
+ FK_NONE, ARM::AEK_DSP)
+ARM_ARCH("armv6", ARMV6, "6", "v6", ARMBuildAttrs::CPUArch::v6,
+ FK_VFPV2, ARM::AEK_DSP)
+ARM_ARCH("armv6k", ARMV6K, "6K", "v6k", ARMBuildAttrs::CPUArch::v6K,
+ FK_VFPV2, ARM::AEK_DSP)
+ARM_ARCH("armv6t2", ARMV6T2, "6T2", "v6t2", ARMBuildAttrs::CPUArch::v6T2,
+ FK_NONE, ARM::AEK_DSP)
+ARM_ARCH("armv6kz", ARMV6KZ, "6KZ", "v6kz", ARMBuildAttrs::CPUArch::v6KZ,
+ FK_VFPV2, (ARM::AEK_SEC | ARM::AEK_DSP))
+ARM_ARCH("armv6-m", ARMV6M, "6-M", "v6m", ARMBuildAttrs::CPUArch::v6_M,
+ FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv7-a", ARMV7A, "7-A", "v7", ARMBuildAttrs::CPUArch::v7,
+ FK_NEON, ARM::AEK_DSP)
+ARM_ARCH("armv7ve", ARMV7VE, "7VE", "v7ve", ARMBuildAttrs::CPUArch::v7,
+ FK_NEON, (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
+ ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP))
+ARM_ARCH("armv7-r", ARMV7R, "7-R", "v7r", ARMBuildAttrs::CPUArch::v7,
+ FK_NONE, (ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP))
+ARM_ARCH("armv7-m", ARMV7M, "7-M", "v7m", ARMBuildAttrs::CPUArch::v7,
+ FK_NONE, ARM::AEK_HWDIVTHUMB)
+ARM_ARCH("armv7e-m", ARMV7EM, "7E-M", "v7em", ARMBuildAttrs::CPUArch::v7E_M,
+ FK_NONE, (ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP))
+ARM_ARCH("armv8-a", ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A,
+ FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC))
+ARM_ARCH("armv8.1-a", ARMV8_1A, "8.1-A", "v8.1a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC))
+ARM_ARCH("armv8.2-a", ARMV8_2A, "8.2-A", "v8.2a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS))
+ARM_ARCH("armv8.3-a", ARMV8_3A, "8.3-A", "v8.3a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS))
+ARM_ARCH("armv8.4-a", ARMV8_4A, "8.4-A", "v8.4a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS |
+ ARM::AEK_DOTPROD))
+ARM_ARCH("armv8.5-a", ARMV8_5A, "8.5-A", "v8.5a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS |
+ ARM::AEK_DOTPROD))
+ARM_ARCH("armv8-r", ARMV8R, "8-R", "v8r", ARMBuildAttrs::CPUArch::v8_R,
+ FK_NEON_FP_ARMV8,
+ (ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
+ ARM::AEK_DSP | ARM::AEK_CRC))
+ARM_ARCH("armv8-m.base", ARMV8MBaseline, "8-M.Baseline", "v8m.base",
+ 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)
+ARM_ARCH("iwmmxt2", IWMMXT2, "iwmmxt2", "", ARMBuildAttrs::CPUArch::v5TE,
+ FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("xscale", XSCALE, "xscale", "v5e", ARMBuildAttrs::CPUArch::v5TE,
+ FK_NONE, ARM::AEK_NONE)
+ARM_ARCH("armv7s", ARMV7S, "7-S", "v7s", ARMBuildAttrs::CPUArch::v7,
+ FK_NEON_VFPV4, ARM::AEK_DSP)
+ARM_ARCH("armv7k", ARMV7K, "7-K", "v7k", ARMBuildAttrs::CPUArch::v7,
+ FK_NONE, ARM::AEK_DSP)
+#undef ARM_ARCH
+
+#ifndef ARM_ARCH_EXT_NAME
+#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE)
+#endif
+// FIXME: This would be nicer were it tablegen
+ARM_ARCH_EXT_NAME("invalid", ARM::AEK_INVALID, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("none", ARM::AEK_NONE, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("crc", ARM::AEK_CRC, "+crc", "-crc")
+ARM_ARCH_EXT_NAME("crypto", ARM::AEK_CRYPTO, "+crypto","-crypto")
+ARM_ARCH_EXT_NAME("sha2", ARM::AEK_SHA2, "+sha2", "-sha2")
+ARM_ARCH_EXT_NAME("aes", ARM::AEK_AES, "+aes", "-aes")
+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("fp.dp", ARM::AEK_FP_DP, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("mve", (ARM::AEK_DSP | ARM::AEK_SIMD), "+mve", "-mve")
+ARM_ARCH_EXT_NAME("mve.fp", (ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP), "+mve.fp", "-mve.fp")
+ARM_ARCH_EXT_NAME("idiv", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB), nullptr, nullptr)
+ARM_ARCH_EXT_NAME("mp", ARM::AEK_MP, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("simd", ARM::AEK_SIMD, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("sec", ARM::AEK_SEC, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("virt", ARM::AEK_VIRT, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("fp16", ARM::AEK_FP16, "+fullfp16", "-fullfp16")
+ARM_ARCH_EXT_NAME("ras", ARM::AEK_RAS, "+ras", "-ras")
+ARM_ARCH_EXT_NAME("os", ARM::AEK_OS, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("iwmmxt", ARM::AEK_IWMMXT, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("iwmmxt2", ARM::AEK_IWMMXT2, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("maverick", ARM::AEK_MAVERICK, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("xscale", ARM::AEK_XSCALE, nullptr, nullptr)
+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
+#define ARM_HW_DIV_NAME(NAME, ID)
+#endif
+ARM_HW_DIV_NAME("invalid", ARM::AEK_INVALID)
+ARM_HW_DIV_NAME("none", ARM::AEK_NONE)
+ARM_HW_DIV_NAME("thumb", ARM::AEK_HWDIVTHUMB)
+ARM_HW_DIV_NAME("arm", ARM::AEK_HWDIVARM)
+ARM_HW_DIV_NAME("arm,thumb", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB))
+#undef ARM_HW_DIV_NAME
+
+#ifndef ARM_CPU_NAME
+#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)
+#endif
+ARM_CPU_NAME("arm2", ARMV2, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm3", ARMV2A, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm6", ARMV3, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm7m", ARMV3M, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm8", ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm810", ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm", ARMV4, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm110", ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm1100", ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("strongarm1110", ARMV4, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm7tdmi", ARMV4T, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm7tdmi-s", ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm710t", ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm720t", ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9", ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9tdmi", ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm920", ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm920t", ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm922t", ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9312", ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm940t", ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("ep9312", ARMV4T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm10tdmi", ARMV5T, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1020t", ARMV5T, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm9e", ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm946e-s", ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm966e-s", ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm968e-s", ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm10e", ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1020e", ARMV5TE, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1022e", ARMV5TE, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm926ej-s", ARMV5TEJ, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1136j-s", ARMV6, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1136jf-s", ARMV6, FK_VFPV2, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1136jz-s", ARMV6, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("mpcore", ARMV6K, FK_VFPV2, true, ARM::AEK_NONE)
+ARM_CPU_NAME("mpcorenovfp", ARMV6K, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1176jz-s", ARMV6KZ, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1176jzf-s", ARMV6KZ, FK_VFPV2, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1156t2-s", ARMV6T2, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("arm1156t2f-s", ARMV6T2, FK_VFPV2, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m0", ARMV6M, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m0plus", ARMV6M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m1", ARMV6M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("sc000", ARMV6M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-a5", ARMV7A, FK_NEON_VFPV4, false,
+ (ARM::AEK_SEC | ARM::AEK_MP))
+ARM_CPU_NAME("cortex-a7", ARMV7A, FK_NEON_VFPV4, false,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB))
+ARM_CPU_NAME("cortex-a8", ARMV7A, FK_NEON, false, ARM::AEK_SEC)
+ARM_CPU_NAME("cortex-a9", ARMV7A, FK_NEON_FP16, false, (ARM::AEK_SEC | ARM::AEK_MP))
+ARM_CPU_NAME("cortex-a12", ARMV7A, FK_NEON_VFPV4, false,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB))
+ARM_CPU_NAME("cortex-a15", ARMV7A, FK_NEON_VFPV4, false,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB))
+ARM_CPU_NAME("cortex-a17", ARMV7A, FK_NEON_VFPV4, false,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB))
+ARM_CPU_NAME("krait", ARMV7A, FK_NEON_VFPV4, false,
+ (ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB))
+ARM_CPU_NAME("cortex-r4", ARMV7R, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-r4f", ARMV7R, FK_VFPV3_D16, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-r5", ARMV7R, FK_VFPV3_D16, false,
+ (ARM::AEK_MP | ARM::AEK_HWDIVARM))
+ARM_CPU_NAME("cortex-r7", ARMV7R, FK_VFPV3_D16_FP16, false,
+ (ARM::AEK_MP | ARM::AEK_HWDIVARM))
+ARM_CPU_NAME("cortex-r8", ARMV7R, FK_VFPV3_D16_FP16, false,
+ (ARM::AEK_MP | ARM::AEK_HWDIVARM))
+ARM_CPU_NAME("cortex-r52", ARMV8R, FK_NEON_FP_ARMV8, true, ARM::AEK_NONE)
+ARM_CPU_NAME("sc300", ARMV7M, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m3", ARMV7M, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m4", ARMV7EM, FK_FPV4_SP_D16, true, ARM::AEK_NONE)
+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)
+ARM_CPU_NAME("cortex-a55", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_FP16 | ARM::AEK_DOTPROD))
+ARM_CPU_NAME("cortex-a57", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("cortex-a72", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+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("neoverse-n1", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_FP16 | ARM::AEK_DOTPROD))
+ARM_CPU_NAME("cyclone", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("exynos-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)
+ARM_CPU_NAME("xscale", XSCALE, FK_NONE, true, ARM::AEK_NONE)
+ARM_CPU_NAME("swift", ARMV7S, FK_NEON_VFPV4, true,
+ (ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB))
+// Invalid CPU
+ARM_CPU_NAME("invalid", INVALID, FK_INVALID, true, ARM::AEK_INVALID)
+#undef ARM_CPU_NAME
diff --git a/third_party/llvm-project/include/llvm/Support/ARMTargetParser.h b/third_party/llvm-project/include/llvm/Support/ARMTargetParser.h
new file mode 100644
index 000000000..02d4c9751
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/ARMTargetParser.h
@@ -0,0 +1,267 @@
+//===-- ARMTargetParser - Parser for ARM target features --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise ARM hardware features
+// such as FPU/CPU/ARCH/extensions and specific support such as HWDIV.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ARMTARGETPARSER_H
+#define LLVM_SUPPORT_ARMTARGETPARSER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/ARMBuildAttributes.h"
+#include <vector>
+
+namespace llvm {
+namespace ARM {
+
+// Arch extension modifiers for CPUs.
+// Note that this is not the same as the AArch64 list
+enum ArchExtKind : unsigned {
+ AEK_INVALID = 0,
+ AEK_NONE = 1,
+ AEK_CRC = 1 << 1,
+ AEK_CRYPTO = 1 << 2,
+ AEK_FP = 1 << 3,
+ AEK_HWDIVTHUMB = 1 << 4,
+ AEK_HWDIVARM = 1 << 5,
+ AEK_MP = 1 << 6,
+ AEK_SIMD = 1 << 7,
+ AEK_SEC = 1 << 8,
+ AEK_VIRT = 1 << 9,
+ AEK_DSP = 1 << 10,
+ AEK_FP16 = 1 << 11,
+ AEK_RAS = 1 << 12,
+ AEK_DOTPROD = 1 << 13,
+ AEK_SHA2 = 1 << 14,
+ AEK_AES = 1 << 15,
+ AEK_FP16FML = 1 << 16,
+ AEK_SB = 1 << 17,
+ AEK_FP_DP = 1 << 18,
+ AEK_LOB = 1 << 19,
+ // Unsupported extensions.
+ AEK_OS = 0x8000000,
+ AEK_IWMMXT = 0x10000000,
+ AEK_IWMMXT2 = 0x20000000,
+ AEK_MAVERICK = 0x40000000,
+ AEK_XSCALE = 0x80000000,
+};
+
+// List of Arch Extension names.
+// FIXME: TableGen this.
+struct ExtName {
+ const char *NameCStr;
+ size_t NameLength;
+ unsigned ID;
+ const char *Feature;
+ const char *NegFeature;
+
+ StringRef getName() const { return StringRef(NameCStr, NameLength); }
+};
+
+const ExtName ARCHExtNames[] = {
+#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
+ {NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE},
+#include "ARMTargetParser.def"
+};
+
+// List of HWDiv names (use getHWDivSynonym) and which architectural
+// features they correspond to (use getHWDivFeatures).
+// FIXME: TableGen this.
+const struct {
+ const char *NameCStr;
+ size_t NameLength;
+ unsigned ID;
+
+ StringRef getName() const { return StringRef(NameCStr, NameLength); }
+} HWDivNames[] = {
+#define ARM_HW_DIV_NAME(NAME, ID) {NAME, sizeof(NAME) - 1, ID},
+#include "ARMTargetParser.def"
+};
+
+// Arch names.
+enum class ArchKind {
+#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) ID,
+#include "ARMTargetParser.def"
+};
+
+// List of CPU names and their arches.
+// The same CPU can have multiple arches and can be default on multiple arches.
+// When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
+// When this becomes table-generated, we'd probably need two tables.
+// FIXME: TableGen this.
+template <typename T> struct CpuNames {
+ const char *NameCStr;
+ size_t NameLength;
+ T ArchID;
+ bool Default; // is $Name the default CPU for $ArchID ?
+ unsigned DefaultExtensions;
+
+ StringRef getName() const { return StringRef(NameCStr, NameLength); }
+};
+
+const CpuNames<ArchKind> CPUNames[] = {
+#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
+ {NAME, sizeof(NAME) - 1, ARM::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT},
+#include "ARMTargetParser.def"
+};
+
+// FPU names.
+enum FPUKind {
+#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) KIND,
+#include "ARMTargetParser.def"
+ FK_LAST
+};
+
+// FPU Version
+enum class FPUVersion {
+ NONE,
+ VFPV2,
+ VFPV3,
+ VFPV3_FP16,
+ VFPV4,
+ VFPV5,
+ VFPV5_FULLFP16,
+};
+
+// An FPU name restricts the FPU in one of three ways:
+enum class FPURestriction {
+ None = 0, ///< No restriction
+ D16, ///< Only 16 D registers
+ SP_D16 ///< Only single-precision instructions, with 16 D registers
+};
+
+// An FPU name implies one of three levels of Neon support:
+enum class NeonSupportLevel {
+ None = 0, ///< No Neon
+ Neon, ///< Neon
+ Crypto ///< Neon with Crypto
+};
+
+// ISA kinds.
+enum class ISAKind { INVALID = 0, ARM, THUMB, AARCH64 };
+
+// Endianness
+// FIXME: BE8 vs. BE32?
+enum class EndianKind { INVALID = 0, LITTLE, BIG };
+
+// v6/v7/v8 Profile
+enum class ProfileKind { INVALID = 0, A, R, M };
+
+// List of canonical FPU names (use getFPUSynonym) and which architectural
+// features they correspond to (use getFPUFeatures).
+// FIXME: TableGen this.
+// The entries must appear in the order listed in ARM::FPUKind for correct
+// indexing
+struct FPUName {
+ const char *NameCStr;
+ size_t NameLength;
+ FPUKind ID;
+ FPUVersion FPUVer;
+ NeonSupportLevel NeonSupport;
+ FPURestriction Restriction;
+
+ StringRef getName() const { return StringRef(NameCStr, NameLength); }
+};
+
+static const FPUName FPUNames[] = {
+#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
+ {NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION},
+#include "llvm/Support/ARMTargetParser.def"
+};
+
+// List of canonical arch names (use getArchSynonym).
+// This table also provides the build attribute fields for CPU arch
+// and Arch ID, according to the Addenda to the ARM ABI, chapters
+// 2.4 and 2.3.5.2 respectively.
+// FIXME: SubArch values were simplified to fit into the expectations
+// of the triples and are not conforming with their official names.
+// Check to see if the expectation should be changed.
+// FIXME: TableGen this.
+template <typename T> struct ArchNames {
+ const char *NameCStr;
+ size_t NameLength;
+ const char *CPUAttrCStr;
+ size_t CPUAttrLength;
+ const char *SubArchCStr;
+ size_t SubArchLength;
+ unsigned DefaultFPU;
+ unsigned ArchBaseExtensions;
+ T ID;
+ ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
+
+ StringRef getName() const { return StringRef(NameCStr, NameLength); }
+
+ // CPU class in build attributes.
+ StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
+
+ // Sub-Arch name.
+ StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
+};
+
+static const ArchNames<ArchKind> ARCHNames[] = {
+#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, \
+ ARCH_BASE_EXT) \
+ {NAME, sizeof(NAME) - 1, \
+ CPU_ATTR, sizeof(CPU_ATTR) - 1, \
+ SUB_ARCH, sizeof(SUB_ARCH) - 1, \
+ ARCH_FPU, ARCH_BASE_EXT, \
+ ArchKind::ID, ARCH_ATTR},
+#include "llvm/Support/ARMTargetParser.def"
+};
+
+// Information by ID
+StringRef getFPUName(unsigned FPUKind);
+FPUVersion getFPUVersion(unsigned FPUKind);
+NeonSupportLevel getFPUNeonSupportLevel(unsigned FPUKind);
+FPURestriction getFPURestriction(unsigned FPUKind);
+
+// FIXME: These should be moved to TargetTuple once it exists
+bool getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features);
+bool getHWDivFeatures(unsigned HWDivKind, std::vector<StringRef> &Features);
+bool getExtensionFeatures(unsigned Extensions,
+ std::vector<StringRef> &Features);
+
+StringRef getArchName(ArchKind AK);
+unsigned getArchAttr(ArchKind AK);
+StringRef getCPUAttr(ArchKind AK);
+StringRef getSubArch(ArchKind AK);
+StringRef getArchExtName(unsigned ArchExtKind);
+StringRef getArchExtFeature(StringRef ArchExt);
+bool appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK, StringRef ArchExt,
+ std::vector<StringRef> &Features);
+StringRef getHWDivName(unsigned HWDivKind);
+
+// Information by Name
+unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
+unsigned getDefaultExtensions(StringRef CPU, ArchKind AK);
+StringRef getDefaultCPU(StringRef Arch);
+StringRef getCanonicalArchName(StringRef Arch);
+StringRef getFPUSynonym(StringRef FPU);
+StringRef getArchSynonym(StringRef Arch);
+
+// Parser
+unsigned parseHWDiv(StringRef HWDiv);
+unsigned parseFPU(StringRef FPU);
+ArchKind parseArch(StringRef Arch);
+unsigned parseArchExt(StringRef ArchExt);
+ArchKind parseCPUArch(StringRef CPU);
+ISAKind parseArchISA(StringRef Arch);
+EndianKind parseArchEndian(StringRef Arch);
+ProfileKind parseArchProfile(StringRef Arch);
+unsigned parseArchVersion(StringRef Arch);
+
+void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
+StringRef computeDefaultTargetABI(const Triple &TT, StringRef CPU);
+
+} // namespace ARM
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/AlignOf.h b/third_party/llvm-project/include/llvm/Support/AlignOf.h
new file mode 100644
index 000000000..eb42542b7
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/AlignOf.h
@@ -0,0 +1,55 @@
+//===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AlignedCharArrayUnion class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ALIGNOF_H
+#define LLVM_SUPPORT_ALIGNOF_H
+
+#include "llvm/Support/Compiler.h"
+#include <cstddef>
+
+namespace llvm {
+
+namespace detail {
+
+template <typename T, typename... Ts> class AlignerImpl {
+ T t;
+ AlignerImpl<Ts...> rest;
+ AlignerImpl() = delete;
+};
+
+template <typename T> class AlignerImpl<T> {
+ T t;
+ AlignerImpl() = delete;
+};
+
+template <typename T, typename... Ts> union SizerImpl {
+ char arr[sizeof(T)];
+ SizerImpl<Ts...> rest;
+};
+
+template <typename T> union SizerImpl<T> { char arr[sizeof(T)]; };
+} // end namespace detail
+
+/// A suitably aligned and sized character array member which can hold elements
+/// of any type.
+///
+/// These types may be arrays, structs, or any other types. This exposes a
+/// `buffer` member which can be used as suitable storage for a placement new of
+/// any of these types.
+template <typename T, typename... Ts> struct AlignedCharArrayUnion {
+ alignas(::llvm::detail::AlignerImpl<T, Ts...>) char buffer[sizeof(
+ llvm::detail::SizerImpl<T, Ts...>)];
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_ALIGNOF_H
diff --git a/third_party/llvm-project/include/llvm/Support/Alignment.h b/third_party/llvm-project/include/llvm/Support/Alignment.h
new file mode 100644
index 000000000..72fad87dd
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Alignment.h
@@ -0,0 +1,403 @@
+//===-- llvm/Support/Alignment.h - Useful alignment functions ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains types to represent alignments.
+// They are instrumented to guarantee some invariants are preserved and prevent
+// invalid manipulations.
+//
+// - Align represents an alignment in bytes, it is always set and always a valid
+// power of two, its minimum value is 1 which means no alignment requirements.
+//
+// - MaybeAlign is an optional type, it may be undefined or set. When it's set
+// you can get the underlying Align type by using the getValue() method.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ALIGNMENT_H_
+#define LLVM_SUPPORT_ALIGNMENT_H_
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <limits>
+
+namespace llvm {
+
+#define ALIGN_CHECK_ISPOSITIVE(decl) \
+ assert(decl > 0 && (#decl " should be defined"))
+#define ALIGN_CHECK_ISSET(decl) \
+ assert(decl.hasValue() && (#decl " should be defined"))
+
+/// This struct is a compact representation of a valid (non-zero power of two)
+/// alignment.
+/// It is suitable for use as static global constants.
+struct Align {
+private:
+ uint8_t ShiftValue = 0; /// The log2 of the required alignment.
+ /// ShiftValue is less than 64 by construction.
+
+ friend struct MaybeAlign;
+ friend unsigned Log2(Align);
+ friend bool operator==(Align Lhs, Align Rhs);
+ friend bool operator!=(Align Lhs, Align Rhs);
+ friend bool operator<=(Align Lhs, Align Rhs);
+ friend bool operator>=(Align Lhs, Align Rhs);
+ friend bool operator<(Align Lhs, Align Rhs);
+ friend bool operator>(Align Lhs, Align Rhs);
+ friend unsigned encode(struct MaybeAlign A);
+ friend struct MaybeAlign decodeMaybeAlign(unsigned Value);
+
+ /// A trivial type to allow construction of constexpr Align.
+ /// This is currently needed to workaround a bug in GCC 5.3 which prevents
+ /// definition of constexpr assign operators.
+ /// https://stackoverflow.com/questions/46756288/explicitly-defaulted-function-cannot-be-declared-as-constexpr-because-the-implic
+ /// FIXME: Remove this, make all assign operators constexpr and introduce user
+ /// defined literals when we don't have to support GCC 5.3 anymore.
+ /// https://llvm.org/docs/GettingStarted.html#getting-a-modern-host-c-toolchain
+ struct LogValue {
+ uint8_t Log;
+ };
+
+public:
+ /// Default is byte-aligned.
+ constexpr Align() = default;
+ /// Do not perform checks in case of copy/move construct/assign, because the
+ /// checks have been performed when building `Other`.
+ constexpr Align(const Align &Other) = default;
+ constexpr Align(Align &&Other) = default;
+ Align &operator=(const Align &Other) = default;
+ Align &operator=(Align &&Other) = default;
+
+ explicit Align(uint64_t Value) {
+ assert(Value > 0 && "Value must not be 0");
+ assert(llvm::isPowerOf2_64(Value) && "Alignment is not a power of 2");
+ ShiftValue = Log2_64(Value);
+ assert(ShiftValue < 64 && "Broken invariant");
+ }
+
+ /// This is a hole in the type system and should not be abused.
+ /// Needed to interact with C for instance.
+ uint64_t value() const { return uint64_t(1) << ShiftValue; }
+
+ /// Returns a default constructed Align which corresponds to no alignment.
+ /// This is useful to test for unalignment as it conveys clear semantic.
+ /// `if (A != Align::None())`
+ /// would be better than
+ /// `if (A > Align(1))`
+ constexpr static const Align None() { return Align(); }
+
+ /// Allow constructions of constexpr Align.
+ template <size_t kValue> constexpr static LogValue Constant() {
+ return LogValue{static_cast<uint8_t>(CTLog2<kValue>())};
+ }
+
+ /// Allow constructions of constexpr Align from types.
+ /// Compile time equivalent to Align(alignof(T)).
+ template <typename T> constexpr static LogValue Of() {
+ return Constant<std::alignment_of<T>::value>();
+ }
+
+ /// Constexpr constructor from LogValue type.
+ constexpr Align(LogValue CA) : ShiftValue(CA.Log) {}
+};
+
+/// Treats the value 0 as a 1, so Align is always at least 1.
+inline Align assumeAligned(uint64_t Value) {
+ return Value ? Align(Value) : Align();
+}
+
+/// This struct is a compact representation of a valid (power of two) or
+/// undefined (0) alignment.
+struct MaybeAlign : public llvm::Optional<Align> {
+private:
+ using UP = llvm::Optional<Align>;
+
+public:
+ /// Default is undefined.
+ MaybeAlign() = default;
+ /// Do not perform checks in case of copy/move construct/assign, because the
+ /// checks have been performed when building `Other`.
+ MaybeAlign(const MaybeAlign &Other) = default;
+ MaybeAlign &operator=(const MaybeAlign &Other) = default;
+ MaybeAlign(MaybeAlign &&Other) = default;
+ MaybeAlign &operator=(MaybeAlign &&Other) = default;
+
+ /// Use llvm::Optional<Align> constructor.
+ using UP::UP;
+
+ explicit MaybeAlign(uint64_t Value) {
+ assert((Value == 0 || llvm::isPowerOf2_64(Value)) &&
+ "Alignment is neither 0 nor a power of 2");
+ if (Value)
+ emplace(Value);
+ }
+
+ /// For convenience, returns a valid alignment or 1 if undefined.
+ Align valueOrOne() const { return hasValue() ? getValue() : Align(); }
+};
+
+/// Checks that SizeInBytes is a multiple of the alignment.
+inline bool isAligned(Align Lhs, uint64_t SizeInBytes) {
+ return SizeInBytes % Lhs.value() == 0;
+}
+
+/// Checks that SizeInBytes is a multiple of the alignment.
+/// Returns false if the alignment is undefined.
+inline bool isAligned(MaybeAlign Lhs, uint64_t SizeInBytes) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return SizeInBytes % (*Lhs).value() == 0;
+}
+
+/// Checks that Addr is a multiple of the alignment.
+inline bool isAddrAligned(Align Lhs, const void *Addr) {
+ return isAligned(Lhs, reinterpret_cast<uintptr_t>(Addr));
+}
+
+/// Returns a multiple of A needed to store `Size` bytes.
+inline uint64_t alignTo(uint64_t Size, Align A) {
+ const uint64_t value = A.value();
+ // The following line is equivalent to `(Size + value - 1) / value * value`.
+
+ // The division followed by a multiplication can be thought of as a right
+ // shift followed by a left shift which zeros out the extra bits produced in
+ // the bump; `~(value - 1)` is a mask where all those bits being zeroed out
+ // are just zero.
+
+ // Most compilers can generate this code but the pattern may be missed when
+ // multiple functions gets inlined.
+ return (Size + value - 1) & ~(value - 1);
+}
+
+/// Returns a multiple of A needed to store `Size` bytes.
+/// Returns `Size` if current alignment is undefined.
+inline uint64_t alignTo(uint64_t Size, MaybeAlign A) {
+ return A ? alignTo(Size, A.getValue()) : Size;
+}
+
+/// Aligns `Addr` to `Alignment` bytes, rounding up.
+inline uintptr_t alignAddr(const void *Addr, Align Alignment) {
+ uintptr_t ArithAddr = reinterpret_cast<uintptr_t>(Addr);
+ assert(static_cast<uintptr_t>(ArithAddr + Alignment.value() - 1) >=
+ ArithAddr && "Overflow");
+ return alignTo(ArithAddr, Alignment);
+}
+
+/// Returns the offset to the next integer (mod 2**64) that is greater than
+/// or equal to \p Value and is a multiple of \p Align.
+inline uint64_t offsetToAlignment(uint64_t Value, Align Alignment) {
+ return alignTo(Value, Alignment) - Value;
+}
+
+/// Returns the necessary adjustment for aligning `Addr` to `Alignment`
+/// bytes, rounding up.
+inline uint64_t offsetToAlignedAddr(const void *Addr, Align Alignment) {
+ return offsetToAlignment(reinterpret_cast<uintptr_t>(Addr), Alignment);
+}
+
+/// Returns the log2 of the alignment.
+inline unsigned Log2(Align A) { return A.ShiftValue; }
+
+/// Returns the log2 of the alignment.
+/// \pre A must be defined.
+inline unsigned Log2(MaybeAlign A) {
+ ALIGN_CHECK_ISSET(A);
+ return Log2(A.getValue());
+}
+
+/// Returns the alignment that satisfies both alignments.
+/// Same semantic as MinAlign.
+inline Align commonAlignment(Align A, Align B) { return std::min(A, B); }
+
+/// Returns the alignment that satisfies both alignments.
+/// Same semantic as MinAlign.
+inline Align commonAlignment(Align A, uint64_t Offset) {
+ return Align(MinAlign(A.value(), Offset));
+}
+
+/// Returns the alignment that satisfies both alignments.
+/// Same semantic as MinAlign.
+inline MaybeAlign commonAlignment(MaybeAlign A, MaybeAlign B) {
+ return A && B ? commonAlignment(*A, *B) : A ? A : B;
+}
+
+/// Returns the alignment that satisfies both alignments.
+/// Same semantic as MinAlign.
+inline MaybeAlign commonAlignment(MaybeAlign A, uint64_t Offset) {
+ return MaybeAlign(MinAlign((*A).value(), Offset));
+}
+
+/// Returns a representation of the alignment that encodes undefined as 0.
+inline unsigned encode(MaybeAlign A) { return A ? A->ShiftValue + 1 : 0; }
+
+/// Dual operation of the encode function above.
+inline MaybeAlign decodeMaybeAlign(unsigned Value) {
+ if (Value == 0)
+ return MaybeAlign();
+ Align Out;
+ Out.ShiftValue = Value - 1;
+ return Out;
+}
+
+/// Returns a representation of the alignment, the encoded value is positive by
+/// definition.
+inline unsigned encode(Align A) { return encode(MaybeAlign(A)); }
+
+/// Comparisons between Align and scalars. Rhs must be positive.
+inline bool operator==(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() == Rhs;
+}
+inline bool operator!=(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() != Rhs;
+}
+inline bool operator<=(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() <= Rhs;
+}
+inline bool operator>=(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() >= Rhs;
+}
+inline bool operator<(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() < Rhs;
+}
+inline bool operator>(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() > Rhs;
+}
+
+/// Comparisons between MaybeAlign and scalars.
+inline bool operator==(MaybeAlign Lhs, uint64_t Rhs) {
+ return Lhs ? (*Lhs).value() == Rhs : Rhs == 0;
+}
+inline bool operator!=(MaybeAlign Lhs, uint64_t Rhs) {
+ return Lhs ? (*Lhs).value() != Rhs : Rhs != 0;
+}
+inline bool operator<=(MaybeAlign Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return (*Lhs).value() <= Rhs;
+}
+inline bool operator>=(MaybeAlign Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return (*Lhs).value() >= Rhs;
+}
+inline bool operator<(MaybeAlign Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return (*Lhs).value() < Rhs;
+}
+inline bool operator>(MaybeAlign Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return (*Lhs).value() > Rhs;
+}
+
+/// Comparisons operators between Align.
+inline bool operator==(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue == Rhs.ShiftValue;
+}
+inline bool operator!=(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue != Rhs.ShiftValue;
+}
+inline bool operator<=(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue <= Rhs.ShiftValue;
+}
+inline bool operator>=(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue >= Rhs.ShiftValue;
+}
+inline bool operator<(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue < Rhs.ShiftValue;
+}
+inline bool operator>(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue > Rhs.ShiftValue;
+}
+
+/// Comparisons operators between Align and MaybeAlign.
+inline bool operator==(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() == (*Rhs).value();
+}
+inline bool operator!=(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() != (*Rhs).value();
+}
+inline bool operator<=(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() <= (*Rhs).value();
+}
+inline bool operator>=(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() >= (*Rhs).value();
+}
+inline bool operator<(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() < (*Rhs).value();
+}
+inline bool operator>(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() > (*Rhs).value();
+}
+
+/// Comparisons operators between MaybeAlign and Align.
+inline bool operator==(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() == Rhs.value();
+}
+inline bool operator!=(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() != Rhs.value();
+}
+inline bool operator<=(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() <= Rhs.value();
+}
+inline bool operator>=(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() >= Rhs.value();
+}
+inline bool operator<(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() < Rhs.value();
+}
+inline bool operator>(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() > Rhs.value();
+}
+
+inline Align operator/(Align Lhs, uint64_t Divisor) {
+ assert(llvm::isPowerOf2_64(Divisor) &&
+ "Divisor must be positive and a power of 2");
+ assert(Lhs != 1 && "Can't halve byte alignment");
+ return Align(Lhs.value() / Divisor);
+}
+
+inline MaybeAlign operator/(MaybeAlign Lhs, uint64_t Divisor) {
+ assert(llvm::isPowerOf2_64(Divisor) &&
+ "Divisor must be positive and a power of 2");
+ return Lhs ? Lhs.getValue() / Divisor : MaybeAlign();
+}
+
+inline Align max(MaybeAlign Lhs, Align Rhs) {
+ return Lhs && *Lhs > Rhs ? *Lhs : Rhs;
+}
+
+inline Align max(Align Lhs, MaybeAlign Rhs) {
+ return Rhs && *Rhs > Lhs ? *Rhs : Lhs;
+}
+
+#undef ALIGN_CHECK_ISPOSITIVE
+#undef ALIGN_CHECK_ISSET
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_ALIGNMENT_H_
diff --git a/third_party/llvm-project/include/llvm/Support/Allocator.h b/third_party/llvm-project/include/llvm/Support/Allocator.h
new file mode 100644
index 000000000..106b90c35
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Allocator.h
@@ -0,0 +1,523 @@
+//===- Allocator.h - Simple memory allocation abstraction -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both
+/// of these conform to an LLVM "Allocator" concept which consists of an
+/// Allocate method accepting a size and alignment, and a Deallocate accepting
+/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of
+/// Allocate and Deallocate for setting size and alignment based on the final
+/// type. These overloads are typically provided by a base class template \c
+/// AllocatorBase.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ALLOCATOR_H
+#define LLVM_SUPPORT_ALLOCATOR_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Alignment.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemAlloc.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+
+namespace llvm {
+
+/// CRTP base class providing obvious overloads for the core \c
+/// Allocate() methods of LLVM-style allocators.
+///
+/// This base class both documents the full public interface exposed by all
+/// LLVM-style allocators, and redirects all of the overloads to a single core
+/// set of methods which the derived class must define.
+template <typename DerivedT> class AllocatorBase {
+public:
+ /// Allocate \a Size bytes of \a Alignment aligned memory. This method
+ /// must be implemented by \c DerivedT.
+ void *Allocate(size_t Size, size_t Alignment) {
+#ifdef __clang__
+ static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>(
+ &AllocatorBase::Allocate) !=
+ static_cast<void *(DerivedT::*)(size_t, size_t)>(
+ &DerivedT::Allocate),
+ "Class derives from AllocatorBase without implementing the "
+ "core Allocate(size_t, size_t) overload!");
+#endif
+ return static_cast<DerivedT *>(this)->Allocate(Size, Alignment);
+ }
+
+ /// Deallocate \a Ptr to \a Size bytes of memory allocated by this
+ /// allocator.
+ void Deallocate(const void *Ptr, size_t Size) {
+#ifdef __clang__
+ static_assert(static_cast<void (AllocatorBase::*)(const void *, size_t)>(
+ &AllocatorBase::Deallocate) !=
+ static_cast<void (DerivedT::*)(const void *, size_t)>(
+ &DerivedT::Deallocate),
+ "Class derives from AllocatorBase without implementing the "
+ "core Deallocate(void *) overload!");
+#endif
+ return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size);
+ }
+
+ // The rest of these methods are helpers that redirect to one of the above
+ // core methods.
+
+ /// Allocate space for a sequence of objects without constructing them.
+ template <typename T> T *Allocate(size_t Num = 1) {
+ return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
+ }
+
+ /// Deallocate space for a sequence of objects without constructing them.
+ template <typename T>
+ typename std::enable_if<
+ !std::is_same<typename std::remove_cv<T>::type, void>::value, void>::type
+ Deallocate(T *Ptr, size_t Num = 1) {
+ Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T));
+ }
+};
+
+class MallocAllocator : public AllocatorBase<MallocAllocator> {
+public:
+ void Reset() {}
+
+ LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
+ size_t /*Alignment*/) {
+ return safe_malloc(Size);
+ }
+
+ // Pull in base class overloads.
+ using AllocatorBase<MallocAllocator>::Allocate;
+
+ void Deallocate(const void *Ptr, size_t /*Size*/) {
+ free(const_cast<void *>(Ptr));
+ }
+
+ // Pull in base class overloads.
+ using AllocatorBase<MallocAllocator>::Deallocate;
+
+ void PrintStats() const {}
+};
+
+namespace detail {
+
+// We call out to an external function to actually print the message as the
+// printing code uses Allocator.h in its implementation.
+void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated,
+ size_t TotalMemory);
+
+} // end namespace detail
+
+/// Allocate memory in an ever growing pool, as if by bump-pointer.
+///
+/// This isn't strictly a bump-pointer allocator as it uses backing slabs of
+/// memory rather than relying on a boundless contiguous heap. However, it has
+/// bump-pointer semantics in that it is a monotonically growing pool of memory
+/// where every allocation is found by merely allocating the next N bytes in
+/// the slab, or the next N bytes in the next slab.
+///
+/// Note that this also has a threshold for forcing allocations above a certain
+/// size into their own slab.
+///
+/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator
+/// object, which wraps malloc, to allocate memory, but it can be changed to
+/// use a custom allocator.
+template <typename AllocatorT = MallocAllocator, size_t SlabSize = 4096,
+ size_t SizeThreshold = SlabSize>
+class BumpPtrAllocatorImpl
+ : public AllocatorBase<
+ BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>> {
+public:
+ static_assert(SizeThreshold <= SlabSize,
+ "The SizeThreshold must be at most the SlabSize to ensure "
+ "that objects larger than a slab go into their own memory "
+ "allocation.");
+
+ BumpPtrAllocatorImpl() = default;
+
+ template <typename T>
+ BumpPtrAllocatorImpl(T &&Allocator)
+ : Allocator(std::forward<T &&>(Allocator)) {}
+
+ // Manually implement a move constructor as we must clear the old allocator's
+ // slabs as a matter of correctness.
+ BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old)
+ : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)),
+ CustomSizedSlabs(std::move(Old.CustomSizedSlabs)),
+ BytesAllocated(Old.BytesAllocated), RedZoneSize(Old.RedZoneSize),
+ Allocator(std::move(Old.Allocator)) {
+ Old.CurPtr = Old.End = nullptr;
+ Old.BytesAllocated = 0;
+ Old.Slabs.clear();
+ Old.CustomSizedSlabs.clear();
+ }
+
+ ~BumpPtrAllocatorImpl() {
+ DeallocateSlabs(Slabs.begin(), Slabs.end());
+ DeallocateCustomSizedSlabs();
+ }
+
+ BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) {
+ DeallocateSlabs(Slabs.begin(), Slabs.end());
+ DeallocateCustomSizedSlabs();
+
+ CurPtr = RHS.CurPtr;
+ End = RHS.End;
+ BytesAllocated = RHS.BytesAllocated;
+ RedZoneSize = RHS.RedZoneSize;
+ Slabs = std::move(RHS.Slabs);
+ CustomSizedSlabs = std::move(RHS.CustomSizedSlabs);
+ Allocator = std::move(RHS.Allocator);
+
+ RHS.CurPtr = RHS.End = nullptr;
+ RHS.BytesAllocated = 0;
+ RHS.Slabs.clear();
+ RHS.CustomSizedSlabs.clear();
+ return *this;
+ }
+
+ /// Deallocate all but the current slab and reset the current pointer
+ /// to the beginning of it, freeing all memory allocated so far.
+ void Reset() {
+ // Deallocate all but the first slab, and deallocate all custom-sized slabs.
+ DeallocateCustomSizedSlabs();
+ CustomSizedSlabs.clear();
+
+ if (Slabs.empty())
+ return;
+
+ // Reset the state.
+ BytesAllocated = 0;
+ CurPtr = (char *)Slabs.front();
+ End = CurPtr + SlabSize;
+
+ __asan_poison_memory_region(*Slabs.begin(), computeSlabSize(0));
+ DeallocateSlabs(std::next(Slabs.begin()), Slabs.end());
+ Slabs.erase(std::next(Slabs.begin()), Slabs.end());
+ }
+
+ /// Allocate space at the specified alignment.
+ LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+ Allocate(size_t Size, Align Alignment) {
+ // Keep track of how many bytes we've allocated.
+ BytesAllocated += Size;
+
+ size_t Adjustment = offsetToAlignedAddr(CurPtr, Alignment);
+ assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow");
+
+ size_t SizeToAllocate = Size;
+#if LLVM_ADDRESS_SANITIZER_BUILD
+ // Add trailing bytes as a "red zone" under ASan.
+ SizeToAllocate += RedZoneSize;
+#endif
+
+ // Check if we have enough space.
+ if (Adjustment + SizeToAllocate <= size_t(End - CurPtr)) {
+ char *AlignedPtr = CurPtr + Adjustment;
+ CurPtr = AlignedPtr + SizeToAllocate;
+ // Update the allocation point of this memory block in MemorySanitizer.
+ // Without this, MemorySanitizer messages for values originated from here
+ // will point to the allocation of the entire slab.
+ __msan_allocated_memory(AlignedPtr, Size);
+ // Similarly, tell ASan about this space.
+ __asan_unpoison_memory_region(AlignedPtr, Size);
+ return AlignedPtr;
+ }
+
+ // If Size is really big, allocate a separate slab for it.
+ size_t PaddedSize = SizeToAllocate + Alignment.value() - 1;
+ if (PaddedSize > SizeThreshold) {
+ void *NewSlab = Allocator.Allocate(PaddedSize, 0);
+ // We own the new slab and don't want anyone reading anyting other than
+ // pieces returned from this method. So poison the whole slab.
+ __asan_poison_memory_region(NewSlab, PaddedSize);
+ CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize));
+
+ uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment);
+ assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize);
+ char *AlignedPtr = (char*)AlignedAddr;
+ __msan_allocated_memory(AlignedPtr, Size);
+ __asan_unpoison_memory_region(AlignedPtr, Size);
+ return AlignedPtr;
+ }
+
+ // Otherwise, start a new slab and try again.
+ StartNewSlab();
+ uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment);
+ assert(AlignedAddr + SizeToAllocate <= (uintptr_t)End &&
+ "Unable to allocate memory!");
+ char *AlignedPtr = (char*)AlignedAddr;
+ CurPtr = AlignedPtr + SizeToAllocate;
+ __msan_allocated_memory(AlignedPtr, Size);
+ __asan_unpoison_memory_region(AlignedPtr, Size);
+ return AlignedPtr;
+ }
+
+ inline LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+ Allocate(size_t Size, size_t Alignment) {
+ assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead.");
+ return Allocate(Size, Align(Alignment));
+ }
+
+ // Pull in base class overloads.
+ using AllocatorBase<BumpPtrAllocatorImpl>::Allocate;
+
+ // Bump pointer allocators are expected to never free their storage; and
+ // clients expect pointers to remain valid for non-dereferencing uses even
+ // after deallocation.
+ void Deallocate(const void *Ptr, size_t Size) {
+ __asan_poison_memory_region(Ptr, Size);
+ }
+
+ // Pull in base class overloads.
+ using AllocatorBase<BumpPtrAllocatorImpl>::Deallocate;
+
+ size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); }
+
+ /// \return An index uniquely and reproducibly identifying
+ /// an input pointer \p Ptr in the given allocator.
+ /// The returned value is negative iff the object is inside a custom-size
+ /// slab.
+ /// Returns an empty optional if the pointer is not found in the allocator.
+ llvm::Optional<int64_t> identifyObject(const void *Ptr) {
+ const char *P = static_cast<const char *>(Ptr);
+ int64_t InSlabIdx = 0;
+ for (size_t Idx = 0, E = Slabs.size(); Idx < E; Idx++) {
+ const char *S = static_cast<const char *>(Slabs[Idx]);
+ if (P >= S && P < S + computeSlabSize(Idx))
+ return InSlabIdx + static_cast<int64_t>(P - S);
+ InSlabIdx += static_cast<int64_t>(computeSlabSize(Idx));
+ }
+
+ // Use negative index to denote custom sized slabs.
+ int64_t InCustomSizedSlabIdx = -1;
+ for (size_t Idx = 0, E = CustomSizedSlabs.size(); Idx < E; Idx++) {
+ const char *S = static_cast<const char *>(CustomSizedSlabs[Idx].first);
+ size_t Size = CustomSizedSlabs[Idx].second;
+ if (P >= S && P < S + Size)
+ return InCustomSizedSlabIdx - static_cast<int64_t>(P - S);
+ InCustomSizedSlabIdx -= static_cast<int64_t>(Size);
+ }
+ return None;
+ }
+
+ /// A wrapper around identifyObject that additionally asserts that
+ /// the object is indeed within the allocator.
+ /// \return An index uniquely and reproducibly identifying
+ /// an input pointer \p Ptr in the given allocator.
+ int64_t identifyKnownObject(const void *Ptr) {
+ Optional<int64_t> Out = identifyObject(Ptr);
+ assert(Out && "Wrong allocator used");
+ return *Out;
+ }
+
+ /// A wrapper around identifyKnownObject. Accepts type information
+ /// about the object and produces a smaller identifier by relying on
+ /// the alignment information. Note that sub-classes may have different
+ /// alignment, so the most base class should be passed as template parameter
+ /// in order to obtain correct results. For that reason automatic template
+ /// parameter deduction is disabled.
+ /// \return An index uniquely and reproducibly identifying
+ /// an input pointer \p Ptr in the given allocator. This identifier is
+ /// different from the ones produced by identifyObject and
+ /// identifyAlignedObject.
+ template <typename T>
+ int64_t identifyKnownAlignedObject(const void *Ptr) {
+ int64_t Out = identifyKnownObject(Ptr);
+ assert(Out % alignof(T) == 0 && "Wrong alignment information");
+ return Out / alignof(T);
+ }
+
+ size_t getTotalMemory() const {
+ size_t TotalMemory = 0;
+ for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I)
+ TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I));
+ for (auto &PtrAndSize : CustomSizedSlabs)
+ TotalMemory += PtrAndSize.second;
+ return TotalMemory;
+ }
+
+ size_t getBytesAllocated() const { return BytesAllocated; }
+
+ void setRedZoneSize(size_t NewSize) {
+ RedZoneSize = NewSize;
+ }
+
+ void PrintStats() const {
+ detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated,
+ getTotalMemory());
+ }
+
+private:
+ /// The current pointer into the current slab.
+ ///
+ /// This points to the next free byte in the slab.
+ char *CurPtr = nullptr;
+
+ /// The end of the current slab.
+ char *End = nullptr;
+
+ /// The slabs allocated so far.
+ SmallVector<void *, 4> Slabs;
+
+ /// Custom-sized slabs allocated for too-large allocation requests.
+ SmallVector<std::pair<void *, size_t>, 0> CustomSizedSlabs;
+
+ /// How many bytes we've allocated.
+ ///
+ /// Used so that we can compute how much space was wasted.
+ size_t BytesAllocated = 0;
+
+ /// The number of bytes to put between allocations when running under
+ /// a sanitizer.
+ size_t RedZoneSize = 1;
+
+ /// The allocator instance we use to get slabs of memory.
+ AllocatorT Allocator;
+
+ static size_t computeSlabSize(unsigned SlabIdx) {
+ // Scale the actual allocated slab size based on the number of slabs
+ // allocated. Every 128 slabs allocated, we double the allocated size to
+ // reduce allocation frequency, but saturate at multiplying the slab size by
+ // 2^30.
+ return SlabSize * ((size_t)1 << std::min<size_t>(30, SlabIdx / 128));
+ }
+
+ /// Allocate a new slab and move the bump pointers over into the new
+ /// slab, modifying CurPtr and End.
+ void StartNewSlab() {
+ size_t AllocatedSlabSize = computeSlabSize(Slabs.size());
+
+ void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0);
+ // We own the new slab and don't want anyone reading anything other than
+ // pieces returned from this method. So poison the whole slab.
+ __asan_poison_memory_region(NewSlab, AllocatedSlabSize);
+
+ Slabs.push_back(NewSlab);
+ CurPtr = (char *)(NewSlab);
+ End = ((char *)NewSlab) + AllocatedSlabSize;
+ }
+
+ /// Deallocate a sequence of slabs.
+ void DeallocateSlabs(SmallVectorImpl<void *>::iterator I,
+ SmallVectorImpl<void *>::iterator E) {
+ for (; I != E; ++I) {
+ size_t AllocatedSlabSize =
+ computeSlabSize(std::distance(Slabs.begin(), I));
+ Allocator.Deallocate(*I, AllocatedSlabSize);
+ }
+ }
+
+ /// Deallocate all memory for custom sized slabs.
+ void DeallocateCustomSizedSlabs() {
+ for (auto &PtrAndSize : CustomSizedSlabs) {
+ void *Ptr = PtrAndSize.first;
+ size_t Size = PtrAndSize.second;
+ Allocator.Deallocate(Ptr, Size);
+ }
+ }
+
+ template <typename T> friend class SpecificBumpPtrAllocator;
+};
+
+/// The standard BumpPtrAllocator which just uses the default template
+/// parameters.
+typedef BumpPtrAllocatorImpl<> BumpPtrAllocator;
+
+/// A BumpPtrAllocator that allows only elements of a specific type to be
+/// allocated.
+///
+/// This allows calling the destructor in DestroyAll() and when the allocator is
+/// destroyed.
+template <typename T> class SpecificBumpPtrAllocator {
+ BumpPtrAllocator Allocator;
+
+public:
+ SpecificBumpPtrAllocator() {
+ // Because SpecificBumpPtrAllocator walks the memory to call destructors,
+ // it can't have red zones between allocations.
+ Allocator.setRedZoneSize(0);
+ }
+ SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old)
+ : Allocator(std::move(Old.Allocator)) {}
+ ~SpecificBumpPtrAllocator() { DestroyAll(); }
+
+ SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) {
+ Allocator = std::move(RHS.Allocator);
+ return *this;
+ }
+
+ /// Call the destructor of each allocated object and deallocate all but the
+ /// current slab and reset the current pointer to the beginning of it, freeing
+ /// all memory allocated so far.
+ void DestroyAll() {
+ auto DestroyElements = [](char *Begin, char *End) {
+ assert(Begin == (char *)alignAddr(Begin, Align::Of<T>()));
+ for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T))
+ reinterpret_cast<T *>(Ptr)->~T();
+ };
+
+ for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E;
+ ++I) {
+ size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize(
+ std::distance(Allocator.Slabs.begin(), I));
+ char *Begin = (char *)alignAddr(*I, Align::Of<T>());
+ char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr
+ : (char *)*I + AllocatedSlabSize;
+
+ DestroyElements(Begin, End);
+ }
+
+ for (auto &PtrAndSize : Allocator.CustomSizedSlabs) {
+ void *Ptr = PtrAndSize.first;
+ size_t Size = PtrAndSize.second;
+ DestroyElements((char *)alignAddr(Ptr, Align::Of<T>()),
+ (char *)Ptr + Size);
+ }
+
+ Allocator.Reset();
+ }
+
+ /// Allocate space for an array of objects without constructing them.
+ T *Allocate(size_t num = 1) { return Allocator.Allocate<T>(num); }
+};
+
+} // end namespace llvm
+
+template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold>
+void *operator new(size_t Size,
+ llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize,
+ SizeThreshold> &Allocator) {
+ struct S {
+ char c;
+ union {
+ double D;
+ long double LD;
+ long long L;
+ void *P;
+ } x;
+ };
+ return Allocator.Allocate(
+ Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x)));
+}
+
+template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold>
+void operator delete(
+ void *, llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold> &) {
+}
+
+#endif // LLVM_SUPPORT_ALLOCATOR_H
diff --git a/third_party/llvm-project/include/llvm/Support/BinaryByteStream.h b/third_party/llvm-project/include/llvm/Support/BinaryByteStream.h
new file mode 100644
index 000000000..7acce9a03
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/BinaryByteStream.h
@@ -0,0 +1,273 @@
+//===- BinaryByteStream.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
+//===----------------------------------------------------------------------===//
+// A BinaryStream which stores data in a single continguous memory buffer.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_BINARYBYTESTREAM_H
+#define LLVM_SUPPORT_BINARYBYTESTREAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStreamError.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+
+namespace llvm {
+
+/// An implementation of BinaryStream which holds its entire data set
+/// in a single contiguous buffer. BinaryByteStream guarantees that no read
+/// operation will ever incur a copy. Note that BinaryByteStream does not
+/// own the underlying buffer.
+class BinaryByteStream : public BinaryStream {
+public:
+ BinaryByteStream() = default;
+ BinaryByteStream(ArrayRef<uint8_t> Data, llvm::support::endianness Endian)
+ : Endian(Endian), Data(Data) {}
+ BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
+ : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
+
+ llvm::support::endianness getEndian() const override { return Endian; }
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ if (auto EC = checkOffsetForRead(Offset, Size))
+ return EC;
+ Buffer = Data.slice(Offset, Size);
+ return Error::success();
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ if (auto EC = checkOffsetForRead(Offset, 1))
+ return EC;
+ Buffer = Data.slice(Offset);
+ return Error::success();
+ }
+
+ uint32_t getLength() override { return Data.size(); }
+
+ ArrayRef<uint8_t> data() const { return Data; }
+
+ StringRef str() const {
+ const char *CharData = reinterpret_cast<const char *>(Data.data());
+ return StringRef(CharData, Data.size());
+ }
+
+protected:
+ llvm::support::endianness Endian;
+ ArrayRef<uint8_t> Data;
+};
+
+/// An implementation of BinaryStream whose data is backed by an llvm
+/// MemoryBuffer object. MemoryBufferByteStream owns the MemoryBuffer in
+/// question. As with BinaryByteStream, reading from a MemoryBufferByteStream
+/// will never cause a copy.
+class MemoryBufferByteStream : public BinaryByteStream {
+public:
+ MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
+ llvm::support::endianness Endian)
+ : BinaryByteStream(Buffer->getBuffer(), Endian),
+ MemBuffer(std::move(Buffer)) {}
+
+ std::unique_ptr<MemoryBuffer> MemBuffer;
+};
+
+/// An implementation of BinaryStream which holds its entire data set
+/// in a single contiguous buffer. As with BinaryByteStream, the mutable
+/// version also guarantees that no read operation will ever incur a copy,
+/// and similarly it does not own the underlying buffer.
+class MutableBinaryByteStream : public WritableBinaryStream {
+public:
+ MutableBinaryByteStream() = default;
+ MutableBinaryByteStream(MutableArrayRef<uint8_t> Data,
+ llvm::support::endianness Endian)
+ : Data(Data), ImmutableStream(Data, Endian) {}
+
+ llvm::support::endianness getEndian() const override {
+ return ImmutableStream.getEndian();
+ }
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ return ImmutableStream.readBytes(Offset, Size, Buffer);
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
+ }
+
+ uint32_t getLength() override { return ImmutableStream.getLength(); }
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override {
+ if (Buffer.empty())
+ return Error::success();
+
+ if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
+ return EC;
+
+ uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
+ ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
+ return Error::success();
+ }
+
+ Error commit() override { return Error::success(); }
+
+ MutableArrayRef<uint8_t> data() const { return Data; }
+
+private:
+ MutableArrayRef<uint8_t> Data;
+ BinaryByteStream ImmutableStream;
+};
+
+/// An implementation of WritableBinaryStream which can write at its end
+/// causing the underlying data to grow. This class owns the underlying data.
+class AppendingBinaryByteStream : public WritableBinaryStream {
+ std::vector<uint8_t> Data;
+ llvm::support::endianness Endian = llvm::support::little;
+
+public:
+ AppendingBinaryByteStream() = default;
+ AppendingBinaryByteStream(llvm::support::endianness Endian)
+ : Endian(Endian) {}
+
+ void clear() { Data.clear(); }
+
+ llvm::support::endianness getEndian() const override { return Endian; }
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
+ return EC;
+
+ Buffer = makeArrayRef(Data).slice(Offset, Size);
+ return Error::success();
+ }
+
+ void insert(uint32_t Offset, ArrayRef<uint8_t> Bytes) {
+ Data.insert(Data.begin() + Offset, Bytes.begin(), Bytes.end());
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ if (auto EC = checkOffsetForWrite(Offset, 1))
+ return EC;
+
+ Buffer = makeArrayRef(Data).slice(Offset);
+ return Error::success();
+ }
+
+ uint32_t getLength() override { return Data.size(); }
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override {
+ if (Buffer.empty())
+ return Error::success();
+
+ // This is well-defined for any case except where offset is strictly
+ // greater than the current length. If offset is equal to the current
+ // length, we can still grow. If offset is beyond the current length, we
+ // would have to decide how to deal with the intermediate uninitialized
+ // bytes. So we punt on that case for simplicity and just say it's an
+ // error.
+ if (Offset > getLength())
+ return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
+
+ uint32_t RequiredSize = Offset + Buffer.size();
+ if (RequiredSize > Data.size())
+ Data.resize(RequiredSize);
+
+ ::memcpy(Data.data() + Offset, Buffer.data(), Buffer.size());
+ return Error::success();
+ }
+
+ Error commit() override { return Error::success(); }
+
+ /// Return the properties of this stream.
+ virtual BinaryStreamFlags getFlags() const override {
+ return BSF_Write | BSF_Append;
+ }
+
+ MutableArrayRef<uint8_t> data() { return Data; }
+};
+
+/// An implementation of WritableBinaryStream backed by an llvm
+/// FileOutputBuffer.
+class FileBufferByteStream : public WritableBinaryStream {
+private:
+ class StreamImpl : public MutableBinaryByteStream {
+ public:
+ StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
+ llvm::support::endianness Endian)
+ : MutableBinaryByteStream(
+ MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
+ Buffer->getBufferEnd()),
+ Endian),
+ FileBuffer(std::move(Buffer)) {}
+
+ Error commit() override {
+ if (FileBuffer->commit())
+ return make_error<BinaryStreamError>(
+ stream_error_code::filesystem_error);
+ return Error::success();
+ }
+
+ /// Returns a pointer to the start of the buffer.
+ uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
+
+ /// Returns a pointer to the end of the buffer.
+ uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
+
+ private:
+ std::unique_ptr<FileOutputBuffer> FileBuffer;
+ };
+
+public:
+ FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
+ llvm::support::endianness Endian)
+ : Impl(std::move(Buffer), Endian) {}
+
+ llvm::support::endianness getEndian() const override {
+ return Impl.getEndian();
+ }
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ return Impl.readBytes(Offset, Size, Buffer);
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ return Impl.readLongestContiguousChunk(Offset, Buffer);
+ }
+
+ uint32_t getLength() override { return Impl.getLength(); }
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) override {
+ return Impl.writeBytes(Offset, Data);
+ }
+
+ Error commit() override { return Impl.commit(); }
+
+ /// Returns a pointer to the start of the buffer.
+ uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
+
+ /// Returns a pointer to the end of the buffer.
+ uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
+
+private:
+ StreamImpl Impl;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_BYTESTREAM_H
diff --git a/third_party/llvm-project/include/llvm/Support/BinaryStream.h b/third_party/llvm-project/include/llvm/Support/BinaryStream.h
new file mode 100644
index 000000000..fcf439855
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/BinaryStream.h
@@ -0,0 +1,101 @@
+//===- BinaryStream.h - Base interface for a stream of data -----*- 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_BINARYSTREAM_H
+#define LLVM_SUPPORT_BINARYSTREAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/Support/BinaryStreamError.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+
+namespace llvm {
+
+enum BinaryStreamFlags {
+ BSF_None = 0,
+ BSF_Write = 1, // Stream supports writing.
+ BSF_Append = 2, // Writing can occur at offset == length.
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ BSF_Append)
+};
+
+/// An interface for accessing data in a stream-like format, but which
+/// discourages copying. Instead of specifying a buffer in which to copy
+/// data on a read, the API returns an ArrayRef to data owned by the stream's
+/// implementation. Since implementations may not necessarily store data in a
+/// single contiguous buffer (or even in memory at all), in such cases a it may
+/// be necessary for an implementation to cache such a buffer so that it can
+/// return it.
+class BinaryStream {
+public:
+ virtual ~BinaryStream() = default;
+
+ virtual llvm::support::endianness getEndian() const = 0;
+
+ /// Given an offset into the stream and a number of bytes, attempt to
+ /// read the bytes and set the output ArrayRef to point to data owned by the
+ /// stream.
+ virtual Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) = 0;
+
+ /// Given an offset into the stream, read as much as possible without
+ /// copying any data.
+ virtual Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) = 0;
+
+ /// Return the number of bytes of data in this stream.
+ virtual uint32_t getLength() = 0;
+
+ /// Return the properties of this stream.
+ virtual BinaryStreamFlags getFlags() const { return BSF_None; }
+
+protected:
+ Error checkOffsetForRead(uint32_t Offset, uint32_t DataSize) {
+ if (Offset > getLength())
+ return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
+ if (getLength() < DataSize + Offset)
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
+ return Error::success();
+ }
+};
+
+/// A BinaryStream which can be read from as well as written to. Note
+/// that writing to a BinaryStream always necessitates copying from the input
+/// buffer to the stream's backing store. Streams are assumed to be buffered
+/// so that to be portable it is necessary to call commit() on the stream when
+/// all data has been written.
+class WritableBinaryStream : public BinaryStream {
+public:
+ ~WritableBinaryStream() override = default;
+
+ /// Attempt to write the given bytes into the stream at the desired
+ /// offset. This will always necessitate a copy. Cannot shrink or grow the
+ /// stream, only writes into existing allocated space.
+ virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) = 0;
+
+ /// For buffered streams, commits changes to the backing store.
+ virtual Error commit() = 0;
+
+ /// Return the properties of this stream.
+ BinaryStreamFlags getFlags() const override { return BSF_Write; }
+
+protected:
+ Error checkOffsetForWrite(uint32_t Offset, uint32_t DataSize) {
+ if (!(getFlags() & BSF_Append))
+ return checkOffsetForRead(Offset, DataSize);
+
+ if (Offset > getLength())
+ return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
+ return Error::success();
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_BINARYSTREAM_H
diff --git a/third_party/llvm-project/include/llvm/Support/BinaryStreamError.h b/third_party/llvm-project/include/llvm/Support/BinaryStreamError.h
new file mode 100644
index 000000000..cf6e034ff
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/BinaryStreamError.h
@@ -0,0 +1,47 @@
+//===- BinaryStreamError.h - Error extensions for Binary Streams *- 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_BINARYSTREAMERROR_H
+#define LLVM_SUPPORT_BINARYSTREAMERROR_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+
+#include <string>
+
+namespace llvm {
+enum class stream_error_code {
+ unspecified,
+ stream_too_short,
+ invalid_array_size,
+ invalid_offset,
+ filesystem_error
+};
+
+/// Base class for errors originating when parsing raw PDB files
+class BinaryStreamError : public ErrorInfo<BinaryStreamError> {
+public:
+ static char ID;
+ explicit BinaryStreamError(stream_error_code C);
+ explicit BinaryStreamError(StringRef Context);
+ BinaryStreamError(stream_error_code C, StringRef Context);
+
+ void log(raw_ostream &OS) const override;
+ std::error_code convertToErrorCode() const override;
+
+ StringRef getErrorMessage() const;
+
+ stream_error_code getErrorCode() const { return Code; }
+
+private:
+ std::string ErrMsg;
+ stream_error_code Code;
+};
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_BINARYSTREAMERROR_H
diff --git a/third_party/llvm-project/include/llvm/Support/CBindingWrapping.h b/third_party/llvm-project/include/llvm/Support/CBindingWrapping.h
new file mode 100644
index 000000000..46d6b4e3f
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/CBindingWrapping.h
@@ -0,0 +1,46 @@
+//===- llvm/Support/CBindingWrapping.h - C Interface Wrapping ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the wrapping macros for the C interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CBINDINGWRAPPING_H
+#define LLVM_SUPPORT_CBINDINGWRAPPING_H
+
+#include "llvm-c/Types.h"
+#include "llvm/Support/Casting.h"
+
+#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \
+ inline ty *unwrap(ref P) { \
+ return reinterpret_cast<ty*>(P); \
+ } \
+ \
+ inline ref wrap(const ty *P) { \
+ return reinterpret_cast<ref>(const_cast<ty*>(P)); \
+ }
+
+#define DEFINE_ISA_CONVERSION_FUNCTIONS(ty, ref) \
+ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \
+ \
+ template<typename T> \
+ inline T *unwrap(ref P) { \
+ return cast<T>(unwrap(P)); \
+ }
+
+#define DEFINE_STDCXX_CONVERSION_FUNCTIONS(ty, ref) \
+ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \
+ \
+ template<typename T> \
+ inline T *unwrap(ref P) { \
+ T *Q = (T*)unwrap(P); \
+ assert(Q && "Invalid cast!"); \
+ return Q; \
+ }
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/Casting.h b/third_party/llvm-project/include/llvm/Support/Casting.h
new file mode 100644
index 000000000..46bdedb04
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Casting.h
@@ -0,0 +1,408 @@
+//===- llvm/Support/Casting.h - Allow flexible, checked, casts --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(),
+// and dyn_cast_or_null<X>() templates.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CASTING_H
+#define LLVM_SUPPORT_CASTING_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <memory>
+#include <type_traits>
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+// isa<x> Support Templates
+//===----------------------------------------------------------------------===//
+
+// Define a template that can be specialized by smart pointers to reflect the
+// fact that they are automatically dereferenced, and are not involved with the
+// template selection process... the default implementation is a noop.
+//
+template<typename From> struct simplify_type {
+ using SimpleType = From; // The real type this represents...
+
+ // An accessor to get the real value...
+ static SimpleType &getSimplifiedValue(From &Val) { return Val; }
+};
+
+template<typename From> struct simplify_type<const From> {
+ using NonConstSimpleType = typename simplify_type<From>::SimpleType;
+ using SimpleType =
+ typename add_const_past_pointer<NonConstSimpleType>::type;
+ using RetType =
+ typename add_lvalue_reference_if_not_pointer<SimpleType>::type;
+
+ static RetType getSimplifiedValue(const From& Val) {
+ return simplify_type<From>::getSimplifiedValue(const_cast<From&>(Val));
+ }
+};
+
+// The core of the implementation of isa<X> is here; To and From should be
+// the names of classes. This template can be specialized to customize the
+// implementation of isa<> without rewriting it from scratch.
+template <typename To, typename From, typename Enabler = void>
+struct isa_impl {
+ static inline bool doit(const From &Val) {
+ return To::classof(&Val);
+ }
+};
+
+/// Always allow upcasts, and perform no dynamic check for them.
+template <typename To, typename From>
+struct isa_impl<
+ To, From, typename std::enable_if<std::is_base_of<To, From>::value>::type> {
+ static inline bool doit(const From &) { return true; }
+};
+
+template <typename To, typename From> struct isa_impl_cl {
+ static inline bool doit(const From &Val) {
+ return isa_impl<To, From>::doit(Val);
+ }
+};
+
+template <typename To, typename From> struct isa_impl_cl<To, const From> {
+ static inline bool doit(const From &Val) {
+ return isa_impl<To, From>::doit(Val);
+ }
+};
+
+template <typename To, typename From>
+struct isa_impl_cl<To, const std::unique_ptr<From>> {
+ static inline bool doit(const std::unique_ptr<From> &Val) {
+ assert(Val && "isa<> used on a null pointer");
+ return isa_impl_cl<To, From>::doit(*Val);
+ }
+};
+
+template <typename To, typename From> struct isa_impl_cl<To, From*> {
+ static inline bool doit(const From *Val) {
+ assert(Val && "isa<> used on a null pointer");
+ return isa_impl<To, From>::doit(*Val);
+ }
+};
+
+template <typename To, typename From> struct isa_impl_cl<To, From*const> {
+ static inline bool doit(const From *Val) {
+ assert(Val && "isa<> used on a null pointer");
+ return isa_impl<To, From>::doit(*Val);
+ }
+};
+
+template <typename To, typename From> struct isa_impl_cl<To, const From*> {
+ static inline bool doit(const From *Val) {
+ assert(Val && "isa<> used on a null pointer");
+ return isa_impl<To, From>::doit(*Val);
+ }
+};
+
+template <typename To, typename From> struct isa_impl_cl<To, const From*const> {
+ static inline bool doit(const From *Val) {
+ assert(Val && "isa<> used on a null pointer");
+ return isa_impl<To, From>::doit(*Val);
+ }
+};
+
+template<typename To, typename From, typename SimpleFrom>
+struct isa_impl_wrap {
+ // When From != SimplifiedType, we can simplify the type some more by using
+ // the simplify_type template.
+ static bool doit(const From &Val) {
+ return isa_impl_wrap<To, SimpleFrom,
+ typename simplify_type<SimpleFrom>::SimpleType>::doit(
+ simplify_type<const From>::getSimplifiedValue(Val));
+ }
+};
+
+template<typename To, typename FromTy>
+struct isa_impl_wrap<To, FromTy, FromTy> {
+ // When From == SimpleType, we are as simple as we are going to get.
+ static bool doit(const FromTy &Val) {
+ return isa_impl_cl<To,FromTy>::doit(Val);
+ }
+};
+
+// isa<X> - Return true if the parameter to the template is an instance of the
+// template type argument. Used like this:
+//
+// if (isa<Type>(myVal)) { ... }
+//
+template <class X, class Y> LLVM_NODISCARD inline bool isa(const Y &Val) {
+ return isa_impl_wrap<X, const Y,
+ typename simplify_type<const Y>::SimpleType>::doit(Val);
+}
+
+// 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
+//===----------------------------------------------------------------------===//
+
+template<class To, class From> struct cast_retty;
+
+// Calculate what type the 'cast' function should return, based on a requested
+// type of To and a source type of From.
+template<class To, class From> struct cast_retty_impl {
+ using ret_type = To &; // Normal case, return Ty&
+};
+template<class To, class From> struct cast_retty_impl<To, const From> {
+ using ret_type = const To &; // Normal case, return Ty&
+};
+
+template<class To, class From> struct cast_retty_impl<To, From*> {
+ using ret_type = To *; // Pointer arg case, return Ty*
+};
+
+template<class To, class From> struct cast_retty_impl<To, const From*> {
+ using ret_type = const To *; // Constant pointer arg case, return const Ty*
+};
+
+template<class To, class From> struct cast_retty_impl<To, const From*const> {
+ using ret_type = const To *; // Constant pointer arg case, return const Ty*
+};
+
+template <class To, class From>
+struct cast_retty_impl<To, std::unique_ptr<From>> {
+private:
+ using PointerType = typename cast_retty_impl<To, From *>::ret_type;
+ using ResultType = typename std::remove_pointer<PointerType>::type;
+
+public:
+ using ret_type = std::unique_ptr<ResultType>;
+};
+
+template<class To, class From, class SimpleFrom>
+struct cast_retty_wrap {
+ // When the simplified type and the from type are not the same, use the type
+ // simplifier to reduce the type, then reuse cast_retty_impl to get the
+ // resultant type.
+ using ret_type = typename cast_retty<To, SimpleFrom>::ret_type;
+};
+
+template<class To, class FromTy>
+struct cast_retty_wrap<To, FromTy, FromTy> {
+ // When the simplified type is equal to the from type, use it directly.
+ using ret_type = typename cast_retty_impl<To,FromTy>::ret_type;
+};
+
+template<class To, class From>
+struct cast_retty {
+ using ret_type = typename cast_retty_wrap<
+ To, From, typename simplify_type<From>::SimpleType>::ret_type;
+};
+
+// Ensure the non-simple values are converted using the simplify_type template
+// that may be specialized by smart pointers...
+//
+template<class To, class From, class SimpleFrom> struct cast_convert_val {
+ // This is not a simple type, use the template to simplify it...
+ static typename cast_retty<To, From>::ret_type doit(From &Val) {
+ return cast_convert_val<To, SimpleFrom,
+ typename simplify_type<SimpleFrom>::SimpleType>::doit(
+ simplify_type<From>::getSimplifiedValue(Val));
+ }
+};
+
+template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> {
+ // This _is_ a simple type, just cast it.
+ static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) {
+ typename cast_retty<To, FromTy>::ret_type Res2
+ = (typename cast_retty<To, FromTy>::ret_type)const_cast<FromTy&>(Val);
+ return Res2;
+ }
+};
+
+template <class X> struct is_simple_type {
+ static const bool value =
+ std::is_same<X, typename simplify_type<X>::SimpleType>::value;
+};
+
+// cast<X> - Return the argument parameter cast to the specified type. This
+// casting operator asserts that the type is correct, so it does not return null
+// on failure. It does not allow a null argument (use cast_or_null for that).
+// It is typically used like this:
+//
+// cast<Instruction>(myVal)->getParent()
+//
+template <class X, class Y>
+inline typename std::enable_if<!is_simple_type<Y>::value,
+ typename cast_retty<X, const Y>::ret_type>::type
+cast(const Y &Val) {
+ assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
+ return cast_convert_val<
+ X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val);
+}
+
+template <class X, class Y>
+inline typename cast_retty<X, Y>::ret_type cast(Y &Val) {
+ assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
+ return cast_convert_val<X, Y,
+ typename simplify_type<Y>::SimpleType>::doit(Val);
+}
+
+template <class X, class Y>
+inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) {
+ assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
+ return cast_convert_val<X, Y*,
+ typename simplify_type<Y*>::SimpleType>::doit(Val);
+}
+
+template <class X, class Y>
+inline typename cast_retty<X, std::unique_ptr<Y>>::ret_type
+cast(std::unique_ptr<Y> &&Val) {
+ assert(isa<X>(Val.get()) && "cast<Ty>() argument of incompatible type!");
+ using ret_type = typename cast_retty<X, std::unique_ptr<Y>>::ret_type;
+ return ret_type(
+ cast_convert_val<X, Y *, typename simplify_type<Y *>::SimpleType>::doit(
+ Val.release()));
+}
+
+// cast_or_null<X> - Functionally identical to cast, except that a null value is
+// accepted.
+//
+template <class X, class Y>
+LLVM_NODISCARD inline
+ typename std::enable_if<!is_simple_type<Y>::value,
+ typename cast_retty<X, const Y>::ret_type>::type
+ cast_or_null(const Y &Val) {
+ if (!Val)
+ return nullptr;
+ assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
+ return cast<X>(Val);
+}
+
+template <class X, class Y>
+LLVM_NODISCARD inline
+ typename std::enable_if<!is_simple_type<Y>::value,
+ typename cast_retty<X, Y>::ret_type>::type
+ cast_or_null(Y &Val) {
+ if (!Val)
+ return nullptr;
+ assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
+ return cast<X>(Val);
+}
+
+template <class X, class Y>
+LLVM_NODISCARD inline typename cast_retty<X, Y *>::ret_type
+cast_or_null(Y *Val) {
+ if (!Val) return nullptr;
+ assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
+ return cast<X>(Val);
+}
+
+template <class X, class Y>
+inline typename cast_retty<X, std::unique_ptr<Y>>::ret_type
+cast_or_null(std::unique_ptr<Y> &&Val) {
+ if (!Val)
+ return nullptr;
+ return cast<X>(std::move(Val));
+}
+
+// dyn_cast<X> - Return the argument parameter cast to the specified type. This
+// casting operator returns null if the argument is of the wrong type, so it can
+// be used to test for a type as well as cast if successful. This should be
+// used in the context of an if statement like this:
+//
+// if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... }
+//
+
+template <class X, class Y>
+LLVM_NODISCARD inline
+ typename std::enable_if<!is_simple_type<Y>::value,
+ typename cast_retty<X, const Y>::ret_type>::type
+ dyn_cast(const Y &Val) {
+ return isa<X>(Val) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
+LLVM_NODISCARD inline typename cast_retty<X, Y>::ret_type dyn_cast(Y &Val) {
+ return isa<X>(Val) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
+LLVM_NODISCARD inline typename cast_retty<X, Y *>::ret_type dyn_cast(Y *Val) {
+ return isa<X>(Val) ? cast<X>(Val) : nullptr;
+}
+
+// dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null
+// value is accepted.
+//
+template <class X, class Y>
+LLVM_NODISCARD inline
+ typename std::enable_if<!is_simple_type<Y>::value,
+ typename cast_retty<X, const Y>::ret_type>::type
+ dyn_cast_or_null(const Y &Val) {
+ return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
+LLVM_NODISCARD inline
+ typename std::enable_if<!is_simple_type<Y>::value,
+ typename cast_retty<X, Y>::ret_type>::type
+ dyn_cast_or_null(Y &Val) {
+ return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
+}
+
+template <class X, class Y>
+LLVM_NODISCARD inline typename cast_retty<X, Y *>::ret_type
+dyn_cast_or_null(Y *Val) {
+ return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
+}
+
+// unique_dyn_cast<X> - Given a unique_ptr<Y>, try to return a unique_ptr<X>,
+// taking ownership of the input pointer iff isa<X>(Val) is true. If the
+// cast is successful, From refers to nullptr on exit and the casted value
+// is returned. If the cast is unsuccessful, the function returns nullptr
+// and From is unchanged.
+template <class X, class Y>
+LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr<Y> &Val)
+ -> decltype(cast<X>(Val)) {
+ if (!isa<X>(Val))
+ return nullptr;
+ return cast<X>(std::move(Val));
+}
+
+template <class X, class Y>
+LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val)
+ -> decltype(cast<X>(Val)) {
+ return unique_dyn_cast<X, Y>(Val);
+}
+
+// dyn_cast_or_null<X> - Functionally identical to unique_dyn_cast, except that
+// a null value is accepted.
+template <class X, class Y>
+LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &Val)
+ -> decltype(cast<X>(Val)) {
+ if (!Val)
+ return nullptr;
+ return unique_dyn_cast<X, Y>(Val);
+}
+
+template <class X, class Y>
+LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val)
+ -> decltype(cast<X>(Val)) {
+ return unique_dyn_cast_or_null<X, Y>(Val);
+}
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_CASTING_H
diff --git a/third_party/llvm-project/include/llvm/Support/Chrono.h b/third_party/llvm-project/include/llvm/Support/Chrono.h
new file mode 100644
index 000000000..334ab6083
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Chrono.h
@@ -0,0 +1,171 @@
+//===- llvm/Support/Chrono.h - Utilities for Timing Manipulation-*- 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_CHRONO_H
+#define LLVM_SUPPORT_CHRONO_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/FormatProviders.h"
+
+#include <chrono>
+#include <ctime>
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace sys {
+
+/// A time point on the system clock. This is provided for two reasons:
+/// - to insulate us agains subtle differences in behavoir to differences in
+/// system clock precision (which is implementation-defined and differs between
+/// platforms).
+/// - to shorten the type name
+/// The default precision is nanoseconds. If need a specific precision specify
+/// it explicitly. If unsure, use the default. If you need a time point on a
+/// clock other than the system_clock, use std::chrono directly.
+template <typename D = std::chrono::nanoseconds>
+using TimePoint = std::chrono::time_point<std::chrono::system_clock, D>;
+
+/// Convert a TimePoint to std::time_t
+inline std::time_t toTimeT(TimePoint<> TP) {
+ using namespace std::chrono;
+ return system_clock::to_time_t(
+ time_point_cast<system_clock::time_point::duration>(TP));
+}
+
+/// Convert a std::time_t to a TimePoint
+inline TimePoint<std::chrono::seconds>
+toTimePoint(std::time_t T) {
+ using namespace std::chrono;
+ return time_point_cast<seconds>(system_clock::from_time_t(T));
+}
+
+/// Convert a std::time_t + nanoseconds to a TimePoint
+inline TimePoint<>
+toTimePoint(std::time_t T, uint32_t nsec) {
+ using namespace std::chrono;
+ return time_point_cast<nanoseconds>(system_clock::from_time_t(T))
+ + nanoseconds(nsec);
+}
+
+} // namespace sys
+
+raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint<> TP);
+
+/// Format provider for TimePoint<>
+///
+/// The options string is a strftime format string, with extensions:
+/// - %L is millis: 000-999
+/// - %f is micros: 000000-999999
+/// - %N is nanos: 000000000 - 999999999
+///
+/// If no options are given, the default format is "%Y-%m-%d %H:%M:%S.%N".
+template <>
+struct format_provider<sys::TimePoint<>> {
+ static void format(const sys::TimePoint<> &TP, llvm::raw_ostream &OS,
+ StringRef Style);
+};
+
+/// Implementation of format_provider<T> for duration types.
+///
+/// The options string of a duration type has the grammar:
+///
+/// duration_options ::= [unit][show_unit [number_options]]
+/// unit ::= `h`|`m`|`s`|`ms|`us`|`ns`
+/// show_unit ::= `+` | `-`
+/// number_options ::= options string for a integral or floating point type
+///
+/// Examples
+/// =================================
+/// | options | Input | Output |
+/// =================================
+/// | "" | 1s | 1 s |
+/// | "ms" | 1s | 1000 ms |
+/// | "ms-" | 1s | 1000 |
+/// | "ms-n" | 1s | 1,000 |
+/// | "" | 1.0s | 1.00 s |
+/// =================================
+///
+/// If the unit of the duration type is not one of the units specified above,
+/// it is still possible to format it, provided you explicitly request a
+/// display unit or you request that the unit is not displayed.
+
+namespace detail {
+template <typename Period> struct unit { static const char value[]; };
+template <typename Period> const char unit<Period>::value[] = "";
+
+template <> struct unit<std::ratio<3600>> { static const char value[]; };
+template <> struct unit<std::ratio<60>> { static const char value[]; };
+template <> struct unit<std::ratio<1>> { static const char value[]; };
+template <> struct unit<std::milli> { static const char value[]; };
+template <> struct unit<std::micro> { static const char value[]; };
+template <> struct unit<std::nano> { static const char value[]; };
+} // namespace detail
+
+template <typename Rep, typename Period>
+struct format_provider<std::chrono::duration<Rep, Period>> {
+private:
+ typedef std::chrono::duration<Rep, Period> Dur;
+ typedef typename std::conditional<
+ std::chrono::treat_as_floating_point<Rep>::value, double, intmax_t>::type
+ InternalRep;
+
+ template <typename AsPeriod> static InternalRep getAs(const Dur &D) {
+ using namespace std::chrono;
+ return duration_cast<duration<InternalRep, AsPeriod>>(D).count();
+ }
+
+ static std::pair<InternalRep, StringRef> consumeUnit(StringRef &Style,
+ const Dur &D) {
+ using namespace std::chrono;
+ if (Style.consume_front("ns"))
+ return {getAs<std::nano>(D), "ns"};
+ if (Style.consume_front("us"))
+ return {getAs<std::micro>(D), "us"};
+ if (Style.consume_front("ms"))
+ return {getAs<std::milli>(D), "ms"};
+ if (Style.consume_front("s"))
+ return {getAs<std::ratio<1>>(D), "s"};
+ if (Style.consume_front("m"))
+ return {getAs<std::ratio<60>>(D), "m"};
+ if (Style.consume_front("h"))
+ return {getAs<std::ratio<3600>>(D), "h"};
+ return {D.count(), detail::unit<Period>::value};
+ }
+
+ static bool consumeShowUnit(StringRef &Style) {
+ if (Style.empty())
+ return true;
+ if (Style.consume_front("-"))
+ return false;
+ if (Style.consume_front("+"))
+ return true;
+ assert(0 && "Unrecognised duration format");
+ return true;
+ }
+
+public:
+ static void format(const Dur &D, llvm::raw_ostream &Stream, StringRef Style) {
+ InternalRep count;
+ StringRef unit;
+ std::tie(count, unit) = consumeUnit(Style, D);
+ bool show_unit = consumeShowUnit(Style);
+
+ format_provider<InternalRep>::format(count, Stream, Style);
+
+ if (show_unit) {
+ assert(!unit.empty());
+ Stream << " " << unit;
+ }
+ }
+};
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_CHRONO_H
diff --git a/third_party/llvm-project/include/llvm/Support/CodeGen.h b/third_party/llvm-project/include/llvm/Support/CodeGen.h
new file mode 100644
index 000000000..a3f423e55
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/CodeGen.h
@@ -0,0 +1,67 @@
+//===-- llvm/Support/CodeGen.h - CodeGen Concepts ---------------*- 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 define some types which define code generation concepts. For
+// example, relocation model.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CODEGEN_H
+#define LLVM_SUPPORT_CODEGEN_H
+
+namespace llvm {
+
+ // Relocation model types.
+ namespace Reloc {
+ // 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 };
+ }
+
+ namespace PICLevel {
+ // This is used to map -fpic/-fPIC.
+ enum Level { NotPIC=0, SmallPIC=1, BigPIC=2 };
+ }
+
+ namespace PIELevel {
+ enum Level { Default=0, Small=1, Large=2 };
+ }
+
+ // TLS models.
+ namespace TLSModel {
+ enum Model {
+ GeneralDynamic,
+ LocalDynamic,
+ InitialExec,
+ LocalExec
+ };
+ }
+
+ // Code generation optimization level.
+ namespace CodeGenOpt {
+ enum Level {
+ None = 0, // -O0
+ Less = 1, // -O1
+ Default = 2, // -O2, -Os
+ Aggressive = 3 // -O3
+ };
+ }
+
+ // Specify effect of frame pointer elimination optimization.
+ namespace FramePointer {
+ enum FP {All, NonLeaf, None};
+ }
+
+} // end llvm namespace
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/CommandLine.h b/third_party/llvm-project/include/llvm/Support/CommandLine.h
new file mode 100644
index 000000000..4eb30f548
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/CommandLine.h
@@ -0,0 +1 @@
+// XXX BINARYEN - we don't need this, but stuff imports it
diff --git a/third_party/llvm-project/include/llvm/Support/Compiler.h b/third_party/llvm-project/include/llvm/Support/Compiler.h
new file mode 100644
index 000000000..cb7e57d4c
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Compiler.h
@@ -0,0 +1,585 @@
+//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines several macros, based on the current compiler. This allows
+// use of compiler-specific features in a way that remains portable. This header
+// can be included from either C or C++.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_COMPILER_H
+#define LLVM_SUPPORT_COMPILER_H
+
+#include "llvm/Config/llvm-config.h"
+
+#ifdef __cplusplus
+#include <new>
+#endif
+#include <stddef.h>
+
+#if defined(_MSC_VER)
+#include <sal.h>
+#endif
+
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+#ifndef __has_extension
+# define __has_extension(x) 0
+#endif
+
+#ifndef __has_attribute
+# define __has_attribute(x) 0
+#endif
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+// Only use __has_cpp_attribute in C++ mode. GCC defines __has_cpp_attribute in
+// C mode, but the :: in __has_cpp_attribute(scoped::attribute) is invalid.
+#ifndef LLVM_HAS_CPP_ATTRIBUTE
+#if defined(__cplusplus) && defined(__has_cpp_attribute)
+# define LLVM_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+# define LLVM_HAS_CPP_ATTRIBUTE(x) 0
+#endif
+#endif
+
+/// \macro LLVM_GNUC_PREREQ
+/// Extend the default __GNUC_PREREQ even if glibc's features.h isn't
+/// available.
+#ifndef LLVM_GNUC_PREREQ
+# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+# define LLVM_GNUC_PREREQ(maj, min, patch) \
+ ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
+ ((maj) << 20) + ((min) << 10) + (patch))
+# elif defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define LLVM_GNUC_PREREQ(maj, min, patch) \
+ ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
+# else
+# define LLVM_GNUC_PREREQ(maj, min, patch) 0
+# endif
+#endif
+
+/// \macro LLVM_MSC_PREREQ
+/// Is the compiler MSVC of at least the specified version?
+/// The common \param version values to check for are:
+/// * 1910: VS2017, version 15.1 & 15.2
+/// * 1911: VS2017, version 15.3 & 15.4
+/// * 1912: VS2017, version 15.5
+/// * 1913: VS2017, version 15.6
+/// * 1914: VS2017, version 15.7
+/// * 1915: VS2017, version 15.8
+/// * 1916: VS2017, version 15.9
+/// * 1920: VS2019, version 16.0
+/// * 1921: VS2019, version 16.1
+#ifdef _MSC_VER
+#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version))
+
+// We require at least MSVC 2017.
+#if !LLVM_MSC_PREREQ(1910)
+#error LLVM requires at least MSVC 2017.
+#endif
+
+#else
+#define LLVM_MSC_PREREQ(version) 0
+#endif
+
+/// Does the compiler support ref-qualifiers for *this?
+///
+/// Sadly, this is separate from just rvalue reference support because GCC
+/// and MSVC implemented this later than everything else.
+#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1)
+#define LLVM_HAS_RVALUE_REFERENCE_THIS 1
+#else
+#define LLVM_HAS_RVALUE_REFERENCE_THIS 0
+#endif
+
+/// Expands to '&' if ref-qualifiers for *this are supported.
+///
+/// This can be used to provide lvalue/rvalue overrides of member functions.
+/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+#define LLVM_LVALUE_FUNCTION &
+#else
+#define LLVM_LVALUE_FUNCTION
+#endif
+
+/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked
+/// into a shared library, then the class should be private to the library and
+/// not accessible from outside it. Can also be used to mark variables and
+/// functions, making them private to any shared library they are linked into.
+/// On PE/COFF targets, library visibility is the default, so this isn't needed.
+#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \
+ !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32)
+#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
+#else
+#define LLVM_LIBRARY_VISIBILITY
+#endif
+
+#if defined(__GNUC__)
+#define LLVM_PREFETCH(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
+#else
+#define LLVM_PREFETCH(addr, rw, locality)
+#endif
+
+#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0)
+#define LLVM_ATTRIBUTE_USED __attribute__((__used__))
+#else
+#define LLVM_ATTRIBUTE_USED
+#endif
+
+/// LLVM_NODISCARD - Warn if a type or return value is discarded.
+
+// Use the 'nodiscard' attribute in C++17 or newer mode.
+#if __cplusplus > 201402L && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)
+#define LLVM_NODISCARD [[nodiscard]]
+#elif LLVM_HAS_CPP_ATTRIBUTE(clang::warn_unused_result)
+#define LLVM_NODISCARD [[clang::warn_unused_result]]
+// Clang in C++14 mode claims that it has the 'nodiscard' attribute, but also
+// warns in the pedantic mode that 'nodiscard' is a C++17 extension (PR33518).
+// Use the 'nodiscard' attribute in C++14 mode only with GCC.
+// TODO: remove this workaround when PR33518 is resolved.
+#elif defined(__GNUC__) && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)
+#define LLVM_NODISCARD [[nodiscard]]
+#else
+#define LLVM_NODISCARD
+#endif
+
+// Indicate that a non-static, non-const C++ member function reinitializes
+// the entire object to a known state, independent of the previous state of
+// the object.
+//
+// The clang-tidy check bugprone-use-after-move recognizes this attribute as a
+// marker that a moved-from object has left the indeterminate state and can be
+// reused.
+#if LLVM_HAS_CPP_ATTRIBUTE(clang::reinitializes)
+#define LLVM_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]
+#else
+#define LLVM_ATTRIBUTE_REINITIALIZES
+#endif
+
+// Some compilers warn about unused functions. When a function is sometimes
+// used or not depending on build settings (e.g. a function only called from
+// within "assert"), this attribute can be used to suppress such warnings.
+//
+// However, it shouldn't be used for unused *variables*, as those have a much
+// more portable solution:
+// (void)unused_var_name;
+// Prefer cast-to-void wherever it is sufficient.
+#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0)
+#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+#define LLVM_ATTRIBUTE_UNUSED
+#endif
+
+// FIXME: Provide this for PE/COFF targets.
+#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \
+ (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32))
+#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__))
+#else
+#define LLVM_ATTRIBUTE_WEAK
+#endif
+
+// Prior to clang 3.2, clang did not accept any spelling of
+// __has_attribute(const), so assume it is supported.
+#if defined(__clang__) || defined(__GNUC__)
+// aka 'CONST' but following LLVM Conventions.
+#define LLVM_READNONE __attribute__((__const__))
+#else
+#define LLVM_READNONE
+#endif
+
+#if __has_attribute(pure) || defined(__GNUC__)
+// aka 'PURE' but following LLVM Conventions.
+#define LLVM_READONLY __attribute__((__pure__))
+#else
+#define LLVM_READONLY
+#endif
+
+#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0)
+#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true)
+#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false)
+#else
+#define LLVM_LIKELY(EXPR) (EXPR)
+#define LLVM_UNLIKELY(EXPR) (EXPR)
+#endif
+
+/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so,
+/// mark a method "not for inlining".
+#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0)
+#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline)
+#else
+#define LLVM_ATTRIBUTE_NOINLINE
+#endif
+
+/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do
+/// so, mark a method "always inline" because it is performance sensitive. GCC
+/// 3.4 supported this but is buggy in various cases and produces unimplemented
+/// errors, just use it in GCC 4.0 and later.
+#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0)
+#define LLVM_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline
+#else
+#define LLVM_ATTRIBUTE_ALWAYS_INLINE
+#endif
+
+#ifdef __GNUC__
+#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn)
+#else
+#define LLVM_ATTRIBUTE_NORETURN
+#endif
+
+#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0)
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL _Ret_notnull_
+#else
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL
+#endif
+
+/// \macro LLVM_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a
+/// pointer that does not alias any other valid pointer.
+#ifdef __GNUC__
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict)
+#else
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS
+#endif
+
+/// LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
+#if __cplusplus > 201402L && LLVM_HAS_CPP_ATTRIBUTE(fallthrough)
+#define LLVM_FALLTHROUGH [[fallthrough]]
+#elif LLVM_HAS_CPP_ATTRIBUTE(gnu::fallthrough)
+#define LLVM_FALLTHROUGH [[gnu::fallthrough]]
+#elif __has_attribute(fallthrough)
+#define LLVM_FALLTHROUGH __attribute__((fallthrough))
+#elif LLVM_HAS_CPP_ATTRIBUTE(clang::fallthrough)
+#define LLVM_FALLTHROUGH [[clang::fallthrough]]
+#else
+#define LLVM_FALLTHROUGH
+#endif
+
+/// LLVM_REQUIRE_CONSTANT_INITIALIZATION - Apply this to globals to ensure that
+/// they are constant initialized.
+#if LLVM_HAS_CPP_ATTRIBUTE(clang::require_constant_initialization)
+#define LLVM_REQUIRE_CONSTANT_INITIALIZATION \
+ [[clang::require_constant_initialization]]
+#else
+#define LLVM_REQUIRE_CONSTANT_INITIALIZATION
+#endif
+
+/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
+/// pedantic diagnostics.
+#ifdef __GNUC__
+#define LLVM_EXTENSION __extension__
+#else
+#define LLVM_EXTENSION
+#endif
+
+// LLVM_ATTRIBUTE_DEPRECATED(decl, "message")
+#if __has_feature(attribute_deprecated_with_message)
+# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
+ decl __attribute__((deprecated(message)))
+#elif defined(__GNUC__)
+# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
+ decl __attribute__((deprecated))
+#elif defined(_MSC_VER)
+# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
+ __declspec(deprecated(message)) decl
+#else
+# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
+ decl
+#endif
+
+/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands
+/// to an expression which states that it is undefined behavior for the
+/// compiler to reach this point. Otherwise is not defined.
+#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0)
+# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
+#elif defined(_MSC_VER)
+# define LLVM_BUILTIN_UNREACHABLE __assume(false)
+#endif
+
+/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression
+/// which causes the program to exit abnormally.
+#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0)
+# define LLVM_BUILTIN_TRAP __builtin_trap()
+#elif defined(_MSC_VER)
+// The __debugbreak intrinsic is supported by MSVC, does not require forward
+// declarations involving platform-specific typedefs (unlike RaiseException),
+// results in a call to vectored exception handlers, and encodes to a short
+// instruction that still causes the trapping behavior we want.
+# define LLVM_BUILTIN_TRAP __debugbreak()
+#else
+# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0
+#endif
+
+/// LLVM_BUILTIN_DEBUGTRAP - On compilers which support it, expands to
+/// an expression which causes the program to break while running
+/// under a debugger.
+#if __has_builtin(__builtin_debugtrap)
+# define LLVM_BUILTIN_DEBUGTRAP __builtin_debugtrap()
+#elif defined(_MSC_VER)
+// The __debugbreak intrinsic is supported by MSVC and breaks while
+// running under the debugger, and also supports invoking a debugger
+// when the OS is configured appropriately.
+# define LLVM_BUILTIN_DEBUGTRAP __debugbreak()
+#else
+// Just continue execution when built with compilers that have no
+// support. This is a debugging aid and not intended to force the
+// program to abort if encountered.
+# define LLVM_BUILTIN_DEBUGTRAP
+#endif
+
+/// \macro LLVM_ASSUME_ALIGNED
+/// Returns a pointer with an assumed alignment.
+#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0)
+# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a)
+#elif defined(LLVM_BUILTIN_UNREACHABLE)
+// As of today, clang does not support __builtin_assume_aligned.
+# define LLVM_ASSUME_ALIGNED(p, a) \
+ (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p)))
+#else
+# define LLVM_ASSUME_ALIGNED(p, a) (p)
+#endif
+
+/// \macro LLVM_PACKED
+/// Used to specify a packed structure.
+/// LLVM_PACKED(
+/// struct A {
+/// int i;
+/// int j;
+/// int k;
+/// long long l;
+/// });
+///
+/// LLVM_PACKED_START
+/// struct B {
+/// int i;
+/// int j;
+/// int k;
+/// long long l;
+/// };
+/// LLVM_PACKED_END
+#ifdef _MSC_VER
+# define LLVM_PACKED(d) __pragma(pack(push, 1)) d __pragma(pack(pop))
+# define LLVM_PACKED_START __pragma(pack(push, 1))
+# define LLVM_PACKED_END __pragma(pack(pop))
+#else
+# define LLVM_PACKED(d) d __attribute__((packed))
+# define LLVM_PACKED_START _Pragma("pack(push, 1)")
+# define LLVM_PACKED_END _Pragma("pack(pop)")
+#endif
+
+/// \macro LLVM_PTR_SIZE
+/// A constant integer equivalent to the value of sizeof(void*).
+/// Generally used in combination with alignas or when doing computation in the
+/// preprocessor.
+#ifdef __SIZEOF_POINTER__
+# define LLVM_PTR_SIZE __SIZEOF_POINTER__
+#elif defined(_WIN64)
+# define LLVM_PTR_SIZE 8
+#elif defined(_WIN32)
+# define LLVM_PTR_SIZE 4
+#elif defined(_MSC_VER)
+# error "could not determine LLVM_PTR_SIZE as a constant int for MSVC"
+#else
+# define LLVM_PTR_SIZE sizeof(void *)
+#endif
+
+/// \macro LLVM_MEMORY_SANITIZER_BUILD
+/// Whether LLVM itself is built with MemorySanitizer instrumentation.
+#if __has_feature(memory_sanitizer)
+# define LLVM_MEMORY_SANITIZER_BUILD 1
+# include <sanitizer/msan_interface.h>
+#else
+# define LLVM_MEMORY_SANITIZER_BUILD 0
+# define __msan_allocated_memory(p, size)
+# define __msan_unpoison(p, size)
+#endif
+
+/// \macro LLVM_ADDRESS_SANITIZER_BUILD
+/// Whether LLVM itself is built with AddressSanitizer instrumentation.
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+# define LLVM_ADDRESS_SANITIZER_BUILD 1
+# include <sanitizer/asan_interface.h>
+#else
+# define LLVM_ADDRESS_SANITIZER_BUILD 0
+# define __asan_poison_memory_region(p, size)
+# define __asan_unpoison_memory_region(p, size)
+#endif
+
+/// \macro LLVM_THREAD_SANITIZER_BUILD
+/// Whether LLVM itself is built with ThreadSanitizer instrumentation.
+#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
+# define LLVM_THREAD_SANITIZER_BUILD 1
+#else
+# define LLVM_THREAD_SANITIZER_BUILD 0
+#endif
+
+#if LLVM_THREAD_SANITIZER_BUILD
+// Thread Sanitizer is a tool that finds races in code.
+// See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations .
+// tsan detects these exact functions by name.
+#ifdef __cplusplus
+extern "C" {
+#endif
+void AnnotateHappensAfter(const char *file, int line, const volatile void *cv);
+void AnnotateHappensBefore(const char *file, int line, const volatile void *cv);
+void AnnotateIgnoreWritesBegin(const char *file, int line);
+void AnnotateIgnoreWritesEnd(const char *file, int line);
+#ifdef __cplusplus
+}
+#endif
+
+// This marker is used to define a happens-before arc. The race detector will
+// infer an arc from the begin to the end when they share the same pointer
+// argument.
+# define TsanHappensBefore(cv) AnnotateHappensBefore(__FILE__, __LINE__, cv)
+
+// This marker defines the destination of a happens-before arc.
+# define TsanHappensAfter(cv) AnnotateHappensAfter(__FILE__, __LINE__, cv)
+
+// Ignore any races on writes between here and the next TsanIgnoreWritesEnd.
+# define TsanIgnoreWritesBegin() AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+
+// Resume checking for racy writes.
+# define TsanIgnoreWritesEnd() AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+#else
+# define TsanHappensBefore(cv)
+# define TsanHappensAfter(cv)
+# define TsanIgnoreWritesBegin()
+# define TsanIgnoreWritesEnd()
+#endif
+
+/// \macro LLVM_NO_SANITIZE
+/// Disable a particular sanitizer for a function.
+#if __has_attribute(no_sanitize)
+#define LLVM_NO_SANITIZE(KIND) __attribute__((no_sanitize(KIND)))
+#else
+#define LLVM_NO_SANITIZE(KIND)
+#endif
+
+/// Mark debug helper function definitions like dump() that should not be
+/// stripped from debug builds.
+/// Note that you should also surround dump() functions with
+/// `#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)` so they do always
+/// get stripped in release builds.
+// FIXME: Move this to a private config.h as it's not usable in public headers.
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED
+#else
+#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE
+#endif
+
+/// \macro LLVM_PRETTY_FUNCTION
+/// Gets a user-friendly looking function signature for the current scope
+/// using the best available method on each platform. The exact format of the
+/// resulting string is implementation specific and non-portable, so this should
+/// only be used, for example, for logging or diagnostics.
+#if defined(_MSC_VER)
+#define LLVM_PRETTY_FUNCTION __FUNCSIG__
+#elif defined(__GNUC__) || defined(__clang__)
+#define LLVM_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#else
+#define LLVM_PRETTY_FUNCTION __func__
+#endif
+
+/// \macro LLVM_THREAD_LOCAL
+/// A thread-local storage specifier which can be used with globals,
+/// extern globals, and static globals.
+///
+/// This is essentially an extremely restricted analog to C++11's thread_local
+/// support, and uses that when available. However, it falls back on
+/// platform-specific or vendor-provided extensions when necessary. These
+/// extensions don't support many of the C++11 thread_local's features. You
+/// should only use this for PODs that you can statically initialize to
+/// some constant value. In almost all circumstances this is most appropriate
+/// for use with a pointer, integer, or small aggregation of pointers and
+/// integers.
+#if LLVM_ENABLE_THREADS
+#if __has_feature(cxx_thread_local)
+#define LLVM_THREAD_LOCAL thread_local
+#elif defined(_MSC_VER)
+// MSVC supports this with a __declspec.
+#define LLVM_THREAD_LOCAL __declspec(thread)
+#else
+// Clang, GCC, and other compatible compilers used __thread prior to C++11 and
+// we only need the restricted functionality that provides.
+#define LLVM_THREAD_LOCAL __thread
+#endif
+#else // !LLVM_ENABLE_THREADS
+// If threading is disabled entirely, this compiles to nothing and you get
+// a normal global variable.
+#define LLVM_THREAD_LOCAL
+#endif
+
+/// \macro LLVM_ENABLE_EXCEPTIONS
+/// Whether LLVM is built with exception support.
+#if __has_feature(cxx_exceptions)
+#define LLVM_ENABLE_EXCEPTIONS 1
+#elif defined(__GNUC__) && defined(__EXCEPTIONS)
+#define LLVM_ENABLE_EXCEPTIONS 1
+#elif defined(_MSC_VER) && defined(_CPPUNWIND)
+#define LLVM_ENABLE_EXCEPTIONS 1
+#endif
+
+#ifdef __cplusplus
+namespace llvm {
+
+/// Allocate a buffer of memory with the given size and alignment.
+///
+/// When the compiler supports aligned operator new, this will use it to to
+/// handle even over-aligned allocations.
+///
+/// However, this doesn't make any attempt to leverage the fancier techniques
+/// like posix_memalign due to portability. It is mostly intended to allow
+/// compatibility with platforms that, after aligned allocation was added, use
+/// reduced default alignment.
+inline void *allocate_buffer(size_t Size, size_t Alignment) {
+ return ::operator new(Size
+#ifdef __cpp_aligned_new
+ ,
+ std::align_val_t(Alignment)
+#endif
+ );
+}
+
+/// Deallocate a buffer of memory with the given size and alignment.
+///
+/// If supported, this will used the sized delete operator. Also if supported,
+/// this will pass the alignment to the delete operator.
+///
+/// The pointer must have been allocated with the corresponding new operator,
+/// most likely using the above helper.
+inline void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) {
+ ::operator delete(Ptr
+#ifdef __cpp_sized_deallocation
+ ,
+ Size
+#endif
+#ifdef __cpp_aligned_new
+ ,
+ std::align_val_t(Alignment)
+#endif
+ );
+}
+
+} // End namespace llvm
+
+#endif // __cplusplus
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/ConvertUTF.h b/third_party/llvm-project/include/llvm/Support/ConvertUTF.h
new file mode 100644
index 000000000..1add18533
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/ConvertUTF.h
@@ -0,0 +1,306 @@
+/*===--- ConvertUTF.h - Universal Character Names conversions ---------------===
+ *
+ * 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
+ *
+ *==------------------------------------------------------------------------==*/
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* ---------------------------------------------------------------------
+
+ Conversions between UTF32, UTF-16, and UTF-8. Header file.
+
+ Several funtions are included here, forming a complete set of
+ conversions between the three formats. UTF-7 is not included
+ here, but is handled in a separate source file.
+
+ Each of these routines takes pointers to input buffers and output
+ buffers. The input buffers are const.
+
+ Each routine converts the text between *sourceStart and sourceEnd,
+ putting the result into the buffer between *targetStart and
+ targetEnd. Note: the end pointers are *after* the last item: e.g.
+ *(sourceEnd - 1) is the last item.
+
+ The return result indicates whether the conversion was successful,
+ and if not, whether the problem was in the source or target buffers.
+ (Only the first encountered problem is indicated.)
+
+ After the conversion, *sourceStart and *targetStart are both
+ updated to point to the end of last text successfully converted in
+ the respective buffers.
+
+ Input parameters:
+ sourceStart - pointer to a pointer to the source buffer.
+ The contents of this are modified on return so that
+ it points at the next thing to be converted.
+ targetStart - similarly, pointer to pointer to the target buffer.
+ sourceEnd, targetEnd - respectively pointers to the ends of the
+ two buffers, for overflow checking only.
+
+ These conversion functions take a ConversionFlags argument. When this
+ flag is set to strict, both irregular sequences and isolated surrogates
+ will cause an error. When the flag is set to lenient, both irregular
+ sequences and isolated surrogates are converted.
+
+ Whether the flag is strict or lenient, all illegal sequences will cause
+ an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
+ or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
+ must check for illegal sequences.
+
+ When the flag is set to lenient, characters over 0x10FFFF are converted
+ to the replacement character; otherwise (when the flag is set to strict)
+ they constitute an error.
+
+ Output parameters:
+ The value "sourceIllegal" is returned from some routines if the input
+ sequence is malformed. When "sourceIllegal" is returned, the source
+ value will point to the illegal value that caused the problem. E.g.,
+ in UTF-8 when a sequence is malformed, it points to the start of the
+ malformed sequence.
+
+ Author: Mark E. Davis, 1994.
+ Rev History: Rick McGowan, fixes & updates May 2001.
+ Fixes & updates, Sept 2001.
+
+------------------------------------------------------------------------ */
+
+#ifndef LLVM_SUPPORT_CONVERTUTF_H
+#define LLVM_SUPPORT_CONVERTUTF_H
+
+#include <cstddef>
+#include <string>
+#include <system_error>
+
+// Wrap everything in namespace llvm so that programs can link with llvm and
+// their own version of the unicode libraries.
+
+namespace llvm {
+
+/* ---------------------------------------------------------------------
+ The following 4 definitions are compiler-specific.
+ The C standard does not guarantee that wchar_t has at least
+ 16 bits, so wchar_t is no less portable than unsigned short!
+ All should be unsigned values to avoid sign extension during
+ bit mask & shift operations.
+------------------------------------------------------------------------ */
+
+typedef unsigned int UTF32; /* at least 32 bits */
+typedef unsigned short UTF16; /* at least 16 bits */
+typedef unsigned char UTF8; /* typically 8 bits */
+typedef unsigned char Boolean; /* 0 or 1 */
+
+/* Some fundamental constants */
+#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
+#define UNI_MAX_BMP (UTF32)0x0000FFFF
+#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
+#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
+#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
+
+#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4
+
+#define UNI_UTF16_BYTE_ORDER_MARK_NATIVE 0xFEFF
+#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED 0xFFFE
+
+typedef enum {
+ conversionOK, /* conversion successful */
+ sourceExhausted, /* partial character in source, but hit end */
+ targetExhausted, /* insuff. room in target for conversion */
+ sourceIllegal /* source sequence is illegal/malformed */
+} ConversionResult;
+
+typedef enum {
+ strictConversion = 0,
+ lenientConversion
+} ConversionFlags;
+
+ConversionResult ConvertUTF8toUTF16 (
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+
+/**
+ * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an
+ * incomplete code unit sequence, returns \c sourceExhausted.
+ */
+ConversionResult ConvertUTF8toUTF32Partial(
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+/**
+ * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an
+ * incomplete code unit sequence, returns \c sourceIllegal.
+ */
+ConversionResult ConvertUTF8toUTF32(
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF16toUTF8 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF8 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF16toUTF32 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF16 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+
+Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
+
+Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd);
+
+unsigned getNumBytesForUTF8(UTF8 firstByte);
+
+/*************************************************************************/
+/* Below are LLVM-specific wrappers of the functions above. */
+
+template <typename T> class ArrayRef;
+template <typename T> class SmallVectorImpl;
+class StringRef;
+
+/**
+ * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on
+ * WideCharWidth. The converted data is written to ResultPtr, which needs to
+ * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success,
+ * ResultPtr will point one after the end of the copied string. On failure,
+ * ResultPtr will not be changed, and ErrorPtr will be set to the location of
+ * the first character which could not be converted.
+ * \return true on success.
+ */
+bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source,
+ char *&ResultPtr, const UTF8 *&ErrorPtr);
+
+/**
+* Converts a UTF-8 StringRef to a std::wstring.
+* \return true on success.
+*/
+bool ConvertUTF8toWide(llvm::StringRef Source, std::wstring &Result);
+
+/**
+* Converts a UTF-8 C-string to a std::wstring.
+* \return true on success.
+*/
+bool ConvertUTF8toWide(const char *Source, std::wstring &Result);
+
+/**
+* Converts a std::wstring to a UTF-8 encoded std::string.
+* \return true on success.
+*/
+bool convertWideToUTF8(const std::wstring &Source, std::string &Result);
+
+
+/**
+ * Convert an Unicode code point to UTF8 sequence.
+ *
+ * \param Source a Unicode code point.
+ * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least
+ * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is
+ * updated one past end of the converted sequence.
+ *
+ * \returns true on success.
+ */
+bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr);
+
+/**
+ * Convert the first UTF8 sequence in the given source buffer to a UTF32
+ * code point.
+ *
+ * \param [in,out] source A pointer to the source buffer. If the conversion
+ * succeeds, this pointer will be updated to point to the byte just past the
+ * end of the converted sequence.
+ * \param sourceEnd A pointer just past the end of the source buffer.
+ * \param [out] target The converted code
+ * \param flags Whether the conversion is strict or lenient.
+ *
+ * \returns conversionOK on success
+ *
+ * \sa ConvertUTF8toUTF32
+ */
+inline ConversionResult convertUTF8Sequence(const UTF8 **source,
+ const UTF8 *sourceEnd,
+ UTF32 *target,
+ ConversionFlags flags) {
+ if (*source == sourceEnd)
+ return sourceExhausted;
+ unsigned size = getNumBytesForUTF8(**source);
+ if ((ptrdiff_t)size > sourceEnd - *source)
+ return sourceExhausted;
+ return ConvertUTF8toUTF32(source, *source + size, &target, target + 1, flags);
+}
+
+/**
+ * Returns true if a blob of text starts with a UTF-16 big or little endian byte
+ * order mark.
+ */
+bool hasUTF16ByteOrderMark(ArrayRef<char> SrcBytes);
+
+/**
+ * Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string.
+ *
+ * \param [in] SrcBytes A buffer of what is assumed to be UTF-16 encoded text.
+ * \param [out] Out Converted UTF-8 is stored here on success.
+ * \returns true on success
+ */
+bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out);
+
+/**
+* Converts a UTF16 string into a UTF8 std::string.
+*
+* \param [in] Src A buffer of UTF-16 encoded text.
+* \param [out] Out Converted UTF-8 is stored here on success.
+* \returns true on success
+*/
+bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out);
+
+/**
+ * Converts a UTF-8 string into a UTF-16 string with native endianness.
+ *
+ * \returns true on success
+ */
+bool convertUTF8ToUTF16String(StringRef SrcUTF8,
+ SmallVectorImpl<UTF16> &DstUTF16);
+
+#if defined(_WIN32)
+namespace sys {
+namespace windows {
+std::error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16);
+/// Convert to UTF16 from the current code page used in the system
+std::error_code CurCPToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16);
+std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
+ SmallVectorImpl<char> &utf8);
+/// Convert from UTF16 to the current code page used in the system
+std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
+ SmallVectorImpl<char> &utf8);
+} // namespace windows
+} // namespace sys
+#endif
+
+} /* end namespace llvm */
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/DJB.h b/third_party/llvm-project/include/llvm/Support/DJB.h
new file mode 100644
index 000000000..8a04a324a
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/DJB.h
@@ -0,0 +1,32 @@
+//===-- llvm/Support/DJB.h ---DJB Hash --------------------------*- 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 support for the DJ Bernstein hash function.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_DJB_H
+#define LLVM_SUPPORT_DJB_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+/// The Bernstein hash function used by the DWARF accelerator tables.
+inline uint32_t djbHash(StringRef Buffer, uint32_t H = 5381) {
+ for (unsigned char C : Buffer.bytes())
+ H = (H << 5) + H + C;
+ return H;
+}
+
+/// Computes the Bernstein hash after folding the input according to the Dwarf 5
+/// standard case folding rules.
+uint32_t caseFoldingDjbHash(StringRef Buffer, uint32_t H = 5381);
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_DJB_H
diff --git a/third_party/llvm-project/include/llvm/Support/DataExtractor.h b/third_party/llvm-project/include/llvm/Support/DataExtractor.h
new file mode 100644
index 000000000..f590a1e10
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/DataExtractor.h
@@ -0,0 +1,575 @@
+//===-- DataExtractor.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_DATAEXTRACTOR_H
+#define LLVM_SUPPORT_DATAEXTRACTOR_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+
+/// An auxiliary type to facilitate extraction of 3-byte entities.
+struct Uint24 {
+ uint8_t Bytes[3];
+ Uint24(uint8_t U) {
+ Bytes[0] = Bytes[1] = Bytes[2] = U;
+ }
+ Uint24(uint8_t U0, uint8_t U1, uint8_t U2) {
+ Bytes[0] = U0; Bytes[1] = U1; Bytes[2] = U2;
+ }
+ uint32_t getAsUint32(bool IsLittleEndian) const {
+ int LoIx = IsLittleEndian ? 0 : 2;
+ return Bytes[LoIx] + (Bytes[1] << 8) + (Bytes[2-LoIx] << 16);
+ }
+};
+
+using uint24_t = Uint24;
+static_assert(sizeof(uint24_t) == 3, "sizeof(uint24_t) != 3");
+
+/// Needed by swapByteOrder().
+inline uint24_t getSwappedBytes(uint24_t C) {
+ return uint24_t(C.Bytes[2], C.Bytes[1], C.Bytes[0]);
+}
+
+class DataExtractor {
+ StringRef Data;
+ uint8_t IsLittleEndian;
+ uint8_t AddressSize;
+public:
+ /// A class representing a position in a DataExtractor, as well as any error
+ /// encountered during extraction. It enables one to extract a sequence of
+ /// values without error-checking and then checking for errors in bulk at the
+ /// end. The class holds an Error object, so failing to check the result of
+ /// the parse will result in a runtime error. The error flag is sticky and
+ /// will cause all subsequent extraction functions to fail without even
+ /// attempting to parse and without updating the Cursor offset. After clearing
+ /// the error flag, one can again use the Cursor object for parsing.
+ class Cursor {
+ uint64_t Offset;
+ Error Err;
+
+ friend class DataExtractor;
+
+ public:
+ /// Construct a cursor for extraction from the given offset.
+ explicit Cursor(uint64_t Offset) : Offset(Offset), Err(Error::success()) {}
+
+ /// Checks whether the cursor is valid (i.e. no errors were encountered). In
+ /// case of errors, this does not clear the error flag -- one must call
+ /// takeError() instead.
+ explicit operator bool() { return !Err; }
+
+ /// Return the current position of this Cursor. In the error state this is
+ /// the position of the Cursor before the first error was encountered.
+ uint64_t tell() const { return Offset; }
+
+ /// Return error contained inside this Cursor, if any. Clears the internal
+ /// Cursor state.
+ Error takeError() { return std::move(Err); }
+ };
+
+ /// Construct with a buffer that is owned by the caller.
+ ///
+ /// This constructor allows us to use data that is owned by the
+ /// caller. The data must stay around as long as this object is
+ /// valid.
+ DataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize)
+ : Data(Data), IsLittleEndian(IsLittleEndian), AddressSize(AddressSize) {}
+ DataExtractor(ArrayRef<uint8_t> Data, bool IsLittleEndian,
+ uint8_t AddressSize)
+ : Data(StringRef(reinterpret_cast<const char *>(Data.data()),
+ Data.size())),
+ IsLittleEndian(IsLittleEndian), AddressSize(AddressSize) {}
+
+ /// Get the data pointed to by this extractor.
+ StringRef getData() const { return Data; }
+ /// Get the endianness for this extractor.
+ bool isLittleEndian() const { return IsLittleEndian; }
+ /// Get the address size for this extractor.
+ uint8_t getAddressSize() const { return AddressSize; }
+ /// Set the address size for this extractor.
+ void setAddressSize(uint8_t Size) { AddressSize = Size; }
+
+ /// Extract a C string from \a *offset_ptr.
+ ///
+ /// Returns a pointer to a C String from the data at the offset
+ /// pointed to by \a offset_ptr. A variable length NULL terminated C
+ /// string will be extracted and the \a offset_ptr will be
+ /// updated with the offset of the byte that follows the NULL
+ /// terminator byte.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @return
+ /// A pointer to the C string value in the data. If the offset
+ /// pointed to by \a offset_ptr is out of bounds, or if the
+ /// offset plus the length of the C string is out of bounds,
+ /// NULL will be returned.
+ const char *getCStr(uint64_t *offset_ptr) const;
+
+ /// Extract a C string from \a *offset_ptr.
+ ///
+ /// Returns a StringRef for the C String from the data at the offset
+ /// pointed to by \a offset_ptr. A variable length NULL terminated C
+ /// string will be extracted and the \a offset_ptr will be
+ /// updated with the offset of the byte that follows the NULL
+ /// terminator byte.
+ ///
+ /// \param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// \return
+ /// A StringRef for the C string value in the data. If the offset
+ /// pointed to by \a offset_ptr is out of bounds, or if the
+ /// offset plus the length of the C string is out of bounds,
+ /// a default-initialized StringRef will be returned.
+ StringRef getCStrRef(uint64_t *offset_ptr) const;
+
+ /// Extract an unsigned integer of size \a byte_size from \a
+ /// *offset_ptr.
+ ///
+ /// Extract a single unsigned integer value and update the offset
+ /// pointed to by \a offset_ptr. The size of the extracted integer
+ /// is specified by the \a byte_size argument. \a byte_size should
+ /// have a value greater than or equal to one and less than or equal
+ /// to eight since the return value is 64 bits wide. Any
+ /// \a byte_size values less than 1 or greater than 8 will result in
+ /// nothing being extracted, and zero being returned.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @param[in] byte_size
+ /// The size in byte of the integer to extract.
+ ///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
+ /// @return
+ /// The unsigned integer value that was extracted, or zero on
+ /// failure.
+ uint64_t getUnsigned(uint64_t *offset_ptr, uint32_t byte_size,
+ Error *Err = nullptr) const;
+
+ /// Extract an unsigned integer of the given size from the location given by
+ /// the cursor. In case of an extraction error, or if the cursor is already in
+ /// an error state, zero is returned.
+ uint64_t getUnsigned(Cursor &C, uint32_t Size) const {
+ return getUnsigned(&C.Offset, Size, &C.Err);
+ }
+
+ /// Extract an signed integer of size \a byte_size from \a *offset_ptr.
+ ///
+ /// Extract a single signed integer value (sign extending if required)
+ /// and update the offset pointed to by \a offset_ptr. The size of
+ /// the extracted integer is specified by the \a byte_size argument.
+ /// \a byte_size should have a value greater than or equal to one
+ /// and less than or equal to eight since the return value is 64
+ /// bits wide. Any \a byte_size values less than 1 or greater than
+ /// 8 will result in nothing being extracted, and zero being returned.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @param[in] size
+ /// The size in bytes of the integer to extract.
+ ///
+ /// @return
+ /// The sign extended signed integer value that was extracted,
+ /// or zero on failure.
+ int64_t getSigned(uint64_t *offset_ptr, uint32_t size) const;
+
+ //------------------------------------------------------------------
+ /// Extract an pointer from \a *offset_ptr.
+ ///
+ /// Extract a single pointer from the data and update the offset
+ /// pointed to by \a offset_ptr. The size of the extracted pointer
+ /// is \a getAddressSize(), so the address size has to be
+ /// set correctly prior to extracting any pointer values.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @return
+ /// The extracted pointer value as a 64 integer.
+ uint64_t getAddress(uint64_t *offset_ptr) const {
+ return getUnsigned(offset_ptr, AddressSize);
+ }
+
+ /// Extract a pointer-sized unsigned integer from the location given by the
+ /// cursor. In case of an extraction error, or if the cursor is already in
+ /// an error state, zero is returned.
+ uint64_t getAddress(Cursor &C) const { return getUnsigned(C, AddressSize); }
+
+ /// Extract a uint8_t value from \a *offset_ptr.
+ ///
+ /// Extract a single uint8_t from the binary data at the offset
+ /// pointed to by \a offset_ptr, and advance the offset on success.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
+ /// @return
+ /// The extracted uint8_t value.
+ uint8_t getU8(uint64_t *offset_ptr, Error *Err = nullptr) const;
+
+ /// Extract a single uint8_t value from the location given by the cursor. In
+ /// case of an extraction error, or if the cursor is already in an error
+ /// state, zero is returned.
+ uint8_t getU8(Cursor &C) const { return getU8(&C.Offset, &C.Err); }
+
+ /// Extract \a count uint8_t values from \a *offset_ptr.
+ ///
+ /// Extract \a count uint8_t values from the binary data at the
+ /// offset pointed to by \a offset_ptr, and advance the offset on
+ /// success. The extracted values are copied into \a dst.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @param[out] dst
+ /// A buffer to copy \a count uint8_t values into. \a dst must
+ /// be large enough to hold all requested data.
+ ///
+ /// @param[in] count
+ /// The number of uint8_t values to extract.
+ ///
+ /// @return
+ /// \a dst if all values were properly extracted and copied,
+ /// NULL otherise.
+ uint8_t *getU8(uint64_t *offset_ptr, uint8_t *dst, uint32_t count) const;
+
+ /// Extract \a Count uint8_t values from the location given by the cursor and
+ /// store them into the destination buffer. In case of an extraction error, or
+ /// if the cursor is already in an error state, a nullptr is returned and the
+ /// destination buffer is left unchanged.
+ uint8_t *getU8(Cursor &C, uint8_t *Dst, uint32_t Count) const;
+
+ /// Extract \a Count uint8_t values from the location given by the cursor and
+ /// store them into the destination vector. The vector is resized to fit the
+ /// extracted data. In case of an extraction error, or if the cursor is
+ /// already in an error state, the destination vector is left unchanged and
+ /// cursor is placed into an error state.
+ void getU8(Cursor &C, SmallVectorImpl<uint8_t> &Dst, uint32_t Count) const {
+ if (isValidOffsetForDataOfSize(C.Offset, Count))
+ Dst.resize(Count);
+
+ // This relies on the fact that getU8 will not attempt to write to the
+ // buffer if isValidOffsetForDataOfSize(C.Offset, Count) is false.
+ getU8(C, Dst.data(), Count);
+ }
+
+ //------------------------------------------------------------------
+ /// Extract a uint16_t value from \a *offset_ptr.
+ ///
+ /// Extract a single uint16_t from the binary data at the offset
+ /// pointed to by \a offset_ptr, and update the offset on success.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
+ /// @return
+ /// The extracted uint16_t value.
+ //------------------------------------------------------------------
+ uint16_t getU16(uint64_t *offset_ptr, Error *Err = nullptr) const;
+
+ /// Extract a single uint16_t value from the location given by the cursor. In
+ /// case of an extraction error, or if the cursor is already in an error
+ /// state, zero is returned.
+ uint16_t getU16(Cursor &C) const { return getU16(&C.Offset, &C.Err); }
+
+ /// Extract \a count uint16_t values from \a *offset_ptr.
+ ///
+ /// Extract \a count uint16_t values from the binary data at the
+ /// offset pointed to by \a offset_ptr, and advance the offset on
+ /// success. The extracted values are copied into \a dst.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @param[out] dst
+ /// A buffer to copy \a count uint16_t values into. \a dst must
+ /// be large enough to hold all requested data.
+ ///
+ /// @param[in] count
+ /// The number of uint16_t values to extract.
+ ///
+ /// @return
+ /// \a dst if all values were properly extracted and copied,
+ /// NULL otherise.
+ uint16_t *getU16(uint64_t *offset_ptr, uint16_t *dst, uint32_t count) const;
+
+ /// Extract a 24-bit unsigned value from \a *offset_ptr and return it
+ /// in a uint32_t.
+ ///
+ /// Extract 3 bytes from the binary data at the offset pointed to by
+ /// \a offset_ptr, construct a uint32_t from them and update the offset
+ /// on success.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the 3 bytes if the value is extracted correctly. If the offset
+ /// is out of bounds or there are not enough bytes to extract this value,
+ /// the offset will be left unmodified.
+ ///
+ /// @return
+ /// The extracted 24-bit value represented in a uint32_t.
+ uint32_t getU24(uint64_t *offset_ptr) const;
+
+ /// Extract a uint32_t value from \a *offset_ptr.
+ ///
+ /// Extract a single uint32_t from the binary data at the offset
+ /// pointed to by \a offset_ptr, and update the offset on success.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
+ /// @return
+ /// The extracted uint32_t value.
+ uint32_t getU32(uint64_t *offset_ptr, Error *Err = nullptr) const;
+
+ /// Extract a single uint32_t value from the location given by the cursor. In
+ /// case of an extraction error, or if the cursor is already in an error
+ /// state, zero is returned.
+ uint32_t getU32(Cursor &C) const { return getU32(&C.Offset, &C.Err); }
+
+ /// Extract \a count uint32_t values from \a *offset_ptr.
+ ///
+ /// Extract \a count uint32_t values from the binary data at the
+ /// offset pointed to by \a offset_ptr, and advance the offset on
+ /// success. The extracted values are copied into \a dst.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @param[out] dst
+ /// A buffer to copy \a count uint32_t values into. \a dst must
+ /// be large enough to hold all requested data.
+ ///
+ /// @param[in] count
+ /// The number of uint32_t values to extract.
+ ///
+ /// @return
+ /// \a dst if all values were properly extracted and copied,
+ /// NULL otherise.
+ uint32_t *getU32(uint64_t *offset_ptr, uint32_t *dst, uint32_t count) const;
+
+ /// Extract a uint64_t value from \a *offset_ptr.
+ ///
+ /// Extract a single uint64_t from the binary data at the offset
+ /// pointed to by \a offset_ptr, and update the offset on success.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
+ /// @return
+ /// The extracted uint64_t value.
+ uint64_t getU64(uint64_t *offset_ptr, Error *Err = nullptr) const;
+
+ /// Extract a single uint64_t value from the location given by the cursor. In
+ /// case of an extraction error, or if the cursor is already in an error
+ /// state, zero is returned.
+ uint64_t getU64(Cursor &C) const { return getU64(&C.Offset, &C.Err); }
+
+ /// Extract \a count uint64_t values from \a *offset_ptr.
+ ///
+ /// Extract \a count uint64_t values from the binary data at the
+ /// offset pointed to by \a offset_ptr, and advance the offset on
+ /// success. The extracted values are copied into \a dst.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @param[out] dst
+ /// A buffer to copy \a count uint64_t values into. \a dst must
+ /// be large enough to hold all requested data.
+ ///
+ /// @param[in] count
+ /// The number of uint64_t values to extract.
+ ///
+ /// @return
+ /// \a dst if all values were properly extracted and copied,
+ /// NULL otherise.
+ uint64_t *getU64(uint64_t *offset_ptr, uint64_t *dst, uint32_t count) const;
+
+ /// Extract a signed LEB128 value from \a *offset_ptr.
+ ///
+ /// Extracts an signed LEB128 number from this object's data
+ /// starting at the offset pointed to by \a offset_ptr. The offset
+ /// pointed to by \a offset_ptr will be updated with the offset of
+ /// the byte following the last extracted byte.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @return
+ /// The extracted signed integer value.
+ int64_t getSLEB128(uint64_t *offset_ptr) const;
+
+ /// Extract a unsigned LEB128 value from \a *offset_ptr.
+ ///
+ /// Extracts an unsigned LEB128 number from this object's data
+ /// starting at the offset pointed to by \a offset_ptr. The offset
+ /// pointed to by \a offset_ptr will be updated with the offset of
+ /// the byte following the last extracted byte.
+ ///
+ /// @param[in,out] offset_ptr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
+ /// @return
+ /// The extracted unsigned integer value.
+ uint64_t getULEB128(uint64_t *offset_ptr, llvm::Error *Err = nullptr) const;
+
+ /// Extract an unsigned ULEB128 value from the location given by the cursor.
+ /// In case of an extraction error, or if the cursor is already in an error
+ /// state, zero is returned.
+ uint64_t getULEB128(Cursor &C) const { return getULEB128(&C.Offset, &C.Err); }
+
+ /// Advance the Cursor position by the given number of bytes. No-op if the
+ /// cursor is in an error state.
+ void skip(Cursor &C, uint64_t Length) const;
+
+ /// Return true iff the cursor is at the end of the buffer, regardless of the
+ /// error state of the cursor. The only way both eof and error states can be
+ /// true is if one attempts a read while the cursor is at the very end of the
+ /// data buffer.
+ bool eof(const Cursor &C) const { return Data.size() == C.Offset; }
+
+ /// Test the validity of \a offset.
+ ///
+ /// @return
+ /// \b true if \a offset is a valid offset into the data in this
+ /// object, \b false otherwise.
+ bool isValidOffset(uint64_t offset) const { return Data.size() > offset; }
+
+ /// Test the availability of \a length bytes of data from \a offset.
+ ///
+ /// @return
+ /// \b true if \a offset is a valid offset and there are \a
+ /// length bytes available at that offset, \b false otherwise.
+ bool isValidOffsetForDataOfSize(uint64_t offset, uint64_t length) const {
+ return offset + length >= offset && isValidOffset(offset + length - 1);
+ }
+
+ /// Test the availability of enough bytes of data for a pointer from
+ /// \a offset. The size of a pointer is \a getAddressSize().
+ ///
+ /// @return
+ /// \b true if \a offset is a valid offset and there are enough
+ /// bytes for a pointer available at that offset, \b false
+ /// otherwise.
+ bool isValidOffsetForAddress(uint64_t offset) const {
+ return isValidOffsetForDataOfSize(offset, AddressSize);
+ }
+
+protected:
+ // Make it possible for subclasses to access these fields without making them
+ // public.
+ static uint64_t &getOffset(Cursor &C) { return C.Offset; }
+ static Error &getError(Cursor &C) { return C.Err; }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/DataTypes.h b/third_party/llvm-project/include/llvm/Support/DataTypes.h
new file mode 100644
index 000000000..a3fcc8253
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/DataTypes.h
@@ -0,0 +1,16 @@
+//===-- llvm/Support/DataTypes.h - Define fixed size types ------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Due to layering constraints (Support depends on llvm-c) this is a thin
+// wrapper around the implementation that lives in llvm-c, though most clients
+// can/should think of this as being provided by Support for simplicity (not
+// many clients are aware of their dependency on llvm-c).
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/DataTypes.h"
diff --git a/third_party/llvm-project/include/llvm/Support/Debug.h b/third_party/llvm-project/include/llvm/Support/Debug.h
new file mode 100644
index 000000000..64b730951
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Debug.h
@@ -0,0 +1,126 @@
+//===- llvm/Support/Debug.h - Easy way to add debug output ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a handy way of adding debugging information to your
+// code, without it being enabled all of the time, and without having to add
+// command line options to enable it.
+//
+// In particular, just wrap your code with the LLVM_DEBUG() macro, and it will
+// be enabled automatically if you specify '-debug' on the command-line.
+// LLVM_DEBUG() requires the DEBUG_TYPE macro to be defined. Set it to "foo"
+// specify that your debug code belongs to class "foo". Be careful that you only
+// do this after including Debug.h and not around any #include of headers.
+// Headers should define and undef the macro acround the code that needs to use
+// the LLVM_DEBUG() macro. Then, on the command line, you can specify
+// '-debug-only=foo' to enable JUST the debug information for the foo class.
+//
+// When compiling without assertions, the -debug-* options and all code in
+// LLVM_DEBUG() statements disappears, so it does not affect the runtime of the
+// code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_DEBUG_H
+#define LLVM_SUPPORT_DEBUG_H
+
+namespace llvm {
+
+class raw_ostream;
+
+#ifndef NDEBUG
+
+/// isCurrentDebugType - Return true if the specified string is the debug type
+/// specified on the command line, or if none was specified on the command line
+/// with the -debug-only=X option.
+///
+bool isCurrentDebugType(const char *Type);
+
+/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X
+/// option were specified. Note that DebugFlag also needs to be set to true for
+/// debug output to be produced.
+///
+void setCurrentDebugType(const char *Type);
+
+/// setCurrentDebugTypes - Set the current debug type, as if the
+/// -debug-only=X,Y,Z option were specified. Note that DebugFlag
+/// also needs to be set to true for debug output to be produced.
+///
+void setCurrentDebugTypes(const char **Types, unsigned Count);
+
+/// DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug
+/// information. In the '-debug' option is specified on the commandline, and if
+/// this is a debug build, then the code specified as the option to the macro
+/// will be executed. Otherwise it will not be. Example:
+///
+/// DEBUG_WITH_TYPE("bitset", dbgs() << "Bitset contains: " << Bitset << "\n");
+///
+/// This will emit the debug information if -debug is present, and -debug-only
+/// is not specified, or is specified as "bitset".
+#define DEBUG_WITH_TYPE(TYPE, X) \
+ do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE)) { X; } \
+ } while (false)
+
+#else
+#define isCurrentDebugType(X) (false)
+#define setCurrentDebugType(X)
+#define setCurrentDebugTypes(X, N)
+#define DEBUG_WITH_TYPE(TYPE, X) do { } while (false)
+#endif
+
+/// This boolean is set to true if the '-debug' command line option
+/// is specified. This should probably not be referenced directly, instead, use
+/// the DEBUG macro below.
+///
+extern bool DebugFlag;
+
+/// \name Verification flags.
+///
+/// These flags turns on/off that are expensive and are turned off by default,
+/// unless macro EXPENSIVE_CHECKS is defined. The flags allow selectively
+/// turning the checks on without need to recompile.
+/// \{
+
+/// Enables verification of dominator trees.
+///
+extern bool VerifyDomInfo;
+
+/// Enables verification of loop info.
+///
+extern bool VerifyLoopInfo;
+
+/// Enables verification of MemorySSA.
+///
+extern bool VerifyMemorySSA;
+
+///\}
+
+/// EnableDebugBuffering - This defaults to false. If true, the debug
+/// stream will install signal handlers to dump any buffered debug
+/// output. It allows clients to selectively allow the debug stream
+/// to install signal handlers if they are certain there will be no
+/// conflict.
+///
+extern bool EnableDebugBuffering;
+
+/// dbgs() - This returns a reference to a raw_ostream for debugging
+/// messages. If debugging is disabled it returns errs(). Use it
+/// like: dbgs() << "foo" << "bar";
+raw_ostream &dbgs();
+
+// DEBUG macro - This macro should be used by passes to emit debug information.
+// In the '-debug' option is specified on the commandline, and if this is a
+// debug build, then the code specified as the option to the macro will be
+// executed. Otherwise it will not be. Example:
+//
+// LLVM_DEBUG(dbgs() << "Bitset contains: " << Bitset << "\n");
+//
+#define LLVM_DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X)
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_DEBUG_H
diff --git a/third_party/llvm-project/include/llvm/Support/Endian.h b/third_party/llvm-project/include/llvm/Support/Endian.h
new file mode 100644
index 000000000..87aecedd3
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Endian.h
@@ -0,0 +1,429 @@
+//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares generic functions to read and write endian specific data.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ENDIAN_H
+#define LLVM_SUPPORT_ENDIAN_H
+
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <type_traits>
+
+namespace llvm {
+namespace support {
+
+enum endianness {big, little, native};
+
+// These are named values for common alignments.
+enum {aligned = 0, unaligned = 1};
+
+namespace detail {
+
+/// ::value is either alignment, or alignof(T) if alignment is 0.
+template<class T, int alignment>
+struct PickAlignment {
+ enum { value = alignment == 0 ? alignof(T) : alignment };
+};
+
+} // end namespace detail
+
+namespace endian {
+
+constexpr endianness system_endianness() {
+ return sys::IsBigEndianHost ? big : little;
+}
+
+template <typename value_type>
+inline value_type byte_swap(value_type value, endianness endian) {
+ if ((endian != native) && (endian != system_endianness()))
+ sys::swapByteOrder(value);
+ return value;
+}
+
+/// Swap the bytes of value to match the given endianness.
+template<typename value_type, endianness endian>
+inline value_type byte_swap(value_type value) {
+ return byte_swap(value, endian);
+}
+
+/// Read a value of a particular endianness from memory.
+template <typename value_type, std::size_t alignment>
+inline value_type read(const void *memory, endianness endian) {
+ value_type ret;
+
+ memcpy(&ret,
+ LLVM_ASSUME_ALIGNED(
+ memory, (detail::PickAlignment<value_type, alignment>::value)),
+ sizeof(value_type));
+ return byte_swap<value_type>(ret, endian);
+}
+
+template<typename value_type,
+ endianness endian,
+ std::size_t alignment>
+inline value_type read(const void *memory) {
+ return read<value_type, alignment>(memory, endian);
+}
+
+/// Read a value of a particular endianness from a buffer, and increment the
+/// buffer past that value.
+template <typename value_type, std::size_t alignment, typename CharT>
+inline value_type readNext(const CharT *&memory, endianness endian) {
+ value_type ret = read<value_type, alignment>(memory, endian);
+ memory += sizeof(value_type);
+ return ret;
+}
+
+template<typename value_type, endianness endian, std::size_t alignment,
+ typename CharT>
+inline value_type readNext(const CharT *&memory) {
+ return readNext<value_type, alignment, CharT>(memory, endian);
+}
+
+/// Write a value to memory with a particular endianness.
+template <typename value_type, std::size_t alignment>
+inline void write(void *memory, value_type value, endianness endian) {
+ value = byte_swap<value_type>(value, endian);
+ memcpy(LLVM_ASSUME_ALIGNED(
+ memory, (detail::PickAlignment<value_type, alignment>::value)),
+ &value, sizeof(value_type));
+}
+
+template<typename value_type,
+ endianness endian,
+ std::size_t alignment>
+inline void write(void *memory, value_type value) {
+ write<value_type, alignment>(memory, value, endian);
+}
+
+template <typename value_type>
+using make_unsigned_t = typename std::make_unsigned<value_type>::type;
+
+/// Read a value of a particular endianness from memory, for a location
+/// that starts at the given bit offset within the first byte.
+template <typename value_type, endianness endian, std::size_t alignment>
+inline value_type readAtBitAlignment(const void *memory, uint64_t startBit) {
+ assert(startBit < 8);
+ if (startBit == 0)
+ return read<value_type, endian, alignment>(memory);
+ else {
+ // Read two values and compose the result from them.
+ value_type val[2];
+ memcpy(&val[0],
+ LLVM_ASSUME_ALIGNED(
+ memory, (detail::PickAlignment<value_type, alignment>::value)),
+ sizeof(value_type) * 2);
+ val[0] = byte_swap<value_type, endian>(val[0]);
+ val[1] = byte_swap<value_type, endian>(val[1]);
+
+ // Shift bits from the lower value into place.
+ make_unsigned_t<value_type> lowerVal = val[0] >> startBit;
+ // Mask off upper bits after right shift in case of signed type.
+ make_unsigned_t<value_type> numBitsFirstVal =
+ (sizeof(value_type) * 8) - startBit;
+ lowerVal &= ((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1;
+
+ // Get the bits from the upper value.
+ make_unsigned_t<value_type> upperVal =
+ val[1] & (((make_unsigned_t<value_type>)1 << startBit) - 1);
+ // Shift them in to place.
+ upperVal <<= numBitsFirstVal;
+
+ return lowerVal | upperVal;
+ }
+}
+
+/// Write a value to memory with a particular endianness, for a location
+/// that starts at the given bit offset within the first byte.
+template <typename value_type, endianness endian, std::size_t alignment>
+inline void writeAtBitAlignment(void *memory, value_type value,
+ uint64_t startBit) {
+ assert(startBit < 8);
+ if (startBit == 0)
+ write<value_type, endian, alignment>(memory, value);
+ else {
+ // Read two values and shift the result into them.
+ value_type val[2];
+ memcpy(&val[0],
+ LLVM_ASSUME_ALIGNED(
+ memory, (detail::PickAlignment<value_type, alignment>::value)),
+ sizeof(value_type) * 2);
+ val[0] = byte_swap<value_type, endian>(val[0]);
+ val[1] = byte_swap<value_type, endian>(val[1]);
+
+ // Mask off any existing bits in the upper part of the lower value that
+ // we want to replace.
+ val[0] &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
+ make_unsigned_t<value_type> numBitsFirstVal =
+ (sizeof(value_type) * 8) - startBit;
+ make_unsigned_t<value_type> lowerVal = value;
+ if (startBit > 0) {
+ // Mask off the upper bits in the new value that are not going to go into
+ // the lower value. This avoids a left shift of a negative value, which
+ // is undefined behavior.
+ lowerVal &= (((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1);
+ // Now shift the new bits into place
+ lowerVal <<= startBit;
+ }
+ val[0] |= lowerVal;
+
+ // Mask off any existing bits in the lower part of the upper value that
+ // we want to replace.
+ val[1] &= ~(((make_unsigned_t<value_type>)1 << startBit) - 1);
+ // Next shift the bits that go into the upper value into position.
+ make_unsigned_t<value_type> upperVal = value >> numBitsFirstVal;
+ // Mask off upper bits after right shift in case of signed type.
+ upperVal &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
+ val[1] |= upperVal;
+
+ // Finally, rewrite values.
+ val[0] = byte_swap<value_type, endian>(val[0]);
+ val[1] = byte_swap<value_type, endian>(val[1]);
+ memcpy(LLVM_ASSUME_ALIGNED(
+ memory, (detail::PickAlignment<value_type, alignment>::value)),
+ &val[0], sizeof(value_type) * 2);
+ }
+}
+
+} // end namespace endian
+
+namespace detail {
+
+template <typename ValueType, endianness Endian, std::size_t Alignment,
+ std::size_t ALIGN = PickAlignment<ValueType, Alignment>::value>
+struct packed_endian_specific_integral {
+ using value_type = ValueType;
+ static constexpr endianness endian = Endian;
+ static constexpr std::size_t alignment = Alignment;
+
+ packed_endian_specific_integral() = default;
+
+ explicit packed_endian_specific_integral(value_type val) { *this = val; }
+
+ operator value_type() const {
+ return endian::read<value_type, endian, alignment>(
+ (const void*)Value.buffer);
+ }
+
+ void operator=(value_type newValue) {
+ endian::write<value_type, endian, alignment>(
+ (void*)Value.buffer, newValue);
+ }
+
+ packed_endian_specific_integral &operator+=(value_type newValue) {
+ *this = *this + newValue;
+ return *this;
+ }
+
+ packed_endian_specific_integral &operator-=(value_type newValue) {
+ *this = *this - newValue;
+ return *this;
+ }
+
+ packed_endian_specific_integral &operator|=(value_type newValue) {
+ *this = *this | newValue;
+ return *this;
+ }
+
+ packed_endian_specific_integral &operator&=(value_type newValue) {
+ *this = *this & newValue;
+ return *this;
+ }
+
+private:
+ struct {
+ alignas(ALIGN) char buffer[sizeof(value_type)];
+ } Value;
+
+public:
+ struct ref {
+ explicit ref(void *Ptr) : Ptr(Ptr) {}
+
+ operator value_type() const {
+ return endian::read<value_type, endian, alignment>(Ptr);
+ }
+
+ void operator=(value_type NewValue) {
+ endian::write<value_type, endian, alignment>(Ptr, NewValue);
+ }
+
+ private:
+ void *Ptr;
+ };
+};
+
+} // end namespace detail
+
+using ulittle16_t =
+ detail::packed_endian_specific_integral<uint16_t, little, unaligned>;
+using ulittle32_t =
+ detail::packed_endian_specific_integral<uint32_t, little, unaligned>;
+using ulittle64_t =
+ detail::packed_endian_specific_integral<uint64_t, little, unaligned>;
+
+using little16_t =
+ detail::packed_endian_specific_integral<int16_t, little, unaligned>;
+using little32_t =
+ detail::packed_endian_specific_integral<int32_t, little, unaligned>;
+using little64_t =
+ detail::packed_endian_specific_integral<int64_t, little, unaligned>;
+
+using aligned_ulittle16_t =
+ detail::packed_endian_specific_integral<uint16_t, little, aligned>;
+using aligned_ulittle32_t =
+ detail::packed_endian_specific_integral<uint32_t, little, aligned>;
+using aligned_ulittle64_t =
+ detail::packed_endian_specific_integral<uint64_t, little, aligned>;
+
+using aligned_little16_t =
+ detail::packed_endian_specific_integral<int16_t, little, aligned>;
+using aligned_little32_t =
+ detail::packed_endian_specific_integral<int32_t, little, aligned>;
+using aligned_little64_t =
+ detail::packed_endian_specific_integral<int64_t, little, aligned>;
+
+using ubig16_t =
+ detail::packed_endian_specific_integral<uint16_t, big, unaligned>;
+using ubig32_t =
+ detail::packed_endian_specific_integral<uint32_t, big, unaligned>;
+using ubig64_t =
+ detail::packed_endian_specific_integral<uint64_t, big, unaligned>;
+
+using big16_t =
+ detail::packed_endian_specific_integral<int16_t, big, unaligned>;
+using big32_t =
+ detail::packed_endian_specific_integral<int32_t, big, unaligned>;
+using big64_t =
+ detail::packed_endian_specific_integral<int64_t, big, unaligned>;
+
+using aligned_ubig16_t =
+ detail::packed_endian_specific_integral<uint16_t, big, aligned>;
+using aligned_ubig32_t =
+ detail::packed_endian_specific_integral<uint32_t, big, aligned>;
+using aligned_ubig64_t =
+ detail::packed_endian_specific_integral<uint64_t, big, aligned>;
+
+using aligned_big16_t =
+ detail::packed_endian_specific_integral<int16_t, big, aligned>;
+using aligned_big32_t =
+ detail::packed_endian_specific_integral<int32_t, big, aligned>;
+using aligned_big64_t =
+ detail::packed_endian_specific_integral<int64_t, big, aligned>;
+
+using unaligned_uint16_t =
+ detail::packed_endian_specific_integral<uint16_t, native, unaligned>;
+using unaligned_uint32_t =
+ detail::packed_endian_specific_integral<uint32_t, native, unaligned>;
+using unaligned_uint64_t =
+ detail::packed_endian_specific_integral<uint64_t, native, unaligned>;
+
+using unaligned_int16_t =
+ detail::packed_endian_specific_integral<int16_t, native, unaligned>;
+using unaligned_int32_t =
+ detail::packed_endian_specific_integral<int32_t, native, unaligned>;
+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) {
+ return read<T, unaligned>(P, E);
+}
+
+template <typename T, endianness E> inline T read(const void *P) {
+ return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P;
+}
+
+inline uint16_t read16(const void *P, endianness E) {
+ return read<uint16_t>(P, E);
+}
+inline uint32_t read32(const void *P, endianness E) {
+ return read<uint32_t>(P, E);
+}
+inline uint64_t read64(const void *P, endianness E) {
+ return read<uint64_t>(P, E);
+}
+
+template <endianness E> inline uint16_t read16(const void *P) {
+ return read<uint16_t, E>(P);
+}
+template <endianness E> inline uint32_t read32(const void *P) {
+ return read<uint32_t, E>(P);
+}
+template <endianness E> inline uint64_t read64(const void *P) {
+ return read<uint64_t, E>(P);
+}
+
+inline uint16_t read16le(const void *P) { return read16<little>(P); }
+inline uint32_t read32le(const void *P) { return read32<little>(P); }
+inline uint64_t read64le(const void *P) { return read64<little>(P); }
+inline uint16_t read16be(const void *P) { return read16<big>(P); }
+inline uint32_t read32be(const void *P) { return read32<big>(P); }
+inline uint64_t read64be(const void *P) { return read64<big>(P); }
+
+template <typename T> inline void write(void *P, T V, endianness E) {
+ write<T, unaligned>(P, V, E);
+}
+
+template <typename T, endianness E> inline void write(void *P, T V) {
+ *(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V;
+}
+
+inline void write16(void *P, uint16_t V, endianness E) {
+ write<uint16_t>(P, V, E);
+}
+inline void write32(void *P, uint32_t V, endianness E) {
+ write<uint32_t>(P, V, E);
+}
+inline void write64(void *P, uint64_t V, endianness E) {
+ write<uint64_t>(P, V, E);
+}
+
+template <endianness E> inline void write16(void *P, uint16_t V) {
+ write<uint16_t, E>(P, V);
+}
+template <endianness E> inline void write32(void *P, uint32_t V) {
+ write<uint32_t, E>(P, V);
+}
+template <endianness E> inline void write64(void *P, uint64_t V) {
+ write<uint64_t, E>(P, V);
+}
+
+inline void write16le(void *P, uint16_t V) { write16<little>(P, V); }
+inline void write32le(void *P, uint32_t V) { write32<little>(P, V); }
+inline void write64le(void *P, uint64_t V) { write64<little>(P, V); }
+inline void write16be(void *P, uint16_t V) { write16<big>(P, V); }
+inline void write32be(void *P, uint32_t V) { write32<big>(P, V); }
+inline void write64be(void *P, uint64_t V) { write64<big>(P, V); }
+
+} // end namespace endian
+
+} // end namespace support
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_ENDIAN_H
diff --git a/third_party/llvm-project/include/llvm/Support/Errc.h b/third_party/llvm-project/include/llvm/Support/Errc.h
new file mode 100644
index 000000000..9be8e5705
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Errc.h
@@ -0,0 +1,86 @@
+//===- llvm/Support/Errc.h - Defines the llvm::errc enum --------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// While std::error_code works OK on all platforms we use, there are some
+// some problems with std::errc that can be avoided by using our own
+// enumeration:
+//
+// * std::errc is a namespace in some implementations. That meas that ADL
+// doesn't work and it is sometimes necessary to write std::make_error_code
+// or in templates:
+// using std::make_error_code;
+// make_error_code(...);
+//
+// with this enum it is safe to always just use make_error_code.
+//
+// * Some implementations define fewer names than others. This header has
+// the intersection of all the ones we support.
+//
+// * std::errc is just marked with is_error_condition_enum. This means that
+// common patters like AnErrorCode == errc::no_such_file_or_directory take
+// 4 virtual calls instead of two comparisons.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ERRC_H
+#define LLVM_SUPPORT_ERRC_H
+
+#include <system_error>
+
+namespace llvm {
+enum class errc {
+ argument_list_too_long = int(std::errc::argument_list_too_long),
+ argument_out_of_domain = int(std::errc::argument_out_of_domain),
+ bad_address = int(std::errc::bad_address),
+ bad_file_descriptor = int(std::errc::bad_file_descriptor),
+ broken_pipe = int(std::errc::broken_pipe),
+ device_or_resource_busy = int(std::errc::device_or_resource_busy),
+ directory_not_empty = int(std::errc::directory_not_empty),
+ executable_format_error = int(std::errc::executable_format_error),
+ file_exists = int(std::errc::file_exists),
+ file_too_large = int(std::errc::file_too_large),
+ filename_too_long = int(std::errc::filename_too_long),
+ function_not_supported = int(std::errc::function_not_supported),
+ illegal_byte_sequence = int(std::errc::illegal_byte_sequence),
+ inappropriate_io_control_operation =
+ int(std::errc::inappropriate_io_control_operation),
+ interrupted = int(std::errc::interrupted),
+ invalid_argument = int(std::errc::invalid_argument),
+ invalid_seek = int(std::errc::invalid_seek),
+ io_error = int(std::errc::io_error),
+ is_a_directory = int(std::errc::is_a_directory),
+ no_child_process = int(std::errc::no_child_process),
+ no_lock_available = int(std::errc::no_lock_available),
+ no_space_on_device = int(std::errc::no_space_on_device),
+ no_such_device_or_address = int(std::errc::no_such_device_or_address),
+ no_such_device = int(std::errc::no_such_device),
+ no_such_file_or_directory = int(std::errc::no_such_file_or_directory),
+ no_such_process = int(std::errc::no_such_process),
+ not_a_directory = int(std::errc::not_a_directory),
+ not_enough_memory = int(std::errc::not_enough_memory),
+ not_supported = int(std::errc::not_supported),
+ operation_not_permitted = int(std::errc::operation_not_permitted),
+ permission_denied = int(std::errc::permission_denied),
+ read_only_file_system = int(std::errc::read_only_file_system),
+ resource_deadlock_would_occur = int(std::errc::resource_deadlock_would_occur),
+ resource_unavailable_try_again =
+ int(std::errc::resource_unavailable_try_again),
+ result_out_of_range = int(std::errc::result_out_of_range),
+ too_many_files_open_in_system = int(std::errc::too_many_files_open_in_system),
+ too_many_files_open = int(std::errc::too_many_files_open),
+ too_many_links = int(std::errc::too_many_links)
+};
+
+inline std::error_code make_error_code(errc E) {
+ return std::error_code(static_cast<int>(E), std::generic_category());
+}
+}
+
+namespace std {
+template <> struct is_error_code_enum<llvm::errc> : std::true_type {};
+}
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/Errno.h b/third_party/llvm-project/include/llvm/Support/Errno.h
new file mode 100644
index 000000000..aedb5fb29
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Errno.h
@@ -0,0 +1,46 @@
+//===- llvm/Support/Errno.h - Portable+convenient errno handling -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares some portable and convenient functions to deal with errno.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ERRNO_H
+#define LLVM_SUPPORT_ERRNO_H
+
+#include <cerrno>
+#include <string>
+#include <type_traits>
+
+namespace llvm {
+namespace sys {
+
+/// Returns a string representation of the errno value, using whatever
+/// thread-safe variant of strerror() is available. Be sure to call this
+/// immediately after the function that set errno, or errno may have been
+/// overwritten by an intervening call.
+std::string StrError();
+
+/// Like the no-argument version above, but uses \p errnum instead of errno.
+std::string StrError(int errnum);
+
+template <typename FailT, typename Fun, typename... Args>
+inline auto RetryAfterSignal(const FailT &Fail, const Fun &F,
+ const Args &... As) -> decltype(F(As...)) {
+ decltype(F(As...)) Res;
+ do {
+ errno = 0;
+ Res = F(As...);
+ } while (Res == Fail && errno == EINTR);
+ return Res;
+}
+
+} // namespace sys
+} // namespace llvm
+
+#endif // LLVM_SYSTEM_ERRNO_H
diff --git a/third_party/llvm-project/include/llvm/Support/Error.h b/third_party/llvm-project/include/llvm/Support/Error.h
new file mode 100644
index 000000000..350877a21
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Error.h
@@ -0,0 +1,1351 @@
+//===- llvm/Support/Error.h - Recoverable error handling --------*- 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 an API used to report recoverable errors.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ERROR_H
+#define LLVM_SUPPORT_ERROR_H
+
+#include "llvm-c/Error.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Config/abi-breaking.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
+#include <memory>
+#include <new>
+#include <string>
+#include <system_error>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+class ErrorSuccess;
+
+/// Base class for error info classes. Do not extend this directly: Extend
+/// the ErrorInfo template subclass instead.
+class ErrorInfoBase {
+public:
+ virtual ~ErrorInfoBase() = default;
+
+ /// Print an error message to an output stream.
+ virtual void log(raw_ostream &OS) const = 0;
+
+ /// Return the error message as a string.
+ virtual std::string message() const {
+ std::string Msg;
+ raw_string_ostream OS(Msg);
+ log(OS);
+ return OS.str();
+ }
+
+ /// Convert this error to a std::error_code.
+ ///
+ /// This is a temporary crutch to enable interaction with code still
+ /// using std::error_code. It will be removed in the future.
+ virtual std::error_code convertToErrorCode() const = 0;
+
+ // Returns the class ID for this type.
+ static const void *classID() { return &ID; }
+
+ // Returns the class ID for the dynamic type of this ErrorInfoBase instance.
+ virtual const void *dynamicClassID() const = 0;
+
+ // Check whether this instance is a subclass of the class identified by
+ // ClassID.
+ virtual bool isA(const void *const ClassID) const {
+ return ClassID == classID();
+ }
+
+ // Check whether this instance is a subclass of ErrorInfoT.
+ template <typename ErrorInfoT> bool isA() const {
+ return isA(ErrorInfoT::classID());
+ }
+
+private:
+ virtual void anchor();
+
+ static char ID;
+};
+
+/// Lightweight error class with error context and mandatory checking.
+///
+/// Instances of this class wrap a ErrorInfoBase pointer. Failure states
+/// are represented by setting the pointer to a ErrorInfoBase subclass
+/// instance containing information describing the failure. Success is
+/// represented by a null pointer value.
+///
+/// Instances of Error also contains a 'Checked' flag, which must be set
+/// before the destructor is called, otherwise the destructor will trigger a
+/// runtime error. This enforces at runtime the requirement that all Error
+/// instances be checked or returned to the caller.
+///
+/// There are two ways to set the checked flag, depending on what state the
+/// Error instance is in. For Error instances indicating success, it
+/// is sufficient to invoke the boolean conversion operator. E.g.:
+///
+/// @code{.cpp}
+/// Error foo(<...>);
+///
+/// if (auto E = foo(<...>))
+/// return E; // <- Return E if it is in the error state.
+/// // We have verified that E was in the success state. It can now be safely
+/// // destroyed.
+/// @endcode
+///
+/// A success value *can not* be dropped. For example, just calling 'foo(<...>)'
+/// without testing the return value will raise a runtime error, even if foo
+/// returns success.
+///
+/// For Error instances representing failure, you must use either the
+/// handleErrors or handleAllErrors function with a typed handler. E.g.:
+///
+/// @code{.cpp}
+/// class MyErrorInfo : public ErrorInfo<MyErrorInfo> {
+/// // Custom error info.
+/// };
+///
+/// Error foo(<...>) { return make_error<MyErrorInfo>(...); }
+///
+/// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo.
+/// auto NewE =
+/// handleErrors(E,
+/// [](const MyErrorInfo &M) {
+/// // Deal with the error.
+/// },
+/// [](std::unique_ptr<OtherError> M) -> Error {
+/// if (canHandle(*M)) {
+/// // handle error.
+/// return Error::success();
+/// }
+/// // Couldn't handle this error instance. Pass it up the stack.
+/// return Error(std::move(M));
+/// );
+/// // Note - we must check or return NewE in case any of the handlers
+/// // returned a new error.
+/// @endcode
+///
+/// The handleAllErrors function is identical to handleErrors, except
+/// that it has a void return type, and requires all errors to be handled and
+/// no new errors be returned. It prevents errors (assuming they can all be
+/// handled) from having to be bubbled all the way to the top-level.
+///
+/// *All* Error instances must be checked before destruction, even if
+/// they're moved-assigned or constructed from Success values that have already
+/// been checked. This enforces checking through all levels of the call stack.
+class LLVM_NODISCARD Error {
+ // Both ErrorList and FileError need to be able to yank ErrorInfoBase
+ // pointers out of this class to add to the error list.
+ friend class ErrorList;
+ friend class FileError;
+
+ // handleErrors needs to be able to set the Checked flag.
+ template <typename... HandlerTs>
+ friend Error handleErrors(Error E, HandlerTs &&... Handlers);
+
+ // Expected<T> needs to be able to steal the payload when constructed from an
+ // error.
+ template <typename T> friend class Expected;
+
+ // wrap needs to be able to steal the payload.
+ friend LLVMErrorRef wrap(Error);
+
+protected:
+ /// Create a success value. Prefer using 'Error::success()' for readability
+ Error() {
+ setPtr(nullptr);
+ setChecked(false);
+ }
+
+public:
+ /// Create a success value.
+ static ErrorSuccess success();
+
+ // Errors are not copy-constructable.
+ Error(const Error &Other) = delete;
+
+ /// Move-construct an error value. The newly constructed error is considered
+ /// unchecked, even if the source error had been checked. The original error
+ /// becomes a checked Success value, regardless of its original state.
+ Error(Error &&Other) {
+ setChecked(true);
+ *this = std::move(Other);
+ }
+
+ /// Create an error value. Prefer using the 'make_error' function, but
+ /// this constructor can be useful when "re-throwing" errors from handlers.
+ Error(std::unique_ptr<ErrorInfoBase> Payload) {
+ setPtr(Payload.release());
+ setChecked(false);
+ }
+
+ // Errors are not copy-assignable.
+ Error &operator=(const Error &Other) = delete;
+
+ /// Move-assign an error value. The current error must represent success, you
+ /// you cannot overwrite an unhandled error. The current error is then
+ /// considered unchecked. The source error becomes a checked success value,
+ /// regardless of its original state.
+ Error &operator=(Error &&Other) {
+ // Don't allow overwriting of unchecked values.
+ assertIsChecked();
+ setPtr(Other.getPtr());
+
+ // This Error is unchecked, even if the source error was checked.
+ setChecked(false);
+
+ // Null out Other's payload and set its checked bit.
+ Other.setPtr(nullptr);
+ Other.setChecked(true);
+
+ return *this;
+ }
+
+ /// Destroy a Error. Fails with a call to abort() if the error is
+ /// unchecked.
+ ~Error() {
+ assertIsChecked();
+ delete getPtr();
+ }
+
+ /// Bool conversion. Returns true if this Error is in a failure state,
+ /// and false if it is in an accept state. If the error is in a Success state
+ /// it will be considered checked.
+ explicit operator bool() {
+ setChecked(getPtr() == nullptr);
+ return getPtr() != nullptr;
+ }
+
+ /// Check whether one error is a subclass of another.
+ template <typename ErrT> bool isA() const {
+ return getPtr() && getPtr()->isA(ErrT::classID());
+ }
+
+ /// Returns the dynamic class id of this error, or null if this is a success
+ /// value.
+ const void* dynamicClassID() const {
+ if (!getPtr())
+ return nullptr;
+ return getPtr()->dynamicClassID();
+ }
+
+private:
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ // assertIsChecked() happens very frequently, but under normal circumstances
+ // is supposed to be a no-op. So we want it to be inlined, but having a bunch
+ // of debug prints can cause the function to be too large for inlining. So
+ // it's important that we define this function out of line so that it can't be
+ // inlined.
+ LLVM_ATTRIBUTE_NORETURN
+ void fatalUncheckedError() const;
+#endif
+
+ void assertIsChecked() {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ if (LLVM_UNLIKELY(!getChecked() || getPtr()))
+ fatalUncheckedError();
+#endif
+ }
+
+ ErrorInfoBase *getPtr() const {
+ return reinterpret_cast<ErrorInfoBase*>(
+ reinterpret_cast<uintptr_t>(Payload) &
+ ~static_cast<uintptr_t>(0x1));
+ }
+
+ void setPtr(ErrorInfoBase *EI) {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ Payload = reinterpret_cast<ErrorInfoBase*>(
+ (reinterpret_cast<uintptr_t>(EI) &
+ ~static_cast<uintptr_t>(0x1)) |
+ (reinterpret_cast<uintptr_t>(Payload) & 0x1));
+#else
+ Payload = EI;
+#endif
+ }
+
+ bool getChecked() const {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0;
+#else
+ return true;
+#endif
+ }
+
+ void setChecked(bool V) {
+ Payload = reinterpret_cast<ErrorInfoBase*>(
+ (reinterpret_cast<uintptr_t>(Payload) &
+ ~static_cast<uintptr_t>(0x1)) |
+ (V ? 0 : 1));
+ }
+
+ std::unique_ptr<ErrorInfoBase> takePayload() {
+ std::unique_ptr<ErrorInfoBase> Tmp(getPtr());
+ setPtr(nullptr);
+ setChecked(true);
+ return Tmp;
+ }
+
+ friend raw_ostream &operator<<(raw_ostream &OS, const Error &E) {
+ if (auto P = E.getPtr())
+ P->log(OS);
+ else
+ OS << "success";
+ return OS;
+ }
+
+ ErrorInfoBase *Payload = nullptr;
+};
+
+/// Subclass of Error for the sole purpose of identifying the success path in
+/// the type system. This allows to catch invalid conversion to Expected<T> at
+/// compile time.
+class ErrorSuccess final : public Error {};
+
+inline ErrorSuccess Error::success() { return ErrorSuccess(); }
+
+/// Make a Error instance representing failure using the given error info
+/// type.
+template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) {
+ return Error(std::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
+}
+
+/// Base class for user error types. Users should declare their error types
+/// like:
+///
+/// class MyError : public ErrorInfo<MyError> {
+/// ....
+/// };
+///
+/// This class provides an implementation of the ErrorInfoBase::kind
+/// method, which is used by the Error RTTI system.
+template <typename ThisErrT, typename ParentErrT = ErrorInfoBase>
+class ErrorInfo : public ParentErrT {
+public:
+ using ParentErrT::ParentErrT; // inherit constructors
+
+ static const void *classID() { return &ThisErrT::ID; }
+
+ const void *dynamicClassID() const override { return &ThisErrT::ID; }
+
+ bool isA(const void *const ClassID) const override {
+ return ClassID == classID() || ParentErrT::isA(ClassID);
+ }
+};
+
+/// Special ErrorInfo subclass representing a list of ErrorInfos.
+/// Instances of this class are constructed by joinError.
+class ErrorList final : public ErrorInfo<ErrorList> {
+ // handleErrors needs to be able to iterate the payload list of an
+ // ErrorList.
+ template <typename... HandlerTs>
+ friend Error handleErrors(Error E, HandlerTs &&... Handlers);
+
+ // joinErrors is implemented in terms of join.
+ friend Error joinErrors(Error, Error);
+
+public:
+ void log(raw_ostream &OS) const override {
+ OS << "Multiple errors:\n";
+ for (auto &ErrPayload : Payloads) {
+ ErrPayload->log(OS);
+ OS << "\n";
+ }
+ }
+
+ std::error_code convertToErrorCode() const override;
+
+ // Used by ErrorInfo::classID.
+ static char ID;
+
+private:
+ ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
+ std::unique_ptr<ErrorInfoBase> Payload2) {
+ assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&
+ "ErrorList constructor payloads should be singleton errors");
+ Payloads.push_back(std::move(Payload1));
+ Payloads.push_back(std::move(Payload2));
+ }
+
+ static Error join(Error E1, Error E2) {
+ if (!E1)
+ return E2;
+ if (!E2)
+ return E1;
+ if (E1.isA<ErrorList>()) {
+ auto &E1List = static_cast<ErrorList &>(*E1.getPtr());
+ if (E2.isA<ErrorList>()) {
+ auto E2Payload = E2.takePayload();
+ auto &E2List = static_cast<ErrorList &>(*E2Payload);
+ for (auto &Payload : E2List.Payloads)
+ E1List.Payloads.push_back(std::move(Payload));
+ } else
+ E1List.Payloads.push_back(E2.takePayload());
+
+ return E1;
+ }
+ if (E2.isA<ErrorList>()) {
+ auto &E2List = static_cast<ErrorList &>(*E2.getPtr());
+ E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
+ return E2;
+ }
+ return Error(std::unique_ptr<ErrorList>(
+ new ErrorList(E1.takePayload(), E2.takePayload())));
+ }
+
+ std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
+};
+
+/// Concatenate errors. The resulting Error is unchecked, and contains the
+/// ErrorInfo(s), if any, contained in E1, followed by the
+/// ErrorInfo(s), if any, contained in E2.
+inline Error joinErrors(Error E1, Error E2) {
+ return ErrorList::join(std::move(E1), std::move(E2));
+}
+
+/// Tagged union holding either a T or a Error.
+///
+/// This class parallels ErrorOr, but replaces error_code with Error. Since
+/// Error cannot be copied, this class replaces getError() with
+/// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the
+/// error class type.
+template <class T> class LLVM_NODISCARD Expected {
+ template <class T1> friend class ExpectedAsOutParameter;
+ template <class OtherT> friend class Expected;
+
+ static const bool isRef = std::is_reference<T>::value;
+
+ using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
+
+ using error_type = std::unique_ptr<ErrorInfoBase>;
+
+public:
+ using storage_type = typename std::conditional<isRef, wrap, T>::type;
+ using value_type = T;
+
+private:
+ using reference = typename std::remove_reference<T>::type &;
+ using const_reference = const typename std::remove_reference<T>::type &;
+ using pointer = typename std::remove_reference<T>::type *;
+ using const_pointer = const typename std::remove_reference<T>::type *;
+
+public:
+ /// Create an Expected<T> error value from the given Error.
+ Expected(Error Err)
+ : HasError(true)
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ // Expected is unchecked upon construction in Debug builds.
+ , Unchecked(true)
+#endif
+ {
+ assert(Err && "Cannot create Expected<T> from Error success value.");
+ new (getErrorStorage()) error_type(Err.takePayload());
+ }
+
+ /// Forbid to convert from Error::success() implicitly, this avoids having
+ /// Expected<T> foo() { return Error::success(); } which compiles otherwise
+ /// but triggers the assertion above.
+ Expected(ErrorSuccess) = delete;
+
+ /// Create an Expected<T> success value from the given OtherT value, which
+ /// must be convertible to T.
+ template <typename OtherT>
+ Expected(OtherT &&Val,
+ typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
+ * = nullptr)
+ : HasError(false)
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ // Expected is unchecked upon construction in Debug builds.
+ , Unchecked(true)
+#endif
+ {
+ new (getStorage()) storage_type(std::forward<OtherT>(Val));
+ }
+
+ /// Move construct an Expected<T> value.
+ Expected(Expected &&Other) { moveConstruct(std::move(Other)); }
+
+ /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
+ /// must be convertible to T.
+ template <class OtherT>
+ Expected(Expected<OtherT> &&Other,
+ typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
+ * = nullptr) {
+ moveConstruct(std::move(Other));
+ }
+
+ /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
+ /// isn't convertible to T.
+ template <class OtherT>
+ explicit Expected(
+ Expected<OtherT> &&Other,
+ typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
+ nullptr) {
+ moveConstruct(std::move(Other));
+ }
+
+ /// Move-assign from another Expected<T>.
+ Expected &operator=(Expected &&Other) {
+ moveAssign(std::move(Other));
+ return *this;
+ }
+
+ /// Destroy an Expected<T>.
+ ~Expected() {
+ assertIsChecked();
+ if (!HasError)
+ getStorage()->~storage_type();
+ else
+ getErrorStorage()->~error_type();
+ }
+
+ /// Return false if there is an error.
+ explicit operator bool() {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ Unchecked = HasError;
+#endif
+ return !HasError;
+ }
+
+ /// Returns a reference to the stored T value.
+ reference get() {
+ assertIsChecked();
+ return *getStorage();
+ }
+
+ /// Returns a const reference to the stored T value.
+ const_reference get() const {
+ assertIsChecked();
+ return const_cast<Expected<T> *>(this)->get();
+ }
+
+ /// Check that this Expected<T> is an error of type ErrT.
+ template <typename ErrT> bool errorIsA() const {
+ return HasError && (*getErrorStorage())->template isA<ErrT>();
+ }
+
+ /// Take ownership of the stored error.
+ /// After calling this the Expected<T> is in an indeterminate state that can
+ /// only be safely destructed. No further calls (beside the destructor) should
+ /// be made on the Expected<T> value.
+ Error takeError() {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ Unchecked = false;
+#endif
+ return HasError ? Error(std::move(*getErrorStorage())) : Error::success();
+ }
+
+ /// Returns a pointer to the stored T value.
+ pointer operator->() {
+ assertIsChecked();
+ return toPointer(getStorage());
+ }
+
+ /// Returns a const pointer to the stored T value.
+ const_pointer operator->() const {
+ assertIsChecked();
+ return toPointer(getStorage());
+ }
+
+ /// Returns a reference to the stored T value.
+ reference operator*() {
+ assertIsChecked();
+ return *getStorage();
+ }
+
+ /// Returns a const reference to the stored T value.
+ const_reference operator*() const {
+ assertIsChecked();
+ return *getStorage();
+ }
+
+private:
+ template <class T1>
+ static bool compareThisIfSameType(const T1 &a, const T1 &b) {
+ return &a == &b;
+ }
+
+ template <class T1, class T2>
+ static bool compareThisIfSameType(const T1 &a, const T2 &b) {
+ return false;
+ }
+
+ template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) {
+ HasError = Other.HasError;
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ Unchecked = true;
+ Other.Unchecked = false;
+#endif
+
+ if (!HasError)
+ new (getStorage()) storage_type(std::move(*Other.getStorage()));
+ else
+ new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage()));
+ }
+
+ template <class OtherT> void moveAssign(Expected<OtherT> &&Other) {
+ assertIsChecked();
+
+ if (compareThisIfSameType(*this, Other))
+ return;
+
+ this->~Expected();
+ new (this) Expected(std::move(Other));
+ }
+
+ pointer toPointer(pointer Val) { return Val; }
+
+ const_pointer toPointer(const_pointer Val) const { return Val; }
+
+ pointer toPointer(wrap *Val) { return &Val->get(); }
+
+ const_pointer toPointer(const wrap *Val) const { return &Val->get(); }
+
+ storage_type *getStorage() {
+ assert(!HasError && "Cannot get value when an error exists!");
+ return reinterpret_cast<storage_type *>(TStorage.buffer);
+ }
+
+ const storage_type *getStorage() const {
+ assert(!HasError && "Cannot get value when an error exists!");
+ return reinterpret_cast<const storage_type *>(TStorage.buffer);
+ }
+
+ error_type *getErrorStorage() {
+ assert(HasError && "Cannot get error when a value exists!");
+ return reinterpret_cast<error_type *>(ErrorStorage.buffer);
+ }
+
+ const error_type *getErrorStorage() const {
+ assert(HasError && "Cannot get error when a value exists!");
+ return reinterpret_cast<const error_type *>(ErrorStorage.buffer);
+ }
+
+ // Used by ExpectedAsOutParameter to reset the checked flag.
+ void setUnchecked() {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ Unchecked = true;
+#endif
+ }
+
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ LLVM_ATTRIBUTE_NORETURN
+ LLVM_ATTRIBUTE_NOINLINE
+ void fatalUncheckedExpected() const {
+ dbgs() << "Expected<T> must be checked before access or destruction.\n";
+ if (HasError) {
+ dbgs() << "Unchecked Expected<T> contained error:\n";
+ (*getErrorStorage())->log(dbgs());
+ } else
+ dbgs() << "Expected<T> value was in success state. (Note: Expected<T> "
+ "values in success mode must still be checked prior to being "
+ "destroyed).\n";
+ abort();
+ }
+#endif
+
+ void assertIsChecked() {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ if (LLVM_UNLIKELY(Unchecked))
+ fatalUncheckedExpected();
+#endif
+ }
+
+ union {
+ AlignedCharArrayUnion<storage_type> TStorage;
+ AlignedCharArrayUnion<error_type> ErrorStorage;
+ };
+ bool HasError : 1;
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ bool Unchecked : 1;
+#endif
+};
+
+/// Report a serious error, calling any installed error handler. See
+/// ErrorHandling.h.
+LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err,
+ bool gen_crash_diag = true);
+
+/// Report a fatal error if Err is a failure value.
+///
+/// This function can be used to wrap calls to fallible functions ONLY when it
+/// is known that the Error will always be a success value. E.g.
+///
+/// @code{.cpp}
+/// // foo only attempts the fallible operation if DoFallibleOperation is
+/// // true. If DoFallibleOperation is false then foo always returns
+/// // Error::success().
+/// Error foo(bool DoFallibleOperation);
+///
+/// cantFail(foo(false));
+/// @endcode
+inline void cantFail(Error Err, const char *Msg = nullptr) {
+ if (Err) {
+ if (!Msg)
+ Msg = "Failure value returned from cantFail wrapped call";
+#ifndef NDEBUG
+ std::string Str;
+ raw_string_ostream OS(Str);
+ OS << Msg << "\n" << Err;
+ Msg = OS.str().c_str();
+#endif
+ llvm_unreachable(Msg);
+ }
+}
+
+/// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and
+/// returns the contained value.
+///
+/// This function can be used to wrap calls to fallible functions ONLY when it
+/// is known that the Error will always be a success value. E.g.
+///
+/// @code{.cpp}
+/// // foo only attempts the fallible operation if DoFallibleOperation is
+/// // true. If DoFallibleOperation is false then foo always returns an int.
+/// Expected<int> foo(bool DoFallibleOperation);
+///
+/// int X = cantFail(foo(false));
+/// @endcode
+template <typename T>
+T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) {
+ if (ValOrErr)
+ return std::move(*ValOrErr);
+ else {
+ if (!Msg)
+ Msg = "Failure value returned from cantFail wrapped call";
+#ifndef NDEBUG
+ std::string Str;
+ raw_string_ostream OS(Str);
+ auto E = ValOrErr.takeError();
+ OS << Msg << "\n" << E;
+ Msg = OS.str().c_str();
+#endif
+ llvm_unreachable(Msg);
+ }
+}
+
+/// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and
+/// returns the contained reference.
+///
+/// This function can be used to wrap calls to fallible functions ONLY when it
+/// is known that the Error will always be a success value. E.g.
+///
+/// @code{.cpp}
+/// // foo only attempts the fallible operation if DoFallibleOperation is
+/// // true. If DoFallibleOperation is false then foo always returns a Bar&.
+/// Expected<Bar&> foo(bool DoFallibleOperation);
+///
+/// Bar &X = cantFail(foo(false));
+/// @endcode
+template <typename T>
+T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) {
+ if (ValOrErr)
+ return *ValOrErr;
+ else {
+ if (!Msg)
+ Msg = "Failure value returned from cantFail wrapped call";
+#ifndef NDEBUG
+ std::string Str;
+ raw_string_ostream OS(Str);
+ auto E = ValOrErr.takeError();
+ OS << Msg << "\n" << E;
+ Msg = OS.str().c_str();
+#endif
+ llvm_unreachable(Msg);
+ }
+}
+
+/// Helper for testing applicability of, and applying, handlers for
+/// ErrorInfo types.
+template <typename HandlerT>
+class ErrorHandlerTraits
+ : public ErrorHandlerTraits<decltype(
+ &std::remove_reference<HandlerT>::type::operator())> {};
+
+// Specialization functions of the form 'Error (const ErrT&)'.
+template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> {
+public:
+ static bool appliesTo(const ErrorInfoBase &E) {
+ return E.template isA<ErrT>();
+ }
+
+ template <typename HandlerT>
+ static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+ assert(appliesTo(*E) && "Applying incorrect handler");
+ return H(static_cast<ErrT &>(*E));
+ }
+};
+
+// Specialization functions of the form 'void (const ErrT&)'.
+template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> {
+public:
+ static bool appliesTo(const ErrorInfoBase &E) {
+ return E.template isA<ErrT>();
+ }
+
+ template <typename HandlerT>
+ static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+ assert(appliesTo(*E) && "Applying incorrect handler");
+ H(static_cast<ErrT &>(*E));
+ return Error::success();
+ }
+};
+
+/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'.
+template <typename ErrT>
+class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> {
+public:
+ static bool appliesTo(const ErrorInfoBase &E) {
+ return E.template isA<ErrT>();
+ }
+
+ template <typename HandlerT>
+ static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+ assert(appliesTo(*E) && "Applying incorrect handler");
+ std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
+ return H(std::move(SubE));
+ }
+};
+
+/// Specialization for functions of the form 'void (std::unique_ptr<ErrT>)'.
+template <typename ErrT>
+class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> {
+public:
+ static bool appliesTo(const ErrorInfoBase &E) {
+ return E.template isA<ErrT>();
+ }
+
+ template <typename HandlerT>
+ static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
+ assert(appliesTo(*E) && "Applying incorrect handler");
+ std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
+ H(std::move(SubE));
+ return Error::success();
+ }
+};
+
+// Specialization for member functions of the form 'RetT (const ErrT&)'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(ErrT &)>
+ : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+// Specialization for member functions of the form 'RetT (const ErrT&) const'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(ErrT &) const>
+ : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+// Specialization for member functions of the form 'RetT (const ErrT&)'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(const ErrT &)>
+ : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+// Specialization for member functions of the form 'RetT (const ErrT&) const'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const>
+ : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
+
+/// Specialization for member functions of the form
+/// 'RetT (std::unique_ptr<ErrT>)'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)>
+ : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
+
+/// Specialization for member functions of the form
+/// 'RetT (std::unique_ptr<ErrT>) const'.
+template <typename C, typename RetT, typename ErrT>
+class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const>
+ : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
+
+inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) {
+ return Error(std::move(Payload));
+}
+
+template <typename HandlerT, typename... HandlerTs>
+Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload,
+ HandlerT &&Handler, HandlerTs &&... Handlers) {
+ if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload))
+ return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler),
+ std::move(Payload));
+ return handleErrorImpl(std::move(Payload),
+ std::forward<HandlerTs>(Handlers)...);
+}
+
+/// Pass the ErrorInfo(s) contained in E to their respective handlers. Any
+/// unhandled errors (or Errors returned by handlers) are re-concatenated and
+/// returned.
+/// Because this function returns an error, its result must also be checked
+/// or returned. If you intend to handle all errors use handleAllErrors
+/// (which returns void, and will abort() on unhandled errors) instead.
+template <typename... HandlerTs>
+Error handleErrors(Error E, HandlerTs &&... Hs) {
+ if (!E)
+ return Error::success();
+
+ std::unique_ptr<ErrorInfoBase> Payload = E.takePayload();
+
+ if (Payload->isA<ErrorList>()) {
+ ErrorList &List = static_cast<ErrorList &>(*Payload);
+ Error R;
+ for (auto &P : List.Payloads)
+ R = ErrorList::join(
+ std::move(R),
+ handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...));
+ return R;
+ }
+
+ return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
+}
+
+/// Behaves the same as handleErrors, except that by contract all errors
+/// *must* be handled by the given handlers (i.e. there must be no remaining
+/// errors after running the handlers, or llvm_unreachable is called).
+template <typename... HandlerTs>
+void handleAllErrors(Error E, HandlerTs &&... Handlers) {
+ cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...));
+}
+
+/// Check that E is a non-error, then drop it.
+/// If E is an error, llvm_unreachable will be called.
+inline void handleAllErrors(Error E) {
+ cantFail(std::move(E));
+}
+
+/// Handle any errors (if present) in an Expected<T>, then try a recovery path.
+///
+/// If the incoming value is a success value it is returned unmodified. If it
+/// is a failure value then it the contained error is passed to handleErrors.
+/// If handleErrors is able to handle the error then the RecoveryPath functor
+/// is called to supply the final result. If handleErrors is not able to
+/// handle all errors then the unhandled errors are returned.
+///
+/// This utility enables the follow pattern:
+///
+/// @code{.cpp}
+/// enum FooStrategy { Aggressive, Conservative };
+/// Expected<Foo> foo(FooStrategy S);
+///
+/// auto ResultOrErr =
+/// handleExpected(
+/// foo(Aggressive),
+/// []() { return foo(Conservative); },
+/// [](AggressiveStrategyError&) {
+/// // Implicitly conusme this - we'll recover by using a conservative
+/// // strategy.
+/// });
+///
+/// @endcode
+template <typename T, typename RecoveryFtor, typename... HandlerTs>
+Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath,
+ HandlerTs &&... Handlers) {
+ if (ValOrErr)
+ return ValOrErr;
+
+ if (auto Err = handleErrors(ValOrErr.takeError(),
+ std::forward<HandlerTs>(Handlers)...))
+ return std::move(Err);
+
+ return RecoveryPath();
+}
+
+/// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner
+/// will be printed before the first one is logged. A newline will be printed
+/// after each error.
+///
+/// This function is compatible with the helpers from Support/WithColor.h. You
+/// can pass any of them as the OS. Please consider using them instead of
+/// including 'error: ' in the ErrorBanner.
+///
+/// This is useful in the base level of your program to allow clean termination
+/// (allowing clean deallocation of resources, etc.), while reporting error
+/// information to the user.
+void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner = {});
+
+/// Write all error messages (if any) in E to a string. The newline character
+/// is used to separate error messages.
+inline std::string toString(Error E) {
+ SmallVector<std::string, 2> Errors;
+ handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) {
+ Errors.push_back(EI.message());
+ });
+ return join(Errors.begin(), Errors.end(), "\n");
+}
+
+/// Consume a Error without doing anything. This method should be used
+/// only where an error can be considered a reasonable and expected return
+/// value.
+///
+/// Uses of this method are potentially indicative of design problems: If it's
+/// legitimate to do nothing while processing an "error", the error-producer
+/// might be more clearly refactored to return an Optional<T>.
+inline void consumeError(Error Err) {
+ handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
+}
+
+/// Convert an Expected to an Optional without doing anything. This method
+/// should be used only where an error can be considered a reasonable and
+/// expected return value.
+///
+/// Uses of this method are potentially indicative of problems: perhaps the
+/// error should be propagated further, or the error-producer should just
+/// return an Optional in the first place.
+template <typename T> Optional<T> expectedToOptional(Expected<T> &&E) {
+ if (E)
+ return std::move(*E);
+ consumeError(E.takeError());
+ return None;
+}
+
+/// Helper for converting an Error to a bool.
+///
+/// This method returns true if Err is in an error state, or false if it is
+/// in a success state. Puts Err in a checked state in both cases (unlike
+/// Error::operator bool(), which only does this for success states).
+inline bool errorToBool(Error Err) {
+ bool IsError = static_cast<bool>(Err);
+ if (IsError)
+ consumeError(std::move(Err));
+ return IsError;
+}
+
+/// Helper for Errors used as out-parameters.
+///
+/// This helper is for use with the Error-as-out-parameter idiom, where an error
+/// is passed to a function or method by reference, rather than being returned.
+/// In such cases it is helpful to set the checked bit on entry to the function
+/// so that the error can be written to (unchecked Errors abort on assignment)
+/// and clear the checked bit on exit so that clients cannot accidentally forget
+/// to check the result. This helper performs these actions automatically using
+/// RAII:
+///
+/// @code{.cpp}
+/// Result foo(Error &Err) {
+/// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set
+/// // <body of foo>
+/// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed.
+/// }
+/// @endcode
+///
+/// ErrorAsOutParameter takes an Error* rather than Error& so that it can be
+/// used with optional Errors (Error pointers that are allowed to be null). If
+/// ErrorAsOutParameter took an Error reference, an instance would have to be
+/// created inside every condition that verified that Error was non-null. By
+/// taking an Error pointer we can just create one instance at the top of the
+/// function.
+class ErrorAsOutParameter {
+public:
+ ErrorAsOutParameter(Error *Err) : Err(Err) {
+ // Raise the checked bit if Err is success.
+ if (Err)
+ (void)!!*Err;
+ }
+
+ ~ErrorAsOutParameter() {
+ // Clear the checked bit.
+ if (Err && !*Err)
+ *Err = Error::success();
+ }
+
+private:
+ Error *Err;
+};
+
+/// Helper for Expected<T>s used as out-parameters.
+///
+/// See ErrorAsOutParameter.
+template <typename T>
+class ExpectedAsOutParameter {
+public:
+ ExpectedAsOutParameter(Expected<T> *ValOrErr)
+ : ValOrErr(ValOrErr) {
+ if (ValOrErr)
+ (void)!!*ValOrErr;
+ }
+
+ ~ExpectedAsOutParameter() {
+ if (ValOrErr)
+ ValOrErr->setUnchecked();
+ }
+
+private:
+ Expected<T> *ValOrErr;
+};
+
+/// This class wraps a std::error_code in a Error.
+///
+/// This is useful if you're writing an interface that returns a Error
+/// (or Expected) and you want to call code that still returns
+/// std::error_codes.
+class ECError : public ErrorInfo<ECError> {
+ friend Error errorCodeToError(std::error_code);
+
+ virtual void anchor() override;
+
+public:
+ void setErrorCode(std::error_code EC) { this->EC = EC; }
+ std::error_code convertToErrorCode() const override { return EC; }
+ void log(raw_ostream &OS) const override { OS << EC.message(); }
+
+ // Used by ErrorInfo::classID.
+ static char ID;
+
+protected:
+ ECError() = default;
+ ECError(std::error_code EC) : EC(EC) {}
+
+ std::error_code EC;
+};
+
+/// The value returned by this function can be returned from convertToErrorCode
+/// for Error values where no sensible translation to std::error_code exists.
+/// It should only be used in this situation, and should never be used where a
+/// sensible conversion to std::error_code is available, as attempts to convert
+/// to/from this error will result in a fatal error. (i.e. it is a programmatic
+///error to try to convert such a value).
+std::error_code inconvertibleErrorCode();
+
+/// Helper for converting an std::error_code to a Error.
+Error errorCodeToError(std::error_code EC);
+
+/// Helper for converting an ECError to a std::error_code.
+///
+/// This method requires that Err be Error() or an ECError, otherwise it
+/// will trigger a call to abort().
+std::error_code errorToErrorCode(Error Err);
+
+/// Convert an ErrorOr<T> to an Expected<T>.
+template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) {
+ if (auto EC = EO.getError())
+ return errorCodeToError(EC);
+ return std::move(*EO);
+}
+
+/// Convert an Expected<T> to an ErrorOr<T>.
+template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) {
+ if (auto Err = E.takeError())
+ return errorToErrorCode(std::move(Err));
+ return std::move(*E);
+}
+
+/// This class wraps a string in an Error.
+///
+/// StringError is useful in cases where the client is not expected to be able
+/// to consume the specific error message programmatically (for example, if the
+/// error message is to be presented to the user).
+///
+/// StringError can also be used when additional information is to be printed
+/// along with a error_code message. Depending on the constructor called, this
+/// class can either display:
+/// 1. the error_code message (ECError behavior)
+/// 2. a string
+/// 3. the error_code message and a string
+///
+/// These behaviors are useful when subtyping is required; for example, when a
+/// specific library needs an explicit error type. In the example below,
+/// PDBError is derived from StringError:
+///
+/// @code{.cpp}
+/// Expected<int> foo() {
+/// return llvm::make_error<PDBError>(pdb_error_code::dia_failed_loading,
+/// "Additional information");
+/// }
+/// @endcode
+///
+class StringError : public ErrorInfo<StringError> {
+public:
+ static char ID;
+
+ // Prints EC + S and converts to EC
+ StringError(std::error_code EC, const Twine &S = Twine());
+
+ // Prints S and converts to EC
+ StringError(const Twine &S, std::error_code EC);
+
+ void log(raw_ostream &OS) const override;
+ std::error_code convertToErrorCode() const override;
+
+ const std::string &getMessage() const { return Msg; }
+
+private:
+ std::string Msg;
+ std::error_code EC;
+ const bool PrintMsgOnly = false;
+};
+
+/// Create formatted StringError object.
+template <typename... Ts>
+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...);
+ return make_error<StringError>(Stream.str(), EC);
+}
+
+Error createStringError(std::error_code EC, char const *Msg);
+
+inline Error createStringError(std::error_code EC, const Twine &S) {
+ return createStringError(EC, S.str().c_str());
+}
+
+template <typename... Ts>
+inline Error createStringError(std::errc EC, char const *Fmt,
+ const Ts &... Vals) {
+ 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
+/// show more detailed information to the user.
+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);
+ }
+
+ Error takeError() { return Error(std::move(Err)); }
+
+ std::error_code convertToErrorCode() const override;
+
+ // Used by ErrorInfo::classID.
+ static char ID;
+
+private:
+ 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, 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, 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
+/// to form an Error object.
+inline Error createFileError(const Twine &F, std::error_code EC) {
+ 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.
+///
+/// For tool use only. NOT FOR USE IN LIBRARY CODE.
+///
+class ExitOnError {
+public:
+ /// Create an error on exit helper.
+ ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1)
+ : Banner(std::move(Banner)),
+ GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {}
+
+ /// Set the banner string for any errors caught by operator().
+ void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
+
+ /// Set the exit-code mapper function.
+ void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) {
+ this->GetExitCode = std::move(GetExitCode);
+ }
+
+ /// Check Err. If it's in a failure state log the error(s) and exit.
+ void operator()(Error Err) const { checkError(std::move(Err)); }
+
+ /// Check E. If it's in a success state then return the contained value. If
+ /// it's in a failure state log the error(s) and exit.
+ template <typename T> T operator()(Expected<T> &&E) const {
+ checkError(E.takeError());
+ return std::move(*E);
+ }
+
+ /// Check E. If it's in a success state then return the contained reference. If
+ /// it's in a failure state log the error(s) and exit.
+ template <typename T> T& operator()(Expected<T&> &&E) const {
+ checkError(E.takeError());
+ return *E;
+ }
+
+private:
+ void checkError(Error Err) const {
+ if (Err) {
+ int ExitCode = GetExitCode(Err);
+ logAllUnhandledErrors(std::move(Err), errs(), Banner);
+ exit(ExitCode);
+ }
+ }
+
+ std::string Banner;
+ std::function<int(const Error &)> GetExitCode;
+};
+
+/// Conversion from Error to LLVMErrorRef for C error bindings.
+inline LLVMErrorRef wrap(Error Err) {
+ return reinterpret_cast<LLVMErrorRef>(Err.takePayload().release());
+}
+
+/// Conversion from LLVMErrorRef to Error for C error bindings.
+inline Error unwrap(LLVMErrorRef ErrRef) {
+ return Error(std::unique_ptr<ErrorInfoBase>(
+ reinterpret_cast<ErrorInfoBase *>(ErrRef)));
+}
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_ERROR_H
diff --git a/third_party/llvm-project/include/llvm/Support/ErrorHandling.h b/third_party/llvm-project/include/llvm/Support/ErrorHandling.h
new file mode 100644
index 000000000..f75c2984a
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/ErrorHandling.h
@@ -0,0 +1,143 @@
+//===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- 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 an API used to indicate fatal error conditions. Non-fatal
+// errors (most of them) should be handled through LLVMContext.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ERRORHANDLING_H
+#define LLVM_SUPPORT_ERRORHANDLING_H
+
+#include "llvm/Support/Compiler.h"
+#include <string>
+
+namespace llvm {
+class StringRef;
+ class Twine;
+
+ /// An error handler callback.
+ typedef void (*fatal_error_handler_t)(void *user_data,
+ const std::string& reason,
+ bool gen_crash_diag);
+
+ /// install_fatal_error_handler - Installs a new error handler to be used
+ /// whenever a serious (non-recoverable) error is encountered by LLVM.
+ ///
+ /// If no error handler is installed the default is to print the error message
+ /// to stderr, and call exit(1). If an error handler is installed then it is
+ /// the handler's responsibility to log the message, it will no longer be
+ /// printed to stderr. If the error handler returns, then exit(1) will be
+ /// called.
+ ///
+ /// It is dangerous to naively use an error handler which throws an exception.
+ /// Even though some applications desire to gracefully recover from arbitrary
+ /// faults, blindly throwing exceptions through unfamiliar code isn't a way to
+ /// achieve this.
+ ///
+ /// \param user_data - An argument which will be passed to the install error
+ /// handler.
+ void install_fatal_error_handler(fatal_error_handler_t handler,
+ void *user_data = nullptr);
+
+ /// Restores default error handling behaviour.
+ void remove_fatal_error_handler();
+
+ /// ScopedFatalErrorHandler - This is a simple helper class which just
+ /// calls install_fatal_error_handler in its constructor and
+ /// remove_fatal_error_handler in its destructor.
+ struct ScopedFatalErrorHandler {
+ explicit ScopedFatalErrorHandler(fatal_error_handler_t handler,
+ void *user_data = nullptr) {
+ install_fatal_error_handler(handler, user_data);
+ }
+
+ ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); }
+ };
+
+/// Reports a serious error, calling any installed error handler. These
+/// functions are intended to be used for error conditions which are outside
+/// the control of the compiler (I/O errors, invalid user input, etc.)
+///
+/// If no error handler is installed the default is to print the message to
+/// standard error, followed by a newline.
+/// After the error handler is called this function will call exit(1), it
+/// does not return.
+LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason,
+ bool gen_crash_diag = true);
+LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason,
+ bool gen_crash_diag = true);
+LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason,
+ bool gen_crash_diag = true);
+LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason,
+ bool gen_crash_diag = true);
+
+/// Installs a new bad alloc error handler that should be used whenever a
+/// bad alloc error, e.g. failing malloc/calloc, is encountered by LLVM.
+///
+/// The user can install a bad alloc handler, in order to define the behavior
+/// in case of failing allocations, e.g. throwing an exception. Note that this
+/// handler must not trigger any additional allocations itself.
+///
+/// If no error handler is installed the default is to print the error message
+/// to stderr, and call exit(1). If an error handler is installed then it is
+/// the handler's responsibility to log the message, it will no longer be
+/// printed to stderr. If the error handler returns, then exit(1) will be
+/// called.
+///
+///
+/// \param user_data - An argument which will be passed to the installed error
+/// handler.
+void install_bad_alloc_error_handler(fatal_error_handler_t handler,
+ void *user_data = nullptr);
+
+/// Restores default bad alloc error handling behavior.
+void remove_bad_alloc_error_handler();
+
+void install_out_of_memory_new_handler();
+
+/// Reports a bad alloc error, calling any user defined bad alloc
+/// error handler. In contrast to the generic 'report_fatal_error'
+/// functions, this function is expected to return, e.g. the user
+/// defined error handler throws an exception.
+///
+/// Note: When throwing an exception in the bad alloc handler, make sure that
+/// the following unwind succeeds, e.g. do not trigger additional allocations
+/// in the unwind chain.
+///
+/// If no error handler is installed (default), then a bad_alloc exception
+/// is thrown, if LLVM is compiled with exception support, otherwise an
+/// assertion is called.
+void report_bad_alloc_error(const char *Reason, bool GenCrashDiag = true);
+
+/// This function calls abort(), and prints the optional message to stderr.
+/// Use the llvm_unreachable macro (that adds location info), instead of
+/// calling this function directly.
+LLVM_ATTRIBUTE_NORETURN void
+llvm_unreachable_internal(const char *msg = nullptr, const char *file = nullptr,
+ unsigned line = 0);
+}
+
+/// Marks that the current location is not supposed to be reachable.
+/// In !NDEBUG builds, prints the message and location info to stderr.
+/// In NDEBUG builds, becomes an optimizer hint that the current location
+/// is not supposed to be reachable. On compilers that don't support
+/// such hints, prints a reduced message instead.
+///
+/// Use this instead of assert(0). It conveys intent more clearly and
+/// allows compilers to omit some unnecessary code.
+#ifndef NDEBUG
+#define llvm_unreachable(msg) \
+ ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__)
+#elif defined(LLVM_BUILTIN_UNREACHABLE)
+#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE
+#else
+#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal()
+#endif
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/ErrorOr.h b/third_party/llvm-project/include/llvm/Support/ErrorOr.h
new file mode 100644
index 000000000..8211f4d8a
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/ErrorOr.h
@@ -0,0 +1,278 @@
+//===- llvm/Support/ErrorOr.h - Error Smart Pointer -------------*- 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
+///
+/// Provides ErrorOr<T> smart pointer.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ERROROR_H
+#define LLVM_SUPPORT_ERROROR_H
+
+#include "llvm/Support/AlignOf.h"
+#include <cassert>
+#include <system_error>
+#include <type_traits>
+#include <utility>
+
+namespace llvm {
+
+/// Represents either an error or a value T.
+///
+/// ErrorOr<T> is a pointer-like class that represents the result of an
+/// operation. The result is either an error, or a value of type T. This is
+/// designed to emulate the usage of returning a pointer where nullptr indicates
+/// failure. However instead of just knowing that the operation failed, we also
+/// have an error_code and optional user data that describes why it failed.
+///
+/// It is used like the following.
+/// \code
+/// ErrorOr<Buffer> getBuffer();
+///
+/// auto buffer = getBuffer();
+/// if (error_code ec = buffer.getError())
+/// return ec;
+/// buffer->write("adena");
+/// \endcode
+///
+///
+/// Implicit conversion to bool returns true if there is a usable value. The
+/// unary * and -> operators provide pointer like access to the value. Accessing
+/// the value when there is an error has undefined behavior.
+///
+/// When T is a reference type the behavior is slightly different. The reference
+/// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and
+/// there is special handling to make operator -> work as if T was not a
+/// reference.
+///
+/// T cannot be a rvalue reference.
+template<class T>
+class ErrorOr {
+ template <class OtherT> friend class ErrorOr;
+
+ static const bool isRef = std::is_reference<T>::value;
+
+ using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
+
+public:
+ using storage_type = typename std::conditional<isRef, wrap, T>::type;
+
+private:
+ using reference = typename std::remove_reference<T>::type &;
+ using const_reference = const typename std::remove_reference<T>::type &;
+ using pointer = typename std::remove_reference<T>::type *;
+ using const_pointer = const typename std::remove_reference<T>::type *;
+
+public:
+ template <class E>
+ ErrorOr(E ErrorCode,
+ typename std::enable_if<std::is_error_code_enum<E>::value ||
+ std::is_error_condition_enum<E>::value,
+ void *>::type = nullptr)
+ : HasError(true) {
+ new (getErrorStorage()) std::error_code(make_error_code(ErrorCode));
+ }
+
+ ErrorOr(std::error_code EC) : HasError(true) {
+ new (getErrorStorage()) std::error_code(EC);
+ }
+
+ template <class OtherT>
+ ErrorOr(OtherT &&Val,
+ typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
+ * = nullptr)
+ : HasError(false) {
+ new (getStorage()) storage_type(std::forward<OtherT>(Val));
+ }
+
+ ErrorOr(const ErrorOr &Other) {
+ copyConstruct(Other);
+ }
+
+ template <class OtherT>
+ ErrorOr(
+ const ErrorOr<OtherT> &Other,
+ typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
+ nullptr) {
+ copyConstruct(Other);
+ }
+
+ template <class OtherT>
+ explicit ErrorOr(
+ const ErrorOr<OtherT> &Other,
+ typename std::enable_if<
+ !std::is_convertible<OtherT, const T &>::value>::type * = nullptr) {
+ copyConstruct(Other);
+ }
+
+ ErrorOr(ErrorOr &&Other) {
+ moveConstruct(std::move(Other));
+ }
+
+ template <class OtherT>
+ ErrorOr(
+ ErrorOr<OtherT> &&Other,
+ typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
+ nullptr) {
+ moveConstruct(std::move(Other));
+ }
+
+ // This might eventually need SFINAE but it's more complex than is_convertible
+ // & I'm too lazy to write it right now.
+ template <class OtherT>
+ explicit ErrorOr(
+ ErrorOr<OtherT> &&Other,
+ typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
+ nullptr) {
+ moveConstruct(std::move(Other));
+ }
+
+ ErrorOr &operator=(const ErrorOr &Other) {
+ copyAssign(Other);
+ return *this;
+ }
+
+ ErrorOr &operator=(ErrorOr &&Other) {
+ moveAssign(std::move(Other));
+ return *this;
+ }
+
+ ~ErrorOr() {
+ if (!HasError)
+ getStorage()->~storage_type();
+ }
+
+ /// Return false if there is an error.
+ explicit operator bool() const {
+ return !HasError;
+ }
+
+ reference get() { return *getStorage(); }
+ const_reference get() const { return const_cast<ErrorOr<T> *>(this)->get(); }
+
+ std::error_code getError() const {
+ return HasError ? *getErrorStorage() : std::error_code();
+ }
+
+ pointer operator ->() {
+ return toPointer(getStorage());
+ }
+
+ const_pointer operator->() const { return toPointer(getStorage()); }
+
+ reference operator *() {
+ return *getStorage();
+ }
+
+ const_reference operator*() const { return *getStorage(); }
+
+private:
+ template <class OtherT>
+ void copyConstruct(const ErrorOr<OtherT> &Other) {
+ if (!Other.HasError) {
+ // Get the other value.
+ HasError = false;
+ new (getStorage()) storage_type(*Other.getStorage());
+ } else {
+ // Get other's error.
+ HasError = true;
+ new (getErrorStorage()) std::error_code(Other.getError());
+ }
+ }
+
+ template <class T1>
+ static bool compareThisIfSameType(const T1 &a, const T1 &b) {
+ return &a == &b;
+ }
+
+ template <class T1, class T2>
+ static bool compareThisIfSameType(const T1 &a, const T2 &b) {
+ return false;
+ }
+
+ template <class OtherT>
+ void copyAssign(const ErrorOr<OtherT> &Other) {
+ if (compareThisIfSameType(*this, Other))
+ return;
+
+ this->~ErrorOr();
+ new (this) ErrorOr(Other);
+ }
+
+ template <class OtherT>
+ void moveConstruct(ErrorOr<OtherT> &&Other) {
+ if (!Other.HasError) {
+ // Get the other value.
+ HasError = false;
+ new (getStorage()) storage_type(std::move(*Other.getStorage()));
+ } else {
+ // Get other's error.
+ HasError = true;
+ new (getErrorStorage()) std::error_code(Other.getError());
+ }
+ }
+
+ template <class OtherT>
+ void moveAssign(ErrorOr<OtherT> &&Other) {
+ if (compareThisIfSameType(*this, Other))
+ return;
+
+ this->~ErrorOr();
+ new (this) ErrorOr(std::move(Other));
+ }
+
+ pointer toPointer(pointer Val) {
+ return Val;
+ }
+
+ const_pointer toPointer(const_pointer Val) const { return Val; }
+
+ pointer toPointer(wrap *Val) {
+ return &Val->get();
+ }
+
+ const_pointer toPointer(const wrap *Val) const { return &Val->get(); }
+
+ storage_type *getStorage() {
+ assert(!HasError && "Cannot get value when an error exists!");
+ return reinterpret_cast<storage_type*>(TStorage.buffer);
+ }
+
+ const storage_type *getStorage() const {
+ assert(!HasError && "Cannot get value when an error exists!");
+ return reinterpret_cast<const storage_type*>(TStorage.buffer);
+ }
+
+ std::error_code *getErrorStorage() {
+ assert(HasError && "Cannot get error when a value exists!");
+ return reinterpret_cast<std::error_code *>(ErrorStorage.buffer);
+ }
+
+ const std::error_code *getErrorStorage() const {
+ return const_cast<ErrorOr<T> *>(this)->getErrorStorage();
+ }
+
+ union {
+ AlignedCharArrayUnion<storage_type> TStorage;
+ AlignedCharArrayUnion<std::error_code> ErrorStorage;
+ };
+ bool HasError : 1;
+};
+
+template <class T, class E>
+typename std::enable_if<std::is_error_code_enum<E>::value ||
+ std::is_error_condition_enum<E>::value,
+ bool>::type
+operator==(const ErrorOr<T> &Err, E Code) {
+ return Err.getError() == Code;
+}
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_ERROROR_H
diff --git a/third_party/llvm-project/include/llvm/Support/FileOutputBuffer.h b/third_party/llvm-project/include/llvm/Support/FileOutputBuffer.h
new file mode 100644
index 000000000..bdc1425d4
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/FileOutputBuffer.h
@@ -0,0 +1,88 @@
+//=== FileOutputBuffer.h - File Output Buffer -------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating a in-memory buffer that will be written to a file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FILEOUTPUTBUFFER_H
+#define LLVM_SUPPORT_FILEOUTPUTBUFFER_H
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+
+namespace llvm {
+/// FileOutputBuffer - This interface provides simple way to create an in-memory
+/// buffer which will be written to a file. During the lifetime of these
+/// objects, the content or existence of the specified file is undefined. That
+/// is, creating an OutputBuffer for a file may immediately remove the file.
+/// If the FileOutputBuffer is committed, the target file's content will become
+/// the buffer content at the time of the commit. If the FileOutputBuffer is
+/// not committed, the file will be deleted in the FileOutputBuffer destructor.
+class FileOutputBuffer {
+public:
+ enum {
+ /// set the 'x' bit on the resulting file
+ F_executable = 1,
+
+ /// Don't use mmap and instead write an in-memory buffer to a file when this
+ /// buffer is closed.
+ F_no_mmap = 2,
+ };
+
+ /// Factory method to create an OutputBuffer object which manages a read/write
+ /// buffer of the specified size. When committed, the buffer will be written
+ /// to the file at the specified path.
+ ///
+ /// When F_modify is specified and \p FilePath refers to an existing on-disk
+ /// file \p Size may be set to -1, in which case the entire file is used.
+ /// Otherwise, the file shrinks or grows as necessary based on the value of
+ /// \p Size. It is an error to specify F_modify and Size=-1 if \p FilePath
+ /// does not exist.
+ static Expected<std::unique_ptr<FileOutputBuffer>>
+ create(StringRef FilePath, size_t Size, unsigned Flags = 0);
+
+ /// Returns a pointer to the start of the buffer.
+ virtual uint8_t *getBufferStart() const = 0;
+
+ /// Returns a pointer to the end of the buffer.
+ virtual uint8_t *getBufferEnd() const = 0;
+
+ /// Returns size of the buffer.
+ virtual size_t getBufferSize() const = 0;
+
+ /// Returns path where file will show up if buffer is committed.
+ StringRef getPath() const { return FinalPath; }
+
+ /// Flushes the content of the buffer to its file and deallocates the
+ /// buffer. If commit() is not called before this object's destructor
+ /// is called, the file is deleted in the destructor. The optional parameter
+ /// is used if it turns out you want the file size to be smaller than
+ /// initially requested.
+ virtual Error commit() = 0;
+
+ /// If this object was previously committed, the destructor just deletes
+ /// this object. If this object was not committed, the destructor
+ /// deallocates the buffer and the target file is never written.
+ virtual ~FileOutputBuffer() {}
+
+ /// This removes the temporary file (unless it already was committed)
+ /// but keeps the memory mapping alive.
+ virtual void discard() {}
+
+protected:
+ FileOutputBuffer(StringRef Path) : FinalPath(Path) {}
+
+ std::string FinalPath;
+};
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/FileSystem.h b/third_party/llvm-project/include/llvm/Support/FileSystem.h
new file mode 100644
index 000000000..a29a9d787
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/FileSystem.h
@@ -0,0 +1,1444 @@
+//===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the llvm::sys::fs namespace. It is designed after
+// TR2/boost filesystem (v3), but modified to remove exception handling and the
+// path class.
+//
+// All functions return an error_code and their actual work via the last out
+// argument. The out argument is defined if and only if errc::success is
+// returned. A function may return any error code in the generic or system
+// category. However, they shall be equivalent to any error conditions listed
+// in each functions respective documentation if the condition applies. [ note:
+// this does not guarantee that error_code will be in the set of explicitly
+// listed codes, but it does guarantee that if any of the explicitly listed
+// errors occur, the correct error_code will be used ]. All functions may
+// return errc::not_enough_memory if there is not enough memory to complete the
+// operation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FILESYSTEM_H
+#define LLVM_SUPPORT_FILESYSTEM_H
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MD5.h"
+#include <cassert>
+#include <cstdint>
+#include <ctime>
+#include <memory>
+#include <stack>
+#include <string>
+#include <system_error>
+#include <tuple>
+#include <vector>
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+namespace llvm {
+namespace sys {
+namespace fs {
+
+#if defined(_WIN32)
+// A Win32 HANDLE is a typedef of void*
+using file_t = void *;
+#else
+using file_t = int;
+#endif
+
+extern const file_t kInvalidFile;
+
+/// An enumeration for the file system's view of the type.
+enum class file_type {
+ status_error,
+ file_not_found,
+ regular_file,
+ directory_file,
+ symlink_file,
+ block_file,
+ character_file,
+ fifo_file,
+ socket_file,
+ type_unknown
+};
+
+/// space_info - Self explanatory.
+struct space_info {
+ uint64_t capacity;
+ uint64_t free;
+ uint64_t available;
+};
+
+enum perms {
+ no_perms = 0,
+ owner_read = 0400,
+ owner_write = 0200,
+ owner_exe = 0100,
+ owner_all = owner_read | owner_write | owner_exe,
+ group_read = 040,
+ group_write = 020,
+ group_exe = 010,
+ group_all = group_read | group_write | group_exe,
+ others_read = 04,
+ others_write = 02,
+ others_exe = 01,
+ others_all = others_read | others_write | others_exe,
+ all_read = owner_read | group_read | others_read,
+ all_write = owner_write | group_write | others_write,
+ all_exe = owner_exe | group_exe | others_exe,
+ all_all = owner_all | group_all | others_all,
+ set_uid_on_exe = 04000,
+ set_gid_on_exe = 02000,
+ sticky_bit = 01000,
+ all_perms = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit,
+ perms_not_known = 0xFFFF
+};
+
+// Helper functions so that you can use & and | to manipulate perms bits:
+inline perms operator|(perms l, perms r) {
+ return static_cast<perms>(static_cast<unsigned short>(l) |
+ static_cast<unsigned short>(r));
+}
+inline perms operator&(perms l, perms r) {
+ return static_cast<perms>(static_cast<unsigned short>(l) &
+ static_cast<unsigned short>(r));
+}
+inline perms &operator|=(perms &l, perms r) {
+ l = l | r;
+ return l;
+}
+inline perms &operator&=(perms &l, perms r) {
+ l = l & r;
+ return l;
+}
+inline perms operator~(perms x) {
+ // Avoid UB by explicitly truncating the (unsigned) ~ result.
+ return static_cast<perms>(
+ static_cast<unsigned short>(~static_cast<unsigned short>(x)));
+}
+
+class UniqueID {
+ uint64_t Device;
+ uint64_t File;
+
+public:
+ UniqueID() = default;
+ UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
+
+ bool operator==(const UniqueID &Other) const {
+ return Device == Other.Device && File == Other.File;
+ }
+ bool operator!=(const UniqueID &Other) const { return !(*this == Other); }
+ bool operator<(const UniqueID &Other) const {
+ return std::tie(Device, File) < std::tie(Other.Device, Other.File);
+ }
+
+ uint64_t getDevice() const { return Device; }
+ uint64_t getFile() const { return File; }
+};
+
+/// Represents the result of a call to directory_iterator::status(). This is a
+/// subset of the information returned by a regular sys::fs::status() call, and
+/// represents the information provided by Windows FileFirstFile/FindNextFile.
+class basic_file_status {
+protected:
+ #if defined(LLVM_ON_UNIX)
+ time_t fs_st_atime = 0;
+ time_t fs_st_mtime = 0;
+ uint32_t fs_st_atime_nsec = 0;
+ uint32_t fs_st_mtime_nsec = 0;
+ uid_t fs_st_uid = 0;
+ gid_t fs_st_gid = 0;
+ off_t fs_st_size = 0;
+ #elif defined (_WIN32)
+ uint32_t LastAccessedTimeHigh = 0;
+ uint32_t LastAccessedTimeLow = 0;
+ uint32_t LastWriteTimeHigh = 0;
+ uint32_t LastWriteTimeLow = 0;
+ uint32_t FileSizeHigh = 0;
+ uint32_t FileSizeLow = 0;
+ #endif
+ file_type Type = file_type::status_error;
+ perms Perms = perms_not_known;
+
+public:
+ basic_file_status() = default;
+
+ explicit basic_file_status(file_type Type) : Type(Type) {}
+
+ #if defined(LLVM_ON_UNIX)
+ basic_file_status(file_type Type, perms Perms, time_t ATime,
+ uint32_t ATimeNSec, time_t MTime, uint32_t MTimeNSec,
+ uid_t UID, gid_t GID, off_t Size)
+ : fs_st_atime(ATime), fs_st_mtime(MTime),
+ fs_st_atime_nsec(ATimeNSec), fs_st_mtime_nsec(MTimeNSec),
+ fs_st_uid(UID), fs_st_gid(GID),
+ fs_st_size(Size), Type(Type), Perms(Perms) {}
+#elif defined(_WIN32)
+ basic_file_status(file_type Type, perms Perms, uint32_t LastAccessTimeHigh,
+ uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,
+ uint32_t LastWriteTimeLow, uint32_t FileSizeHigh,
+ uint32_t FileSizeLow)
+ : LastAccessedTimeHigh(LastAccessTimeHigh),
+ LastAccessedTimeLow(LastAccessTimeLow),
+ LastWriteTimeHigh(LastWriteTimeHigh),
+ LastWriteTimeLow(LastWriteTimeLow), FileSizeHigh(FileSizeHigh),
+ FileSizeLow(FileSizeLow), Type(Type), Perms(Perms) {}
+ #endif
+
+ // getters
+ file_type type() const { return Type; }
+ perms permissions() const { return Perms; }
+
+ /// The file access time as reported from the underlying file system.
+ ///
+ /// Also see comments on \c getLastModificationTime() related to the precision
+ /// of the returned value.
+ TimePoint<> getLastAccessedTime() const;
+
+ /// The file modification time as reported from the underlying file system.
+ ///
+ /// The returned value allows for nanosecond precision but the actual
+ /// resolution is an implementation detail of the underlying file system.
+ /// There is no guarantee for what kind of resolution you can expect, the
+ /// resolution can differ across platforms and even across mountpoints on the
+ /// same machine.
+ TimePoint<> getLastModificationTime() const;
+
+ #if defined(LLVM_ON_UNIX)
+ uint32_t getUser() const { return fs_st_uid; }
+ uint32_t getGroup() const { return fs_st_gid; }
+ uint64_t getSize() const { return fs_st_size; }
+ #elif defined (_WIN32)
+ uint32_t getUser() const {
+ return 9999; // Not applicable to Windows, so...
+ }
+
+ uint32_t getGroup() const {
+ return 9999; // Not applicable to Windows, so...
+ }
+
+ uint64_t getSize() const {
+ return (uint64_t(FileSizeHigh) << 32) + FileSizeLow;
+ }
+ #endif
+
+ // setters
+ void type(file_type v) { Type = v; }
+ void permissions(perms p) { Perms = p; }
+};
+
+/// Represents the result of a call to sys::fs::status().
+class file_status : public basic_file_status {
+ friend bool equivalent(file_status A, file_status B);
+
+ #if defined(LLVM_ON_UNIX)
+ dev_t fs_st_dev = 0;
+ nlink_t fs_st_nlinks = 0;
+ ino_t fs_st_ino = 0;
+ #elif defined (_WIN32)
+ uint32_t NumLinks = 0;
+ uint32_t VolumeSerialNumber = 0;
+ uint32_t FileIndexHigh = 0;
+ uint32_t FileIndexLow = 0;
+ #endif
+
+public:
+ file_status() = default;
+
+ explicit file_status(file_type Type) : basic_file_status(Type) {}
+
+ #if defined(LLVM_ON_UNIX)
+ file_status(file_type Type, perms Perms, dev_t Dev, nlink_t Links, ino_t Ino,
+ time_t ATime, uint32_t ATimeNSec,
+ time_t MTime, uint32_t MTimeNSec,
+ uid_t UID, gid_t GID, off_t Size)
+ : basic_file_status(Type, Perms, ATime, ATimeNSec, MTime, MTimeNSec,
+ UID, GID, Size),
+ fs_st_dev(Dev), fs_st_nlinks(Links), fs_st_ino(Ino) {}
+ #elif defined(_WIN32)
+ file_status(file_type Type, perms Perms, uint32_t LinkCount,
+ uint32_t LastAccessTimeHigh, uint32_t LastAccessTimeLow,
+ uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow,
+ uint32_t VolumeSerialNumber, uint32_t FileSizeHigh,
+ uint32_t FileSizeLow, uint32_t FileIndexHigh,
+ uint32_t FileIndexLow)
+ : basic_file_status(Type, Perms, LastAccessTimeHigh, LastAccessTimeLow,
+ LastWriteTimeHigh, LastWriteTimeLow, FileSizeHigh,
+ FileSizeLow),
+ NumLinks(LinkCount), VolumeSerialNumber(VolumeSerialNumber),
+ FileIndexHigh(FileIndexHigh), FileIndexLow(FileIndexLow) {}
+ #endif
+
+ UniqueID getUniqueID() const;
+ uint32_t getLinkCount() const;
+};
+
+/// @}
+/// @name Physical Operators
+/// @{
+
+/// Make \a path an absolute path.
+///
+/// Makes \a path absolute using the \a current_directory if it is not already.
+/// An empty \a path will result in the \a current_directory.
+///
+/// /absolute/path => /absolute/path
+/// relative/../path => <current-directory>/relative/../path
+///
+/// @param path A path that is modified to be an absolute path.
+void make_absolute(const Twine &current_directory, SmallVectorImpl<char> &path);
+
+/// Make \a path an absolute path.
+///
+/// Makes \a path absolute using the current directory if it is not already. An
+/// empty \a path will result in the current directory.
+///
+/// /absolute/path => /absolute/path
+/// relative/../path => <current-directory>/relative/../path
+///
+/// @param path A path that is modified to be an absolute path.
+/// @returns errc::success if \a path has been made absolute, otherwise a
+/// platform-specific error_code.
+std::error_code make_absolute(SmallVectorImpl<char> &path);
+
+/// Create all the non-existent directories in path.
+///
+/// @param path Directories to create.
+/// @returns errc::success if is_directory(path), otherwise a platform
+/// specific error_code. If IgnoreExisting is false, also returns
+/// error if the directory already existed.
+std::error_code create_directories(const Twine &path,
+ bool IgnoreExisting = true,
+ perms Perms = owner_all | group_all);
+
+/// Create the directory in path.
+///
+/// @param path Directory to create.
+/// @returns errc::success if is_directory(path), otherwise a platform
+/// specific error_code. If IgnoreExisting is false, also returns
+/// error if the directory already existed.
+std::error_code create_directory(const Twine &path, bool IgnoreExisting = true,
+ perms Perms = owner_all | group_all);
+
+/// Create a link from \a from to \a to.
+///
+/// The link may be a soft or a hard link, depending on the platform. The caller
+/// may not assume which one. Currently on windows it creates a hard link since
+/// soft links require extra privileges. On unix, it creates a soft link since
+/// hard links don't work on SMB file systems.
+///
+/// @param to The path to hard link to.
+/// @param from The path to hard link from. This is created.
+/// @returns errc::success if the link was created, otherwise a platform
+/// specific error_code.
+std::error_code create_link(const Twine &to, const Twine &from);
+
+/// Create a hard link from \a from to \a to, or return an error.
+///
+/// @param to The path to hard link to.
+/// @param from The path to hard link from. This is created.
+/// @returns errc::success if the link was created, otherwise a platform
+/// specific error_code.
+std::error_code create_hard_link(const Twine &to, const Twine &from);
+
+/// Collapse all . and .. patterns, resolve all symlinks, and optionally
+/// expand ~ expressions to the user's home directory.
+///
+/// @param path The path to resolve.
+/// @param output The location to store the resolved path.
+/// @param expand_tilde If true, resolves ~ expressions to the user's home
+/// directory.
+std::error_code real_path(const Twine &path, SmallVectorImpl<char> &output,
+ bool expand_tilde = false);
+
+/// Expands ~ expressions to the user's home directory. On Unix ~user
+/// directories are resolved as well.
+///
+/// @param path The path to resolve.
+void expand_tilde(const Twine &path, SmallVectorImpl<char> &output);
+
+/// Get the current path.
+///
+/// @param result Holds the current path on return.
+/// @returns errc::success if the current path has been stored in result,
+/// otherwise a platform-specific error_code.
+std::error_code current_path(SmallVectorImpl<char> &result);
+
+/// Set the current path.
+///
+/// @param path The path to set.
+/// @returns errc::success if the current path was successfully set,
+/// otherwise a platform-specific error_code.
+std::error_code set_current_path(const Twine &path);
+
+/// Remove path. Equivalent to POSIX remove().
+///
+/// @param path Input path.
+/// @returns errc::success if path has been removed or didn't exist, otherwise a
+/// platform-specific error code. If IgnoreNonExisting is false, also
+/// returns error if the file didn't exist.
+std::error_code remove(const Twine &path, bool IgnoreNonExisting = true);
+
+/// Recursively delete a directory.
+///
+/// @param path Input path.
+/// @returns errc::success if path has been removed or didn't exist, otherwise a
+/// platform-specific error code.
+std::error_code remove_directories(const Twine &path, bool IgnoreErrors = true);
+
+/// Rename \a from to \a to.
+///
+/// Files are renamed as if by POSIX rename(), except that on Windows there may
+/// be a short interval of time during which the destination file does not
+/// exist.
+///
+/// @param from The path to rename from.
+/// @param to The path to rename to. This is created.
+std::error_code rename(const Twine &from, const Twine &to);
+
+/// Copy the contents of \a From to \a To.
+///
+/// @param From The path to copy from.
+/// @param To The path to copy to. This is created.
+std::error_code copy_file(const Twine &From, const Twine &To);
+
+/// Copy the contents of \a From to \a To.
+///
+/// @param From The path to copy from.
+/// @param ToFD The open file descriptor of the destination file.
+std::error_code copy_file(const Twine &From, int ToFD);
+
+/// Resize path to size. File is resized as if by POSIX truncate().
+///
+/// @param FD Input file descriptor.
+/// @param Size Size to resize to.
+/// @returns errc::success if \a path has been resized to \a size, otherwise a
+/// platform-specific error_code.
+std::error_code resize_file(int FD, uint64_t Size);
+
+/// Compute an MD5 hash of a file's contents.
+///
+/// @param FD Input file descriptor.
+/// @returns An MD5Result with the hash computed, if successful, otherwise a
+/// std::error_code.
+ErrorOr<MD5::MD5Result> md5_contents(int FD);
+
+/// Version of compute_md5 that doesn't require an open file descriptor.
+ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path);
+
+/// @}
+/// @name Physical Observers
+/// @{
+
+/// Does file exist?
+///
+/// @param status A basic_file_status previously returned from stat.
+/// @returns True if the file represented by status exists, false if it does
+/// not.
+bool exists(const basic_file_status &status);
+
+enum class AccessMode { Exist, Write, Execute };
+
+/// Can the file be accessed?
+///
+/// @param Path Input path.
+/// @returns errc::success if the path can be accessed, otherwise a
+/// platform-specific error_code.
+std::error_code access(const Twine &Path, AccessMode Mode);
+
+/// Does file exist?
+///
+/// @param Path Input path.
+/// @returns True if it exists, false otherwise.
+inline bool exists(const Twine &Path) {
+ return !access(Path, AccessMode::Exist);
+}
+
+/// Can we execute this file?
+///
+/// @param Path Input path.
+/// @returns True if we can execute it, false otherwise.
+bool can_execute(const Twine &Path);
+
+/// Can we write this file?
+///
+/// @param Path Input path.
+/// @returns True if we can write to it, false otherwise.
+inline bool can_write(const Twine &Path) {
+ return !access(Path, AccessMode::Write);
+}
+
+/// Do file_status's represent the same thing?
+///
+/// @param A Input file_status.
+/// @param B Input file_status.
+///
+/// assert(status_known(A) || status_known(B));
+///
+/// @returns True if A and B both represent the same file system entity, false
+/// otherwise.
+bool equivalent(file_status A, file_status B);
+
+/// Do paths represent the same thing?
+///
+/// assert(status_known(A) || status_known(B));
+///
+/// @param A Input path A.
+/// @param B Input path B.
+/// @param result Set to true if stat(A) and stat(B) have the same device and
+/// inode (or equivalent).
+/// @returns errc::success if result has been successfully set, otherwise a
+/// platform-specific error_code.
+std::error_code equivalent(const Twine &A, const Twine &B, bool &result);
+
+/// Simpler version of equivalent for clients that don't need to
+/// differentiate between an error and false.
+inline bool equivalent(const Twine &A, const Twine &B) {
+ bool result;
+ return !equivalent(A, B, result) && result;
+}
+
+/// Is the file mounted on a local filesystem?
+///
+/// @param path Input path.
+/// @param result Set to true if \a path is on fixed media such as a hard disk,
+/// false if it is not.
+/// @returns errc::success if result has been successfully set, otherwise a
+/// platform specific error_code.
+std::error_code is_local(const Twine &path, bool &result);
+
+/// Version of is_local accepting an open file descriptor.
+std::error_code is_local(int FD, bool &result);
+
+/// Simpler version of is_local for clients that don't need to
+/// differentiate between an error and false.
+inline bool is_local(const Twine &Path) {
+ bool Result;
+ return !is_local(Path, Result) && Result;
+}
+
+/// Simpler version of is_local accepting an open file descriptor for
+/// clients that don't need to differentiate between an error and false.
+inline bool is_local(int FD) {
+ bool Result;
+ return !is_local(FD, Result) && Result;
+}
+
+/// Does status represent a directory?
+///
+/// @param Path The path to get the type of.
+/// @param Follow For symbolic links, indicates whether to return the file type
+/// of the link itself, or of the target.
+/// @returns A value from the file_type enumeration indicating the type of file.
+file_type get_file_type(const Twine &Path, bool Follow = true);
+
+/// Does status represent a directory?
+///
+/// @param status A basic_file_status previously returned from status.
+/// @returns status.type() == file_type::directory_file.
+bool is_directory(const basic_file_status &status);
+
+/// Is path a directory?
+///
+/// @param path Input path.
+/// @param result Set to true if \a path is a directory (after following
+/// symlinks, false if it is not. Undefined otherwise.
+/// @returns errc::success if result has been successfully set, otherwise a
+/// platform-specific error_code.
+std::error_code is_directory(const Twine &path, bool &result);
+
+/// Simpler version of is_directory for clients that don't need to
+/// differentiate between an error and false.
+inline bool is_directory(const Twine &Path) {
+ bool Result;
+ return !is_directory(Path, Result) && Result;
+}
+
+/// Does status represent a regular file?
+///
+/// @param status A basic_file_status previously returned from status.
+/// @returns status_known(status) && status.type() == file_type::regular_file.
+bool is_regular_file(const basic_file_status &status);
+
+/// Is path a regular file?
+///
+/// @param path Input path.
+/// @param result Set to true if \a path is a regular file (after following
+/// symlinks), false if it is not. Undefined otherwise.
+/// @returns errc::success if result has been successfully set, otherwise a
+/// platform-specific error_code.
+std::error_code is_regular_file(const Twine &path, bool &result);
+
+/// Simpler version of is_regular_file for clients that don't need to
+/// differentiate between an error and false.
+inline bool is_regular_file(const Twine &Path) {
+ bool Result;
+ if (is_regular_file(Path, Result))
+ return false;
+ return Result;
+}
+
+/// Does status represent a symlink file?
+///
+/// @param status A basic_file_status previously returned from status.
+/// @returns status_known(status) && status.type() == file_type::symlink_file.
+bool is_symlink_file(const basic_file_status &status);
+
+/// Is path a symlink file?
+///
+/// @param path Input path.
+/// @param result Set to true if \a path is a symlink file, false if it is not.
+/// Undefined otherwise.
+/// @returns errc::success if result has been successfully set, otherwise a
+/// platform-specific error_code.
+std::error_code is_symlink_file(const Twine &path, bool &result);
+
+/// Simpler version of is_symlink_file for clients that don't need to
+/// differentiate between an error and false.
+inline bool is_symlink_file(const Twine &Path) {
+ bool Result;
+ if (is_symlink_file(Path, Result))
+ return false;
+ return Result;
+}
+
+/// Does this status represent something that exists but is not a
+/// directory or regular file?
+///
+/// @param status A basic_file_status previously returned from status.
+/// @returns exists(s) && !is_regular_file(s) && !is_directory(s)
+bool is_other(const basic_file_status &status);
+
+/// Is path something that exists but is not a directory,
+/// regular file, or symlink?
+///
+/// @param path Input path.
+/// @param result Set to true if \a path exists, but is not a directory, regular
+/// file, or a symlink, false if it does not. Undefined otherwise.
+/// @returns errc::success if result has been successfully set, otherwise a
+/// platform-specific error_code.
+std::error_code is_other(const Twine &path, bool &result);
+
+/// Get file status as if by POSIX stat().
+///
+/// @param path Input path.
+/// @param result Set to the file status.
+/// @param follow When true, follows symlinks. Otherwise, the symlink itself is
+/// statted.
+/// @returns errc::success if result has been successfully set, otherwise a
+/// platform-specific error_code.
+std::error_code status(const Twine &path, file_status &result,
+ bool follow = true);
+
+/// 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.
+/// @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);
+
+/// Vesion of setPermissions accepting a file descriptor.
+/// TODO Delete the path based overload once we implement the FD based overload
+/// on Windows.
+std::error_code setPermissions(int FD, perms Permissions);
+
+/// Get file permissions.
+///
+/// @param Path File to get permissions from.
+/// @returns the permissions if they were successfully retrieved, otherwise a
+/// platform-specific error_code.
+/// @note On Windows, if the file does not have the FILE_ATTRIBUTE_READONLY
+/// attribute, all_all will be returned. Otherwise, all_read | all_exe
+/// will be returned.
+ErrorOr<perms> getPermissions(const Twine &Path);
+
+/// Get file size.
+///
+/// @param Path Input path.
+/// @param Result Set to the size of the file in \a Path.
+/// @returns errc::success if result has been successfully set, otherwise a
+/// platform-specific error_code.
+inline std::error_code file_size(const Twine &Path, uint64_t &Result) {
+ file_status Status;
+ std::error_code EC = status(Path, Status);
+ if (EC)
+ return EC;
+ Result = Status.getSize();
+ return std::error_code();
+}
+
+/// Set the file modification and access time.
+///
+/// @returns errc::success if the file times were successfully set, otherwise a
+/// platform-specific error_code or errc::function_not_supported on
+/// platforms where the functionality isn't available.
+std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
+ TimePoint<> ModificationTime);
+
+/// Simpler version that sets both file modification and access time to the same
+/// time.
+inline std::error_code setLastAccessAndModificationTime(int FD,
+ TimePoint<> Time) {
+ return setLastAccessAndModificationTime(FD, Time, Time);
+}
+
+/// Is status available?
+///
+/// @param s Input file status.
+/// @returns True if status() != status_error.
+bool status_known(const basic_file_status &s);
+
+/// Is status available?
+///
+/// @param path Input path.
+/// @param result Set to true if status() != status_error.
+/// @returns errc::success if result has been successfully set, otherwise a
+/// platform-specific error_code.
+std::error_code status_known(const Twine &path, bool &result);
+
+enum CreationDisposition : unsigned {
+ /// CD_CreateAlways - When opening a file:
+ /// * If it already exists, truncate it.
+ /// * If it does not already exist, create a new file.
+ CD_CreateAlways = 0,
+
+ /// CD_CreateNew - When opening a file:
+ /// * If it already exists, fail.
+ /// * If it does not already exist, create a new file.
+ CD_CreateNew = 1,
+
+ /// CD_OpenExisting - When opening a file:
+ /// * If it already exists, open the file with the offset set to 0.
+ /// * If it does not already exist, fail.
+ CD_OpenExisting = 2,
+
+ /// CD_OpenAlways - When opening a file:
+ /// * If it already exists, open the file with the offset set to 0.
+ /// * If it does not already exist, create a new file.
+ CD_OpenAlways = 3,
+};
+
+enum FileAccess : unsigned {
+ FA_Read = 1,
+ FA_Write = 2,
+};
+
+enum OpenFlags : unsigned {
+ OF_None = 0,
+ F_None = 0, // For compatibility
+
+ /// The file should be opened in text mode on platforms that make this
+ /// distinction.
+ OF_Text = 1,
+ F_Text = 1, // For compatibility
+
+ /// The file should be opened in append mode.
+ OF_Append = 2,
+ F_Append = 2, // For compatibility
+
+ /// Delete the file on close. Only makes a difference on windows.
+ OF_Delete = 4,
+
+ /// When a child process is launched, this file should remain open in the
+ /// child process.
+ OF_ChildInherit = 8,
+
+ /// Force files Atime to be updated on access. Only makes a difference on windows.
+ 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
+/// created in the current directory.
+///
+/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s
+///
+/// This is an atomic operation. Either the file is created and opened, or the
+/// file system is left untouched.
+///
+/// The intended use is for files that are to be kept, possibly after
+/// renaming them. For example, when running 'clang -c foo.o', the file can
+/// be first created as foo-abc123.o and then renamed.
+///
+/// @param Model Name to base unique path off of.
+/// @param ResultFD Set to the opened file's file descriptor.
+/// @param ResultPath Set to the opened file's absolute path.
+/// @returns errc::success if Result{FD,Path} have been successfully set,
+/// otherwise a platform-specific error_code.
+std::error_code createUniqueFile(const Twine &Model, int &ResultFD,
+ SmallVectorImpl<char> &ResultPath,
+ unsigned Mode = all_read | all_write);
+
+/// Simpler version for clients that don't want an open file. An empty
+/// file will still be created.
+std::error_code createUniqueFile(const Twine &Model,
+ SmallVectorImpl<char> &ResultPath,
+ unsigned Mode = all_read | all_write);
+
+/// Represents a temporary file.
+///
+/// The temporary file must be eventually discarded or given a final name and
+/// kept.
+///
+/// The destructor doesn't implicitly discard because there is no way to
+/// properly handle errors in a destructor.
+class TempFile {
+ bool Done = false;
+ TempFile(StringRef Name, int FD);
+
+public:
+ /// This creates a temporary file with createUniqueFile and schedules it for
+ /// deletion with sys::RemoveFileOnSignal.
+ static Expected<TempFile> create(const Twine &Model,
+ unsigned Mode = all_read | all_write);
+ TempFile(TempFile &&Other);
+ TempFile &operator=(TempFile &&Other);
+
+ // Name of the temporary file.
+ std::string TmpName;
+
+ // The open file descriptor.
+ int FD = -1;
+
+ // Keep this with the given name.
+ Error keep(const Twine &Name);
+
+ // Keep this with the temporary name.
+ Error keep();
+
+ // Delete the file.
+ Error discard();
+
+ // This checks that keep or delete was called.
+ ~TempFile();
+};
+
+/// Create a file in the system temporary directory.
+///
+/// The filename is of the form prefix-random_chars.suffix. Since the directory
+/// is not know to the caller, Prefix and Suffix cannot have path separators.
+/// The files are created with mode 0600.
+///
+/// This should be used for things like a temporary .s that is removed after
+/// running the assembler.
+std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
+ int &ResultFD,
+ SmallVectorImpl<char> &ResultPath);
+
+/// Simpler version for clients that don't want an open file. An empty
+/// file will still be created.
+std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
+ SmallVectorImpl<char> &ResultPath);
+
+std::error_code createUniqueDirectory(const Twine &Prefix,
+ SmallVectorImpl<char> &ResultPath);
+
+/// Get a unique name, not currently exisiting in the filesystem. Subject
+/// to race conditions, prefer to use createUniqueFile instead.
+///
+/// Similar to createUniqueFile, but instead of creating a file only
+/// checks if it exists. This function is subject to race conditions, if you
+/// want to use the returned name to actually create a file, use
+/// createUniqueFile instead.
+std::error_code getPotentiallyUniqueFileName(const Twine &Model,
+ SmallVectorImpl<char> &ResultPath);
+
+/// Get a unique temporary file name, not currently exisiting in the
+/// filesystem. Subject to race conditions, prefer to use createTemporaryFile
+/// instead.
+///
+/// Similar to createTemporaryFile, but instead of creating a file only
+/// checks if it exists. This function is subject to race conditions, if you
+/// want to use the returned name to actually create a file, use
+/// createTemporaryFile instead.
+std::error_code
+getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
+ SmallVectorImpl<char> &ResultPath);
+
+inline OpenFlags operator|(OpenFlags A, OpenFlags B) {
+ return OpenFlags(unsigned(A) | unsigned(B));
+}
+
+inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) {
+ A = A | B;
+ return A;
+}
+
+inline FileAccess operator|(FileAccess A, FileAccess B) {
+ return FileAccess(unsigned(A) | unsigned(B));
+}
+
+inline FileAccess &operator|=(FileAccess &A, FileAccess B) {
+ A = A | B;
+ return A;
+}
+
+/// @brief Opens a file with the specified creation disposition, access mode,
+/// and flags and returns a file descriptor.
+///
+/// The caller is responsible for closing the file descriptor once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param ResultFD If the file could be opened successfully, its descriptor
+/// is stored in this location. Otherwise, this is set to -1.
+/// @param Disp Value specifying the existing-file behavior.
+/// @param Access Value specifying whether to open the file in read, write, or
+/// read-write mode.
+/// @param Flags Additional flags.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns errc::success if \a Name has been opened, otherwise a
+/// platform-specific error_code.
+std::error_code openFile(const Twine &Name, int &ResultFD,
+ CreationDisposition Disp, FileAccess Access,
+ OpenFlags Flags, unsigned Mode = 0666);
+
+/// @brief Opens a file with the specified creation disposition, access mode,
+/// and flags and returns a platform-specific file object.
+///
+/// The caller is responsible for closing the file object once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param Disp Value specifying the existing-file behavior.
+/// @param Access Value specifying whether to open the file in read, write, or
+/// read-write mode.
+/// @param Flags Additional flags.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns errc::success if \a Name has been opened, otherwise a
+/// platform-specific error_code.
+Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp,
+ 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. Returns the number
+/// of bytes actually read. On Unix, this is equivalent to `return ::read(FD,
+/// Buf.data(), Buf.size())`, with error reporting. Returns 0 when reaching EOF.
+///
+/// @param FileHandle File to read from.
+/// @param Buf Buffer to read into.
+/// @returns The number of bytes read, or error.
+Expected<size_t> readNativeFile(file_t FileHandle, MutableArrayRef<char> Buf);
+
+/// Reads \p Buf.size() bytes from \p FileHandle at offset \p Offset into \p
+/// Buf. If 'pread' is available, this will use that, otherwise it will use
+/// 'lseek'. Returns the number of bytes actually read. Returns 0 when reaching
+/// EOF.
+///
+/// @param FileHandle File to read from.
+/// @param Buf Buffer to read into.
+/// @param Offset Offset into the file at which the read should occur.
+/// @returns The number of bytes read, or error.
+Expected<size_t> readNativeFileSlice(file_t FileHandle,
+ MutableArrayRef<char> Buf,
+ uint64_t Offset);
+
+/// @brief Opens the file with the given name in a write-only or read-write
+/// mode, returning its open file descriptor. If the file does not exist, it
+/// is created.
+///
+/// The caller is responsible for closing the file descriptor once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param ResultFD If the file could be opened successfully, its descriptor
+/// is stored in this location. Otherwise, this is set to -1.
+/// @param Flags Additional flags used to determine whether the file should be
+/// opened in, for example, read-write or in write-only mode.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns errc::success if \a Name has been opened, otherwise a
+/// platform-specific error_code.
+inline std::error_code
+openFileForWrite(const Twine &Name, int &ResultFD,
+ CreationDisposition Disp = CD_CreateAlways,
+ OpenFlags Flags = OF_None, unsigned Mode = 0666) {
+ return openFile(Name, ResultFD, Disp, FA_Write, Flags, Mode);
+}
+
+/// @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.
+///
+/// The caller is responsible for closing the freeing the file once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param Flags Additional flags used to determine whether the file should be
+/// opened in, for example, read-write or in write-only mode.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns a platform-specific file descriptor if \a Name has been opened,
+/// otherwise an error object.
+inline Expected<file_t> openNativeFileForWrite(const Twine &Name,
+ CreationDisposition Disp,
+ OpenFlags Flags,
+ unsigned Mode = 0666) {
+ return openNativeFile(Name, Disp, FA_Write, Flags, Mode);
+}
+
+/// @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.
+///
+/// The caller is responsible for closing the file descriptor once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param ResultFD If the file could be opened successfully, its descriptor
+/// is stored in this location. Otherwise, this is set to -1.
+/// @param Flags Additional flags used to determine whether the file should be
+/// opened in, for example, read-write or in write-only mode.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns errc::success if \a Name has been opened, otherwise a
+/// platform-specific error_code.
+inline std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD,
+ CreationDisposition Disp,
+ OpenFlags Flags,
+ unsigned Mode = 0666) {
+ return openFile(Name, ResultFD, Disp, FA_Write | FA_Read, Flags, Mode);
+}
+
+/// @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.
+///
+/// The caller is responsible for closing the freeing the file once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param Flags Additional flags used to determine whether the file should be
+/// opened in, for example, read-write or in write-only mode.
+/// @param Mode The access permissions of the file, represented in octal.
+/// @returns a platform-specific file descriptor if \a Name has been opened,
+/// otherwise an error object.
+inline Expected<file_t> openNativeFileForReadWrite(const Twine &Name,
+ CreationDisposition Disp,
+ OpenFlags Flags,
+ unsigned Mode = 0666) {
+ return openNativeFile(Name, Disp, FA_Write | FA_Read, Flags, Mode);
+}
+
+/// @brief Opens the file with the given name in a read-only mode, returning
+/// its open file descriptor.
+///
+/// The caller is responsible for closing the file descriptor once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param ResultFD If the file could be opened successfully, its descriptor
+/// is stored in this location. Otherwise, this is set to -1.
+/// @param RealPath If nonnull, extra work is done to determine the real path
+/// of the opened file, and that path is stored in this
+/// location.
+/// @returns errc::success if \a Name has been opened, otherwise a
+/// platform-specific error_code.
+std::error_code openFileForRead(const Twine &Name, int &ResultFD,
+ OpenFlags Flags = OF_None,
+ SmallVectorImpl<char> *RealPath = nullptr);
+
+/// @brief Opens the file with the given name in a read-only mode, returning
+/// its open file descriptor.
+///
+/// The caller is responsible for closing the freeing the file once they are
+/// finished with it.
+///
+/// @param Name The path of the file to open, relative or absolute.
+/// @param RealPath If nonnull, extra work is done to determine the real path
+/// of the opened file, and that path is stored in this
+/// location.
+/// @returns a platform-specific file descriptor if \a Name has been opened,
+/// otherwise an error object.
+Expected<file_t>
+openNativeFileForRead(const Twine &Name, OpenFlags Flags = OF_None,
+ SmallVectorImpl<char> *RealPath = nullptr);
+
+/// @brief Close the file object. This should be used instead of ::close for
+/// portability. On error, the caller should assume the file is closed, as is
+/// the case for Process::SafelyCloseFileDescriptor
+///
+/// @param F On input, this is the file to close. On output, the file is
+/// set to kInvalidFile.
+///
+/// @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);
+
+/// Get disk space usage information.
+///
+/// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug.
+/// Note: Windows reports results according to the quota allocated to the user.
+///
+/// @param Path Input path.
+/// @returns a space_info structure filled with the capacity, free, and
+/// available space on the device \a Path is on. A platform specific error_code
+/// is returned on error.
+ErrorOr<space_info> disk_space(const Twine &Path);
+
+/// This class represents a memory mapped file. It is based on
+/// boost::iostreams::mapped_file.
+class mapped_file_region {
+public:
+ enum mapmode {
+ readonly, ///< May only access map via const_data as read only.
+ readwrite, ///< May access map via data and modify it. Written to path.
+ priv ///< May modify via data, but changes are lost on destruction.
+ };
+
+private:
+ /// Platform-specific mapping state.
+ size_t Size;
+ void *Mapping;
+#ifdef _WIN32
+ sys::fs::file_t FileHandle;
+#endif
+ 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. 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();
+
+ size_t size() const;
+ char *data() const;
+
+ /// Get a const view of the data. Modifying this memory has undefined
+ /// behavior.
+ const char *const_data() const;
+
+ /// \returns The minimum alignment offset must be.
+ static int alignment();
+};
+
+/// Return the path to the main executable, given the value of argv[0] from
+/// program startup and the address of main itself. In extremis, this function
+/// may fail and return an empty path.
+std::string getMainExecutable(const char *argv0, void *MainExecAddr);
+
+/// @}
+/// @name Iterators
+/// @{
+
+/// directory_entry - A single entry in a directory.
+class directory_entry {
+ // FIXME: different platforms make different information available "for free"
+ // when traversing a directory. The design of this class wraps most of the
+ // information in basic_file_status, so on platforms where we can't populate
+ // that whole structure, callers end up paying for a stat().
+ // std::filesystem::directory_entry may be a better model.
+ std::string Path;
+ file_type Type = file_type::type_unknown; // Most platforms can provide this.
+ bool FollowSymlinks = true; // Affects the behavior of status().
+ basic_file_status Status; // If available.
+
+public:
+ explicit directory_entry(const Twine &Path, bool FollowSymlinks = true,
+ file_type Type = file_type::type_unknown,
+ basic_file_status Status = basic_file_status())
+ : Path(Path.str()), Type(Type), FollowSymlinks(FollowSymlinks),
+ Status(Status) {}
+
+ directory_entry() = default;
+
+ void replace_filename(const Twine &Filename, file_type Type,
+ basic_file_status Status = basic_file_status());
+
+ const std::string &path() const { return Path; }
+ // Get basic information about entry file (a subset of fs::status()).
+ // On most platforms this is a stat() call.
+ // On windows the information was already retrieved from the directory.
+ ErrorOr<basic_file_status> status() const;
+ // Get the type of this file.
+ // On most platforms (Linux/Mac/Windows/BSD), this was already retrieved.
+ // On some platforms (e.g. Solaris) this is a stat() call.
+ file_type type() const {
+ if (Type != file_type::type_unknown)
+ return Type;
+ auto S = status();
+ return S ? S->type() : file_type::type_unknown;
+ }
+
+ bool operator==(const directory_entry& RHS) const { return Path == RHS.Path; }
+ bool operator!=(const directory_entry& RHS) const { return !(*this == RHS); }
+ bool operator< (const directory_entry& RHS) const;
+ bool operator<=(const directory_entry& RHS) const;
+ bool operator> (const directory_entry& RHS) const;
+ bool operator>=(const directory_entry& RHS) const;
+};
+
+namespace detail {
+
+ struct DirIterState;
+
+ std::error_code directory_iterator_construct(DirIterState &, StringRef, bool);
+ std::error_code directory_iterator_increment(DirIterState &);
+ std::error_code directory_iterator_destruct(DirIterState &);
+
+ /// Keeps state for the directory_iterator.
+ struct DirIterState {
+ ~DirIterState() {
+ directory_iterator_destruct(*this);
+ }
+
+ intptr_t IterationHandle = 0;
+ directory_entry CurrentEntry;
+ };
+
+} // end namespace detail
+
+/// directory_iterator - Iterates through the entries in path. There is no
+/// operator++ because we need an error_code. If it's really needed we can make
+/// it call report_fatal_error on error.
+class directory_iterator {
+ std::shared_ptr<detail::DirIterState> State;
+ bool FollowSymlinks = true;
+
+public:
+ explicit directory_iterator(const Twine &path, std::error_code &ec,
+ bool follow_symlinks = true)
+ : FollowSymlinks(follow_symlinks) {
+ State = std::make_shared<detail::DirIterState>();
+ SmallString<128> path_storage;
+ ec = detail::directory_iterator_construct(
+ *State, path.toStringRef(path_storage), FollowSymlinks);
+ }
+
+ explicit directory_iterator(const directory_entry &de, std::error_code &ec,
+ bool follow_symlinks = true)
+ : FollowSymlinks(follow_symlinks) {
+ State = std::make_shared<detail::DirIterState>();
+ ec = detail::directory_iterator_construct(
+ *State, de.path(), FollowSymlinks);
+ }
+
+ /// Construct end iterator.
+ directory_iterator() = default;
+
+ // No operator++ because we need error_code.
+ directory_iterator &increment(std::error_code &ec) {
+ ec = directory_iterator_increment(*State);
+ return *this;
+ }
+
+ const directory_entry &operator*() const { return State->CurrentEntry; }
+ const directory_entry *operator->() const { return &State->CurrentEntry; }
+
+ bool operator==(const directory_iterator &RHS) const {
+ if (State == RHS.State)
+ return true;
+ if (!RHS.State)
+ return State->CurrentEntry == directory_entry();
+ if (!State)
+ return RHS.State->CurrentEntry == directory_entry();
+ return State->CurrentEntry == RHS.State->CurrentEntry;
+ }
+
+ bool operator!=(const directory_iterator &RHS) const {
+ return !(*this == RHS);
+ }
+};
+
+namespace detail {
+
+ /// Keeps state for the recursive_directory_iterator.
+ struct RecDirIterState {
+ std::stack<directory_iterator, std::vector<directory_iterator>> Stack;
+ uint16_t Level = 0;
+ bool HasNoPushRequest = false;
+ };
+
+} // end namespace detail
+
+/// recursive_directory_iterator - Same as directory_iterator except for it
+/// recurses down into child directories.
+class recursive_directory_iterator {
+ std::shared_ptr<detail::RecDirIterState> State;
+ bool Follow;
+
+public:
+ recursive_directory_iterator() = default;
+ explicit recursive_directory_iterator(const Twine &path, std::error_code &ec,
+ bool follow_symlinks = true)
+ : State(std::make_shared<detail::RecDirIterState>()),
+ Follow(follow_symlinks) {
+ State->Stack.push(directory_iterator(path, ec, Follow));
+ if (State->Stack.top() == directory_iterator())
+ State.reset();
+ }
+
+ // No operator++ because we need error_code.
+ recursive_directory_iterator &increment(std::error_code &ec) {
+ const directory_iterator end_itr = {};
+
+ if (State->HasNoPushRequest)
+ State->HasNoPushRequest = false;
+ else {
+ file_type type = State->Stack.top()->type();
+ if (type == file_type::symlink_file && Follow) {
+ // Resolve the symlink: is it a directory to recurse into?
+ ErrorOr<basic_file_status> status = State->Stack.top()->status();
+ if (status)
+ type = status->type();
+ // Otherwise broken symlink, and we'll continue.
+ }
+ if (type == file_type::directory_file) {
+ State->Stack.push(directory_iterator(*State->Stack.top(), ec, Follow));
+ if (State->Stack.top() != end_itr) {
+ ++State->Level;
+ return *this;
+ }
+ State->Stack.pop();
+ }
+ }
+
+ while (!State->Stack.empty()
+ && State->Stack.top().increment(ec) == end_itr) {
+ State->Stack.pop();
+ --State->Level;
+ }
+
+ // Check if we are done. If so, create an end iterator.
+ if (State->Stack.empty())
+ State.reset();
+
+ return *this;
+ }
+
+ const directory_entry &operator*() const { return *State->Stack.top(); }
+ const directory_entry *operator->() const { return &*State->Stack.top(); }
+
+ // observers
+ /// Gets the current level. Starting path is at level 0.
+ int level() const { return State->Level; }
+
+ /// Returns true if no_push has been called for this directory_entry.
+ bool no_push_request() const { return State->HasNoPushRequest; }
+
+ // modifiers
+ /// Goes up one level if Level > 0.
+ void pop() {
+ assert(State && "Cannot pop an end iterator!");
+ assert(State->Level > 0 && "Cannot pop an iterator with level < 1");
+
+ const directory_iterator end_itr = {};
+ std::error_code ec;
+ do {
+ if (ec)
+ report_fatal_error("Error incrementing directory iterator.");
+ State->Stack.pop();
+ --State->Level;
+ } while (!State->Stack.empty()
+ && State->Stack.top().increment(ec) == end_itr);
+
+ // Check if we are done. If so, create an end iterator.
+ if (State->Stack.empty())
+ State.reset();
+ }
+
+ /// Does not go down into the current directory_entry.
+ void no_push() { State->HasNoPushRequest = true; }
+
+ bool operator==(const recursive_directory_iterator &RHS) const {
+ return State == RHS.State;
+ }
+
+ bool operator!=(const recursive_directory_iterator &RHS) const {
+ return !(*this == RHS);
+ }
+};
+
+/// @}
+
+} // end namespace fs
+} // end namespace sys
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_FILESYSTEM_H
diff --git a/third_party/llvm-project/include/llvm/Support/Format.h b/third_party/llvm-project/include/llvm/Support/Format.h
new file mode 100644
index 000000000..9dd7b401b
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Format.h
@@ -0,0 +1,257 @@
+//===- Format.h - Efficient printf-style formatting for streams -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the format() function, which can be used with other
+// LLVM subsystems to provide printf-style formatting. This gives all the power
+// and risk of printf. This can be used like this (with raw_ostreams as an
+// example):
+//
+// OS << "mynumber: " << format("%4.5f", 1234.412) << '\n';
+//
+// Or if you prefer:
+//
+// OS << format("mynumber: %4.5f\n", 1234.412);
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FORMAT_H
+#define LLVM_SUPPORT_FORMAT_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <cstdio>
+#include <tuple>
+#include <utility>
+
+namespace llvm {
+
+/// This is a helper class used for handling formatted output. It is the
+/// abstract base class of a templated derived class.
+class format_object_base {
+protected:
+ const char *Fmt;
+ ~format_object_base() = default; // Disallow polymorphic deletion.
+ format_object_base(const format_object_base &) = default;
+ virtual void home(); // Out of line virtual method.
+
+ /// Call snprintf() for this object, on the given buffer and size.
+ virtual int snprint(char *Buffer, unsigned BufferSize) const = 0;
+
+public:
+ format_object_base(const char *fmt) : Fmt(fmt) {}
+
+ /// Format the object into the specified buffer. On success, this returns
+ /// the length of the formatted string. If the buffer is too small, this
+ /// returns a length to retry with, which will be larger than BufferSize.
+ unsigned print(char *Buffer, unsigned BufferSize) const {
+ assert(BufferSize && "Invalid buffer size!");
+
+ // Print the string, leaving room for the terminating null.
+ int N = snprint(Buffer, BufferSize);
+
+ // VC++ and old GlibC return negative on overflow, just double the size.
+ if (N < 0)
+ return BufferSize * 2;
+
+ // Other implementations yield number of bytes needed, not including the
+ // final '\0'.
+ if (unsigned(N) >= BufferSize)
+ return N + 1;
+
+ // Otherwise N is the length of output (not including the final '\0').
+ return N;
+ }
+};
+
+/// These are templated helper classes used by the format function that
+/// capture the object to be formatted and the format string. When actually
+/// printed, this synthesizes the string into a temporary buffer provided and
+/// returns whether or not it is big enough.
+
+// Helper to validate that format() parameters are scalars or pointers.
+template <typename... Args> struct validate_format_parameters;
+template <typename Arg, typename... Args>
+struct validate_format_parameters<Arg, Args...> {
+ static_assert(std::is_scalar<Arg>::value,
+ "format can't be used with non fundamental / non pointer type");
+ validate_format_parameters() { validate_format_parameters<Args...>(); }
+};
+template <> struct validate_format_parameters<> {};
+
+template <typename... Ts>
+class format_object final : public format_object_base {
+ std::tuple<Ts...> Vals;
+
+ template <std::size_t... Is>
+ int snprint_tuple(char *Buffer, unsigned BufferSize,
+ std::index_sequence<Is...>) const {
+#ifdef _MSC_VER
+ return _snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...);
+#else
+ return snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...);
+#endif
+ }
+
+public:
+ format_object(const char *fmt, const Ts &... vals)
+ : format_object_base(fmt), Vals(vals...) {
+ validate_format_parameters<Ts...>();
+ }
+
+ int snprint(char *Buffer, unsigned BufferSize) const override {
+ return snprint_tuple(Buffer, BufferSize, std::index_sequence_for<Ts...>());
+ }
+};
+
+/// These are helper functions used to produce formatted output. They use
+/// template type deduction to construct the appropriate instance of the
+/// format_object class to simplify their construction.
+///
+/// This is typically used like:
+/// \code
+/// OS << format("%0.4f", myfloat) << '\n';
+/// \endcode
+
+template <typename... Ts>
+inline format_object<Ts...> format(const char *Fmt, const Ts &... Vals) {
+ return format_object<Ts...>(Fmt, Vals...);
+}
+
+/// This is a helper class for left_justify, right_justify, and center_justify.
+class FormattedString {
+public:
+ enum Justification { JustifyNone, JustifyLeft, JustifyRight, JustifyCenter };
+ FormattedString(StringRef S, unsigned W, Justification J)
+ : Str(S), Width(W), Justify(J) {}
+
+private:
+ StringRef Str;
+ unsigned Width;
+ Justification Justify;
+ friend class raw_ostream;
+};
+
+/// left_justify - append spaces after string so total output is
+/// \p Width characters. If \p Str is larger that \p Width, full string
+/// is written with no padding.
+inline FormattedString left_justify(StringRef Str, unsigned Width) {
+ return FormattedString(Str, Width, FormattedString::JustifyLeft);
+}
+
+/// right_justify - add spaces before string so total output is
+/// \p Width characters. If \p Str is larger that \p Width, full string
+/// is written with no padding.
+inline FormattedString right_justify(StringRef Str, unsigned Width) {
+ return FormattedString(Str, Width, FormattedString::JustifyRight);
+}
+
+/// center_justify - add spaces before and after string so total output is
+/// \p Width characters. If \p Str is larger that \p Width, full string
+/// is written with no padding.
+inline FormattedString center_justify(StringRef Str, unsigned Width) {
+ return FormattedString(Str, Width, FormattedString::JustifyCenter);
+}
+
+/// This is a helper class used for format_hex() and format_decimal().
+class FormattedNumber {
+ uint64_t HexValue;
+ int64_t DecValue;
+ unsigned Width;
+ bool Hex;
+ bool Upper;
+ bool HexPrefix;
+ friend class raw_ostream;
+
+public:
+ FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U,
+ bool Prefix)
+ : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U),
+ HexPrefix(Prefix) {}
+};
+
+/// format_hex - Output \p N as a fixed width hexadecimal. If number will not
+/// fit in width, full number is still printed. Examples:
+/// OS << format_hex(255, 4) => 0xff
+/// OS << format_hex(255, 4, true) => 0xFF
+/// OS << format_hex(255, 6) => 0x00ff
+/// OS << format_hex(255, 2) => 0xff
+inline FormattedNumber format_hex(uint64_t N, unsigned Width,
+ bool Upper = false) {
+ assert(Width <= 18 && "hex width must be <= 18");
+ return FormattedNumber(N, 0, Width, true, Upper, true);
+}
+
+/// format_hex_no_prefix - Output \p N as a fixed width hexadecimal. Does not
+/// prepend '0x' to the outputted string. If number will not fit in width,
+/// full number is still printed. Examples:
+/// OS << format_hex_no_prefix(255, 2) => ff
+/// OS << format_hex_no_prefix(255, 2, true) => FF
+/// OS << format_hex_no_prefix(255, 4) => 00ff
+/// OS << format_hex_no_prefix(255, 1) => ff
+inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width,
+ bool Upper = false) {
+ assert(Width <= 16 && "hex width must be <= 16");
+ return FormattedNumber(N, 0, Width, true, Upper, false);
+}
+
+/// format_decimal - Output \p N as a right justified, fixed-width decimal. If
+/// number will not fit in width, full number is still printed. Examples:
+/// OS << format_decimal(0, 5) => " 0"
+/// OS << format_decimal(255, 5) => " 255"
+/// OS << format_decimal(-1, 3) => " -1"
+/// OS << format_decimal(12345, 3) => "12345"
+inline FormattedNumber format_decimal(int64_t N, unsigned Width) {
+ return FormattedNumber(0, N, Width, false, false, false);
+}
+
+class FormattedBytes {
+ ArrayRef<uint8_t> Bytes;
+
+ // If not None, display offsets for each line relative to starting value.
+ Optional<uint64_t> FirstByteOffset;
+ uint32_t IndentLevel; // Number of characters to indent each line.
+ uint32_t NumPerLine; // Number of bytes to show per line.
+ uint8_t ByteGroupSize; // How many hex bytes are grouped without spaces
+ bool Upper; // Show offset and hex bytes as upper case.
+ bool ASCII; // Show the ASCII bytes for the hex bytes to the right.
+ friend class raw_ostream;
+
+public:
+ FormattedBytes(ArrayRef<uint8_t> B, uint32_t IL, Optional<uint64_t> O,
+ uint32_t NPL, uint8_t BGS, bool U, bool A)
+ : Bytes(B), FirstByteOffset(O), IndentLevel(IL), NumPerLine(NPL),
+ ByteGroupSize(BGS), Upper(U), ASCII(A) {
+
+ if (ByteGroupSize > NumPerLine)
+ ByteGroupSize = NumPerLine;
+ }
+};
+
+inline FormattedBytes
+format_bytes(ArrayRef<uint8_t> Bytes, Optional<uint64_t> FirstByteOffset = None,
+ uint32_t NumPerLine = 16, uint8_t ByteGroupSize = 4,
+ uint32_t IndentLevel = 0, bool Upper = false) {
+ return FormattedBytes(Bytes, IndentLevel, FirstByteOffset, NumPerLine,
+ ByteGroupSize, Upper, false);
+}
+
+inline FormattedBytes
+format_bytes_with_ascii(ArrayRef<uint8_t> Bytes,
+ Optional<uint64_t> FirstByteOffset = None,
+ uint32_t NumPerLine = 16, uint8_t ByteGroupSize = 4,
+ uint32_t IndentLevel = 0, bool Upper = false) {
+ return FormattedBytes(Bytes, IndentLevel, FirstByteOffset, NumPerLine,
+ ByteGroupSize, Upper, true);
+}
+
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/FormatAdapters.h b/third_party/llvm-project/include/llvm/Support/FormatAdapters.h
new file mode 100644
index 000000000..a0e8cc439
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/FormatAdapters.h
@@ -0,0 +1,108 @@
+//===- FormatAdapters.h - Formatters for common LLVM types -----*- 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_FORMATADAPTERS_H
+#define LLVM_SUPPORT_FORMATADAPTERS_H
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatCommon.h"
+#include "llvm/Support/FormatVariadicDetails.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+template <typename T> class FormatAdapter : public detail::format_adapter {
+protected:
+ explicit FormatAdapter(T &&Item) : Item(std::forward<T>(Item)) {}
+
+ T Item;
+};
+
+namespace detail {
+template <typename T> class AlignAdapter final : public FormatAdapter<T> {
+ AlignStyle Where;
+ size_t Amount;
+ char Fill;
+
+public:
+ AlignAdapter(T &&Item, AlignStyle Where, size_t Amount, char Fill)
+ : FormatAdapter<T>(std::forward<T>(Item)), Where(Where), Amount(Amount),
+ Fill(Fill) {}
+
+ void format(llvm::raw_ostream &Stream, StringRef Style) {
+ auto Adapter = detail::build_format_adapter(std::forward<T>(this->Item));
+ FmtAlign(Adapter, Where, Amount, Fill).format(Stream, Style);
+ }
+};
+
+template <typename T> class PadAdapter final : public FormatAdapter<T> {
+ size_t Left;
+ size_t Right;
+
+public:
+ PadAdapter(T &&Item, size_t Left, size_t Right)
+ : FormatAdapter<T>(std::forward<T>(Item)), Left(Left), Right(Right) {}
+
+ void format(llvm::raw_ostream &Stream, StringRef Style) {
+ auto Adapter = detail::build_format_adapter(std::forward<T>(this->Item));
+ Stream.indent(Left);
+ Adapter.format(Stream, Style);
+ Stream.indent(Right);
+ }
+};
+
+template <typename T> class RepeatAdapter final : public FormatAdapter<T> {
+ size_t Count;
+
+public:
+ RepeatAdapter(T &&Item, size_t Count)
+ : FormatAdapter<T>(std::forward<T>(Item)), Count(Count) {}
+
+ void format(llvm::raw_ostream &Stream, StringRef Style) {
+ auto Adapter = detail::build_format_adapter(std::forward<T>(this->Item));
+ for (size_t I = 0; I < Count; ++I) {
+ Adapter.format(Stream, Style);
+ }
+ }
+};
+
+class ErrorAdapter : public FormatAdapter<Error> {
+public:
+ ErrorAdapter(Error &&Item) : FormatAdapter(std::move(Item)) {}
+ ErrorAdapter(ErrorAdapter &&) = default;
+ ~ErrorAdapter() { consumeError(std::move(Item)); }
+ void format(llvm::raw_ostream &Stream, StringRef Style) { Stream << Item; }
+};
+}
+
+template <typename T>
+detail::AlignAdapter<T> fmt_align(T &&Item, AlignStyle Where, size_t Amount,
+ char Fill = ' ') {
+ return detail::AlignAdapter<T>(std::forward<T>(Item), Where, Amount, Fill);
+}
+
+template <typename T>
+detail::PadAdapter<T> fmt_pad(T &&Item, size_t Left, size_t Right) {
+ return detail::PadAdapter<T>(std::forward<T>(Item), Left, Right);
+}
+
+template <typename T>
+detail::RepeatAdapter<T> fmt_repeat(T &&Item, size_t Count) {
+ return detail::RepeatAdapter<T>(std::forward<T>(Item), Count);
+}
+
+// llvm::Error values must be consumed before being destroyed.
+// Wrapping an error in fmt_consume explicitly indicates that the formatv_object
+// should take ownership and consume it.
+inline detail::ErrorAdapter fmt_consume(Error &&Item) {
+ return detail::ErrorAdapter(std::move(Item));
+}
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/FormatCommon.h b/third_party/llvm-project/include/llvm/Support/FormatCommon.h
new file mode 100644
index 000000000..3c119d125
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/FormatCommon.h
@@ -0,0 +1,76 @@
+//===- FormatCommon.h - Formatters for common LLVM types --------*- 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_FORMATCOMMON_H
+#define LLVM_SUPPORT_FORMATCOMMON_H
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FormatVariadicDetails.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+enum class AlignStyle { Left, Center, Right };
+
+struct FmtAlign {
+ detail::format_adapter &Adapter;
+ AlignStyle Where;
+ size_t Amount;
+ char Fill;
+
+ FmtAlign(detail::format_adapter &Adapter, AlignStyle Where, size_t Amount,
+ char Fill = ' ')
+ : Adapter(Adapter), Where(Where), Amount(Amount), Fill(Fill) {}
+
+ void format(raw_ostream &S, StringRef Options) {
+ // If we don't need to align, we can format straight into the underlying
+ // stream. Otherwise we have to go through an intermediate stream first
+ // in order to calculate how long the output is so we can align it.
+ // TODO: Make the format method return the number of bytes written, that
+ // way we can also skip the intermediate stream for left-aligned output.
+ if (Amount == 0) {
+ Adapter.format(S, Options);
+ return;
+ }
+ SmallString<64> Item;
+ raw_svector_ostream Stream(Item);
+
+ Adapter.format(Stream, Options);
+ if (Amount <= Item.size()) {
+ S << Item;
+ return;
+ }
+
+ size_t PadAmount = Amount - Item.size();
+ switch (Where) {
+ case AlignStyle::Left:
+ S << Item;
+ fill(S, PadAmount);
+ break;
+ case AlignStyle::Center: {
+ size_t X = PadAmount / 2;
+ fill(S, X);
+ S << Item;
+ fill(S, PadAmount - X);
+ break;
+ }
+ default:
+ fill(S, PadAmount);
+ S << Item;
+ break;
+ }
+ }
+
+private:
+ void fill(llvm::raw_ostream &S, uint32_t Count) {
+ for (uint32_t I = 0; I < Count; ++I)
+ S << Fill;
+ }
+};
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/FormatProviders.h b/third_party/llvm-project/include/llvm/Support/FormatProviders.h
new file mode 100644
index 000000000..629a48457
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/FormatProviders.h
@@ -0,0 +1,422 @@
+//===- FormatProviders.h - Formatters for common LLVM types -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements format providers for many common LLVM types, for example
+// allowing precision and width specifiers for scalar and string types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FORMATPROVIDERS_H
+#define LLVM_SUPPORT_FORMATPROVIDERS_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/FormatVariadicDetails.h"
+#include "llvm/Support/NativeFormatting.h"
+
+#include <type_traits>
+#include <vector>
+
+namespace llvm {
+namespace detail {
+template <typename T>
+struct use_integral_formatter
+ : public std::integral_constant<
+ bool, is_one_of<T, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
+ int64_t, uint64_t, int, unsigned, long, unsigned long,
+ long long, unsigned long long>::value> {};
+
+template <typename T>
+struct use_char_formatter
+ : public std::integral_constant<bool, std::is_same<T, char>::value> {};
+
+template <typename T>
+struct is_cstring
+ : public std::integral_constant<bool,
+ is_one_of<T, char *, const char *>::value> {
+};
+
+template <typename T>
+struct use_string_formatter
+ : public std::integral_constant<bool,
+ std::is_convertible<T, llvm::StringRef>::value> {};
+
+template <typename T>
+struct use_pointer_formatter
+ : public std::integral_constant<bool, std::is_pointer<T>::value &&
+ !is_cstring<T>::value> {};
+
+template <typename T>
+struct use_double_formatter
+ : public std::integral_constant<bool, std::is_floating_point<T>::value> {};
+
+class HelperFunctions {
+protected:
+ static Optional<size_t> parseNumericPrecision(StringRef Str) {
+ size_t Prec;
+ Optional<size_t> Result;
+ if (Str.empty())
+ Result = None;
+ else if (Str.getAsInteger(10, Prec)) {
+ assert(false && "Invalid precision specifier");
+ Result = None;
+ } else {
+ assert(Prec < 100 && "Precision out of range");
+ Result = std::min<size_t>(99u, Prec);
+ }
+ return Result;
+ }
+
+ static bool consumeHexStyle(StringRef &Str, HexPrintStyle &Style) {
+ if (!Str.startswith_lower("x"))
+ return false;
+
+ if (Str.consume_front("x-"))
+ Style = HexPrintStyle::Lower;
+ else if (Str.consume_front("X-"))
+ Style = HexPrintStyle::Upper;
+ else if (Str.consume_front("x+") || Str.consume_front("x"))
+ Style = HexPrintStyle::PrefixLower;
+ else if (Str.consume_front("X+") || Str.consume_front("X"))
+ Style = HexPrintStyle::PrefixUpper;
+ return true;
+ }
+
+ static size_t consumeNumHexDigits(StringRef &Str, HexPrintStyle Style,
+ size_t Default) {
+ Str.consumeInteger(10, Default);
+ if (isPrefixedHexStyle(Style))
+ Default += 2;
+ return Default;
+ }
+};
+}
+
+/// Implementation of format_provider<T> for integral arithmetic types.
+///
+/// The options string of an integral type has the grammar:
+///
+/// integer_options :: [style][digits]
+/// style :: <see table below>
+/// digits :: <non-negative integer> 0-99
+///
+/// ==========================================================================
+/// | style | Meaning | Example | Digits Meaning |
+/// --------------------------------------------------------------------------
+/// | | | Input | Output | |
+/// ==========================================================================
+/// | x- | Hex no prefix, lower | 42 | 2a | Minimum # digits |
+/// | X- | Hex no prefix, upper | 42 | 2A | Minimum # digits |
+/// | x+ / x | Hex + prefix, lower | 42 | 0x2a | Minimum # digits |
+/// | X+ / X | Hex + prefix, upper | 42 | 0x2A | Minimum # digits |
+/// | N / n | Digit grouped number | 123456 | 123,456 | Ignored |
+/// | D / d | Integer | 100000 | 100000 | Ignored |
+/// | (empty) | Same as D / d | | | |
+/// ==========================================================================
+///
+
+template <typename T>
+struct format_provider<
+ T, typename std::enable_if<detail::use_integral_formatter<T>::value>::type>
+ : public detail::HelperFunctions {
+private:
+public:
+ static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
+ HexPrintStyle HS;
+ size_t Digits = 0;
+ if (consumeHexStyle(Style, HS)) {
+ Digits = consumeNumHexDigits(Style, HS, 0);
+ write_hex(Stream, V, HS, Digits);
+ return;
+ }
+
+ IntegerStyle IS = IntegerStyle::Integer;
+ if (Style.consume_front("N") || Style.consume_front("n"))
+ IS = IntegerStyle::Number;
+ else if (Style.consume_front("D") || Style.consume_front("d"))
+ IS = IntegerStyle::Integer;
+
+ Style.consumeInteger(10, Digits);
+ assert(Style.empty() && "Invalid integral format style!");
+ write_integer(Stream, V, Digits, IS);
+ }
+};
+
+/// Implementation of format_provider<T> for integral pointer types.
+///
+/// The options string of a pointer type has the grammar:
+///
+/// pointer_options :: [style][precision]
+/// style :: <see table below>
+/// digits :: <non-negative integer> 0-sizeof(void*)
+///
+/// ==========================================================================
+/// | S | Meaning | Example |
+/// --------------------------------------------------------------------------
+/// | | | Input | Output |
+/// ==========================================================================
+/// | x- | Hex no prefix, lower | 0xDEADBEEF | deadbeef |
+/// | X- | Hex no prefix, upper | 0xDEADBEEF | DEADBEEF |
+/// | x+ / x | Hex + prefix, lower | 0xDEADBEEF | 0xdeadbeef |
+/// | X+ / X | Hex + prefix, upper | 0xDEADBEEF | 0xDEADBEEF |
+/// | (empty) | Same as X+ / X | | |
+/// ==========================================================================
+///
+/// The default precision is the number of nibbles in a machine word, and in all
+/// cases indicates the minimum number of nibbles to print.
+template <typename T>
+struct format_provider<
+ T, typename std::enable_if<detail::use_pointer_formatter<T>::value>::type>
+ : public detail::HelperFunctions {
+private:
+public:
+ static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
+ HexPrintStyle HS = HexPrintStyle::PrefixUpper;
+ consumeHexStyle(Style, HS);
+ size_t Digits = consumeNumHexDigits(Style, HS, sizeof(void *) * 2);
+ write_hex(Stream, reinterpret_cast<std::uintptr_t>(V), HS, Digits);
+ }
+};
+
+/// Implementation of format_provider<T> for c-style strings and string
+/// objects such as std::string and llvm::StringRef.
+///
+/// The options string of a string type has the grammar:
+///
+/// string_options :: [length]
+///
+/// where `length` is an optional integer specifying the maximum number of
+/// characters in the string to print. If `length` is omitted, the string is
+/// printed up to the null terminator.
+
+template <typename T>
+struct format_provider<
+ T, typename std::enable_if<detail::use_string_formatter<T>::value>::type> {
+ static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
+ size_t N = StringRef::npos;
+ if (!Style.empty() && Style.getAsInteger(10, N)) {
+ assert(false && "Style is not a valid integer");
+ }
+ llvm::StringRef S = V;
+ Stream << S.substr(0, N);
+ }
+};
+
+/// Implementation of format_provider<T> for llvm::Twine.
+///
+/// This follows the same rules as the string formatter.
+
+template <> struct format_provider<Twine> {
+ static void format(const Twine &V, llvm::raw_ostream &Stream,
+ StringRef Style) {
+ format_provider<std::string>::format(V.str(), Stream, Style);
+ }
+};
+
+/// Implementation of format_provider<T> for characters.
+///
+/// The options string of a character type has the grammar:
+///
+/// char_options :: (empty) | [integer_options]
+///
+/// If `char_options` is empty, the character is displayed as an ASCII
+/// character. Otherwise, it is treated as an integer options string.
+///
+template <typename T>
+struct format_provider<
+ T, typename std::enable_if<detail::use_char_formatter<T>::value>::type> {
+ static void format(const char &V, llvm::raw_ostream &Stream,
+ StringRef Style) {
+ if (Style.empty())
+ Stream << V;
+ else {
+ int X = static_cast<int>(V);
+ format_provider<int>::format(X, Stream, Style);
+ }
+ }
+};
+
+/// Implementation of format_provider<T> for type `bool`
+///
+/// The options string of a boolean type has the grammar:
+///
+/// bool_options :: "" | "Y" | "y" | "D" | "d" | "T" | "t"
+///
+/// ==================================
+/// | C | Meaning |
+/// ==================================
+/// | Y | YES / NO |
+/// | y | yes / no |
+/// | D / d | Integer 0 or 1 |
+/// | T | TRUE / FALSE |
+/// | t | true / false |
+/// | (empty) | Equivalent to 't' |
+/// ==================================
+template <> struct format_provider<bool> {
+ static void format(const bool &B, llvm::raw_ostream &Stream,
+ StringRef Style) {
+ Stream << StringSwitch<const char *>(Style)
+ .Case("Y", B ? "YES" : "NO")
+ .Case("y", B ? "yes" : "no")
+ .CaseLower("D", B ? "1" : "0")
+ .Case("T", B ? "TRUE" : "FALSE")
+ .Cases("t", "", B ? "true" : "false")
+ .Default(B ? "1" : "0");
+ }
+};
+
+/// Implementation of format_provider<T> for floating point types.
+///
+/// The options string of a floating point type has the format:
+///
+/// float_options :: [style][precision]
+/// style :: <see table below>
+/// precision :: <non-negative integer> 0-99
+///
+/// =====================================================
+/// | style | Meaning | Example |
+/// -----------------------------------------------------
+/// | | | Input | Output |
+/// =====================================================
+/// | P / p | Percentage | 0.05 | 5.00% |
+/// | F / f | Fixed point | 1.0 | 1.00 |
+/// | E | Exponential with E | 100000 | 1.0E+05 |
+/// | e | Exponential with e | 100000 | 1.0e+05 |
+/// | (empty) | Same as F / f | | |
+/// =====================================================
+///
+/// The default precision is 6 for exponential (E / e) and 2 for everything
+/// else.
+
+template <typename T>
+struct format_provider<
+ T, typename std::enable_if<detail::use_double_formatter<T>::value>::type>
+ : public detail::HelperFunctions {
+ static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
+ FloatStyle S;
+ if (Style.consume_front("P") || Style.consume_front("p"))
+ S = FloatStyle::Percent;
+ else if (Style.consume_front("F") || Style.consume_front("f"))
+ S = FloatStyle::Fixed;
+ else if (Style.consume_front("E"))
+ S = FloatStyle::ExponentUpper;
+ else if (Style.consume_front("e"))
+ S = FloatStyle::Exponent;
+ else
+ S = FloatStyle::Fixed;
+
+ Optional<size_t> Precision = parseNumericPrecision(Style);
+ if (!Precision.hasValue())
+ Precision = getDefaultPrecision(S);
+
+ write_double(Stream, static_cast<double>(V), S, Precision);
+ }
+};
+
+namespace detail {
+template <typename IterT>
+using IterValue = typename std::iterator_traits<IterT>::value_type;
+
+template <typename IterT>
+struct range_item_has_provider
+ : public std::integral_constant<
+ bool, !uses_missing_provider<IterValue<IterT>>::value> {};
+}
+
+/// Implementation of format_provider<T> for ranges.
+///
+/// This will print an arbitrary range as a delimited sequence of items.
+///
+/// The options string of a range type has the grammar:
+///
+/// range_style ::= [separator] [element_style]
+/// separator ::= "$" delimeted_expr
+/// element_style ::= "@" delimeted_expr
+/// delimeted_expr ::= "[" expr "]" | "(" expr ")" | "<" expr ">"
+/// expr ::= <any string not containing delimeter>
+///
+/// where the separator expression is the string to insert between consecutive
+/// items in the range and the argument expression is the Style specification to
+/// be used when formatting the underlying type. The default separator if
+/// unspecified is ' ' (space). The syntax of the argument expression follows
+/// whatever grammar is dictated by the format provider or format adapter used
+/// to format the value type.
+///
+/// Note that attempting to format an `iterator_range<T>` where no format
+/// provider can be found for T will result in a compile error.
+///
+
+template <typename IterT> class format_provider<llvm::iterator_range<IterT>> {
+ using value = typename std::iterator_traits<IterT>::value_type;
+ using reference = typename std::iterator_traits<IterT>::reference;
+
+ static StringRef consumeOneOption(StringRef &Style, char Indicator,
+ StringRef Default) {
+ if (Style.empty())
+ return Default;
+ if (Style.front() != Indicator)
+ return Default;
+ Style = Style.drop_front();
+ if (Style.empty()) {
+ assert(false && "Invalid range style");
+ return Default;
+ }
+
+ for (const char *D : {"[]", "<>", "()"}) {
+ if (Style.front() != D[0])
+ continue;
+ size_t End = Style.find_first_of(D[1]);
+ if (End == StringRef::npos) {
+ assert(false && "Missing range option end delimeter!");
+ return Default;
+ }
+ StringRef Result = Style.slice(1, End);
+ Style = Style.drop_front(End + 1);
+ return Result;
+ }
+ assert(false && "Invalid range style!");
+ return Default;
+ }
+
+ static std::pair<StringRef, StringRef> parseOptions(StringRef Style) {
+ StringRef Sep = consumeOneOption(Style, '$', ", ");
+ StringRef Args = consumeOneOption(Style, '@', "");
+ assert(Style.empty() && "Unexpected text in range option string!");
+ return std::make_pair(Sep, Args);
+ }
+
+public:
+ static_assert(detail::range_item_has_provider<IterT>::value,
+ "Range value_type does not have a format provider!");
+ static void format(const llvm::iterator_range<IterT> &V,
+ llvm::raw_ostream &Stream, StringRef Style) {
+ StringRef Sep;
+ StringRef ArgStyle;
+ std::tie(Sep, ArgStyle) = parseOptions(Style);
+ auto Begin = V.begin();
+ auto End = V.end();
+ if (Begin != End) {
+ auto Adapter =
+ detail::build_format_adapter(std::forward<reference>(*Begin));
+ Adapter.format(Stream, ArgStyle);
+ ++Begin;
+ }
+ while (Begin != End) {
+ Stream << Sep;
+ auto Adapter =
+ detail::build_format_adapter(std::forward<reference>(*Begin));
+ Adapter.format(Stream, ArgStyle);
+ ++Begin;
+ }
+ }
+};
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/FormatVariadic.h b/third_party/llvm-project/include/llvm/Support/FormatVariadic.h
new file mode 100644
index 000000000..86a9d30cc
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/FormatVariadic.h
@@ -0,0 +1,264 @@
+//===- FormatVariadic.h - Efficient type-safe string formatting --*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the formatv() function which can be used with other LLVM
+// subsystems to provide printf-like formatting, but with improved safety and
+// flexibility. The result of `formatv` is an object which can be streamed to
+// a raw_ostream or converted to a std::string or llvm::SmallString.
+//
+// // Convert to std::string.
+// std::string S = formatv("{0} {1}", 1234.412, "test").str();
+//
+// // Convert to llvm::SmallString
+// SmallString<8> S = formatv("{0} {1}", 1234.412, "test").sstr<8>();
+//
+// // Stream to an existing raw_ostream.
+// OS << formatv("{0} {1}", 1234.412, "test");
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FORMATVARIADIC_H
+#define LLVM_SUPPORT_FORMATVARIADIC_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FormatCommon.h"
+#include "llvm/Support/FormatProviders.h"
+#include "llvm/Support/FormatVariadicDetails.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstddef>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+enum class ReplacementType { Empty, Format, Literal };
+
+struct ReplacementItem {
+ ReplacementItem() = default;
+ explicit ReplacementItem(StringRef Literal)
+ : Type(ReplacementType::Literal), Spec(Literal) {}
+ ReplacementItem(StringRef Spec, size_t Index, size_t Align, AlignStyle Where,
+ char Pad, StringRef Options)
+ : Type(ReplacementType::Format), Spec(Spec), Index(Index), Align(Align),
+ Where(Where), Pad(Pad), Options(Options) {}
+
+ ReplacementType Type = ReplacementType::Empty;
+ StringRef Spec;
+ size_t Index = 0;
+ size_t Align = 0;
+ AlignStyle Where = AlignStyle::Right;
+ char Pad = 0;
+ StringRef Options;
+};
+
+class formatv_object_base {
+protected:
+ // The parameters are stored in a std::tuple, which does not provide runtime
+ // indexing capabilities. In order to enable runtime indexing, we use this
+ // structure to put the parameters into a std::vector. Since the parameters
+ // are not all the same type, we use some type-erasure by wrapping the
+ // parameters in a template class that derives from a non-template superclass.
+ // Essentially, we are converting a std::tuple<Derived<Ts...>> to a
+ // std::vector<Base*>.
+ struct create_adapters {
+ template <typename... Ts>
+ std::vector<detail::format_adapter *> operator()(Ts &... Items) {
+ return std::vector<detail::format_adapter *>{&Items...};
+ }
+ };
+
+ StringRef Fmt;
+ std::vector<detail::format_adapter *> Adapters;
+ std::vector<ReplacementItem> Replacements;
+
+ static bool consumeFieldLayout(StringRef &Spec, AlignStyle &Where,
+ size_t &Align, char &Pad);
+
+ static std::pair<ReplacementItem, StringRef>
+ splitLiteralAndReplacement(StringRef Fmt);
+
+public:
+ formatv_object_base(StringRef Fmt, std::size_t ParamCount)
+ : Fmt(Fmt), Replacements(parseFormatString(Fmt)) {
+ Adapters.reserve(ParamCount);
+ }
+
+ formatv_object_base(formatv_object_base const &rhs) = delete;
+
+ formatv_object_base(formatv_object_base &&rhs)
+ : Fmt(std::move(rhs.Fmt)),
+ Adapters(), // Adapters are initialized by formatv_object
+ Replacements(std::move(rhs.Replacements)) {
+ Adapters.reserve(rhs.Adapters.size());
+ };
+
+ void format(raw_ostream &S) const {
+ for (auto &R : Replacements) {
+ if (R.Type == ReplacementType::Empty)
+ continue;
+ if (R.Type == ReplacementType::Literal) {
+ S << R.Spec;
+ continue;
+ }
+ if (R.Index >= Adapters.size()) {
+ S << R.Spec;
+ continue;
+ }
+
+ auto W = Adapters[R.Index];
+
+ FmtAlign Align(*W, R.Where, R.Align, R.Pad);
+ Align.format(S, R.Options);
+ }
+ }
+ static std::vector<ReplacementItem> parseFormatString(StringRef Fmt);
+
+ static Optional<ReplacementItem> parseReplacementItem(StringRef Spec);
+
+ std::string str() const {
+ std::string Result;
+ raw_string_ostream Stream(Result);
+ Stream << *this;
+ Stream.flush();
+ return Result;
+ }
+
+ template <unsigned N> SmallString<N> sstr() const {
+ SmallString<N> Result;
+ raw_svector_ostream Stream(Result);
+ Stream << *this;
+ return Result;
+ }
+
+ template <unsigned N> operator SmallString<N>() const { return sstr<N>(); }
+
+ operator std::string() const { return str(); }
+};
+
+template <typename Tuple> class formatv_object : public formatv_object_base {
+ // Storage for the parameter adapters. Since the base class erases the type
+ // of the parameters, we have to own the storage for the parameters here, and
+ // have the base class store type-erased pointers into this tuple.
+ Tuple Parameters;
+
+public:
+ formatv_object(StringRef Fmt, Tuple &&Params)
+ : formatv_object_base(Fmt, std::tuple_size<Tuple>::value),
+ Parameters(std::move(Params)) {
+ Adapters = apply_tuple(create_adapters(), Parameters);
+ }
+
+ formatv_object(formatv_object const &rhs) = delete;
+
+ formatv_object(formatv_object &&rhs)
+ : formatv_object_base(std::move(rhs)),
+ Parameters(std::move(rhs.Parameters)) {
+ Adapters = apply_tuple(create_adapters(), Parameters);
+ }
+};
+
+// Format text given a format string and replacement parameters.
+//
+// ===General Description===
+//
+// Formats textual output. `Fmt` is a string consisting of one or more
+// replacement sequences with the following grammar:
+//
+// rep_field ::= "{" [index] ["," layout] [":" format] "}"
+// index ::= <non-negative integer>
+// layout ::= [[[char]loc]width]
+// format ::= <any string not containing "{" or "}">
+// char ::= <any character except "{" or "}">
+// loc ::= "-" | "=" | "+"
+// width ::= <positive integer>
+//
+// index - A non-negative integer specifying the index of the item in the
+// parameter pack to print. Any other value is invalid.
+// layout - A string controlling how the field is laid out within the available
+// space.
+// format - A type-dependent string used to provide additional options to
+// the formatting operation. Refer to the documentation of the
+// various individual format providers for per-type options.
+// char - The padding character. Defaults to ' ' (space). Only valid if
+// `loc` is also specified.
+// loc - Where to print the formatted text within the field. Only valid if
+// `width` is also specified.
+// '-' : The field is left aligned within the available space.
+// '=' : The field is centered within the available space.
+// '+' : The field is right aligned within the available space (this
+// is the default).
+// width - The width of the field within which to print the formatted text.
+// If this is less than the required length then the `char` and `loc`
+// fields are ignored, and the field is printed with no leading or
+// trailing padding. If this is greater than the required length,
+// then the text is output according to the value of `loc`, and padded
+// as appropriate on the left and/or right by `char`.
+//
+// ===Special Characters===
+//
+// The characters '{' and '}' are reserved and cannot appear anywhere within a
+// replacement sequence. Outside of a replacement sequence, in order to print
+// a literal '{' or '}' it must be doubled -- "{{" to print a literal '{' and
+// "}}" to print a literal '}'.
+//
+// ===Parameter Indexing===
+// `index` specifies the index of the parameter in the parameter pack to format
+// into the output. Note that it is possible to refer to the same parameter
+// index multiple times in a given format string. This makes it possible to
+// output the same value multiple times without passing it multiple times to the
+// function. For example:
+//
+// formatv("{0} {1} {0}", "a", "bb")
+//
+// would yield the string "abba". This can be convenient when it is expensive
+// to compute the value of the parameter, and you would otherwise have had to
+// save it to a temporary.
+//
+// ===Formatter Search===
+//
+// For a given parameter of type T, the following steps are executed in order
+// until a match is found:
+//
+// 1. If the parameter is of class type, and inherits from format_adapter,
+// Then format() is invoked on it to produce the formatted output. The
+// implementation should write the formatted text into `Stream`.
+// 2. If there is a suitable template specialization of format_provider<>
+// for type T containing a method whose signature is:
+// void format(const T &Obj, raw_ostream &Stream, StringRef Options)
+// Then this method is invoked as described in Step 1.
+// 3. If an appropriate operator<< for raw_ostream exists, it will be used.
+// For this to work, (raw_ostream& << const T&) must return raw_ostream&.
+//
+// If a match cannot be found through either of the above methods, a compiler
+// error is generated.
+//
+// ===Invalid Format String Handling===
+//
+// In the case of a format string which does not match the grammar described
+// above, the output is undefined. With asserts enabled, LLVM will trigger an
+// assertion. Otherwise, it will try to do something reasonable, but in general
+// the details of what that is are undefined.
+//
+template <typename... Ts>
+inline auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object<decltype(
+ std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...))> {
+ using ParamTuple = decltype(
+ std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
+ return formatv_object<ParamTuple>(
+ Fmt,
+ std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...));
+}
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_FORMATVARIADIC_H
diff --git a/third_party/llvm-project/include/llvm/Support/FormatVariadicDetails.h b/third_party/llvm-project/include/llvm/Support/FormatVariadicDetails.h
new file mode 100644
index 000000000..e3c185134
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/FormatVariadicDetails.h
@@ -0,0 +1,164 @@
+//===- FormatVariadicDetails.h - Helpers for FormatVariadic.h ----*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H
+#define LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <type_traits>
+
+namespace llvm {
+template <typename T, typename Enable = void> struct format_provider {};
+class Error;
+
+namespace detail {
+class format_adapter {
+ virtual void anchor();
+
+protected:
+ virtual ~format_adapter() {}
+
+public:
+ virtual void format(raw_ostream &S, StringRef Options) = 0;
+};
+
+template <typename T> class provider_format_adapter : public format_adapter {
+ T Item;
+
+public:
+ explicit provider_format_adapter(T &&Item) : Item(std::forward<T>(Item)) {}
+
+ void format(llvm::raw_ostream &S, StringRef Options) override {
+ format_provider<typename std::decay<T>::type>::format(Item, S, Options);
+ }
+};
+
+template <typename T>
+class stream_operator_format_adapter : public format_adapter {
+ T Item;
+
+public:
+ explicit stream_operator_format_adapter(T &&Item)
+ : Item(std::forward<T>(Item)) {}
+
+ void format(llvm::raw_ostream &S, StringRef Options) override { S << Item; }
+};
+
+template <typename T> class missing_format_adapter;
+
+// Test if format_provider<T> is defined on T and contains a member function
+// with the signature:
+// static void format(const T&, raw_stream &, StringRef);
+//
+template <class T> class has_FormatProvider {
+public:
+ using Decayed = typename std::decay<T>::type;
+ typedef void (*Signature_format)(const Decayed &, llvm::raw_ostream &,
+ StringRef);
+
+ template <typename U>
+ static char test(SameType<Signature_format, &U::format> *);
+
+ template <typename U> static double test(...);
+
+ static bool const value =
+ (sizeof(test<llvm::format_provider<Decayed>>(nullptr)) == 1);
+};
+
+// Test if raw_ostream& << T -> raw_ostream& is findable via ADL.
+template <class T> class has_StreamOperator {
+public:
+ using ConstRefT = const typename std::decay<T>::type &;
+
+ template <typename U>
+ static char test(typename std::enable_if<
+ std::is_same<decltype(std::declval<llvm::raw_ostream &>()
+ << std::declval<U>()),
+ llvm::raw_ostream &>::value,
+ int *>::type);
+
+ template <typename U> static double test(...);
+
+ static bool const value = (sizeof(test<ConstRefT>(nullptr)) == 1);
+};
+
+// Simple template that decides whether a type T should use the member-function
+// based format() invocation.
+template <typename T>
+struct uses_format_member
+ : public std::integral_constant<
+ bool,
+ std::is_base_of<format_adapter,
+ typename std::remove_reference<T>::type>::value> {};
+
+// Simple template that decides whether a type T should use the format_provider
+// based format() invocation. The member function takes priority, so this test
+// will only be true if there is not ALSO a format member.
+template <typename T>
+struct uses_format_provider
+ : public std::integral_constant<
+ bool, !uses_format_member<T>::value && has_FormatProvider<T>::value> {
+};
+
+// Simple template that decides whether a type T should use the operator<<
+// based format() invocation. This takes last priority.
+template <typename T>
+struct uses_stream_operator
+ : public std::integral_constant<bool, !uses_format_member<T>::value &&
+ !uses_format_provider<T>::value &&
+ has_StreamOperator<T>::value> {};
+
+// Simple template that decides whether a type T has neither a member-function
+// nor format_provider based implementation that it can use. Mostly used so
+// that the compiler spits out a nice diagnostic when a type with no format
+// implementation can be located.
+template <typename T>
+struct uses_missing_provider
+ : public std::integral_constant<bool, !uses_format_member<T>::value &&
+ !uses_format_provider<T>::value &&
+ !uses_stream_operator<T>::value> {
+};
+
+template <typename T>
+typename std::enable_if<uses_format_member<T>::value, T>::type
+build_format_adapter(T &&Item) {
+ return std::forward<T>(Item);
+}
+
+template <typename T>
+typename std::enable_if<uses_format_provider<T>::value,
+ provider_format_adapter<T>>::type
+build_format_adapter(T &&Item) {
+ return provider_format_adapter<T>(std::forward<T>(Item));
+}
+
+template <typename T>
+typename std::enable_if<uses_stream_operator<T>::value,
+ stream_operator_format_adapter<T>>::type
+build_format_adapter(T &&Item) {
+ // If the caller passed an Error by value, then stream_operator_format_adapter
+ // would be responsible for consuming it.
+ // Make the caller opt into this by calling fmt_consume().
+ static_assert(
+ !std::is_same<llvm::Error, typename std::remove_cv<T>::type>::value,
+ "llvm::Error-by-value must be wrapped in fmt_consume() for formatv");
+ return stream_operator_format_adapter<T>(std::forward<T>(Item));
+}
+
+template <typename T>
+typename std::enable_if<uses_missing_provider<T>::value,
+ missing_format_adapter<T>>::type
+build_format_adapter(T &&Item) {
+ return missing_format_adapter<T>();
+}
+}
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/FormattedStream.h b/third_party/llvm-project/include/llvm/Support/FormattedStream.h
new file mode 100644
index 000000000..b49c8d865
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/FormattedStream.h
@@ -0,0 +1,161 @@
+//===-- llvm/Support/FormattedStream.h - Formatted streams ------*- 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 raw_ostream implementations for streams to do
+// things like pretty-print comments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FORMATTEDSTREAM_H
+#define LLVM_SUPPORT_FORMATTEDSTREAM_H
+
+#include "llvm/Support/raw_ostream.h"
+#include <utility>
+
+namespace llvm {
+
+/// formatted_raw_ostream - A raw_ostream that wraps another one and keeps track
+/// of line and column position, allowing padding out to specific column
+/// boundaries and querying the number of lines written to the stream.
+///
+class formatted_raw_ostream : public raw_ostream {
+ /// TheStream - The real stream we output to. We set it to be
+ /// unbuffered, since we're already doing our own buffering.
+ ///
+ raw_ostream *TheStream;
+
+ /// Position - The current output column and line of the data that's
+ /// been flushed and the portion of the buffer that's been
+ /// scanned. The line and column scheme is zero-based.
+ ///
+ std::pair<unsigned, unsigned> Position;
+
+ /// Scanned - This points to one past the last character in the
+ /// buffer we've scanned.
+ ///
+ const char *Scanned;
+
+ void write_impl(const char *Ptr, size_t Size) override;
+
+ /// current_pos - Return the current position within the stream,
+ /// not counting the bytes currently in the buffer.
+ uint64_t current_pos() const override {
+ // Our current position in the stream is all the contents which have been
+ // written to the underlying stream (*not* the current position of the
+ // underlying stream).
+ return TheStream->tell();
+ }
+
+ /// ComputePosition - Examine the given output buffer and figure out the new
+ /// position after output.
+ ///
+ void ComputePosition(const char *Ptr, size_t size);
+
+ void setStream(raw_ostream &Stream) {
+ releaseStream();
+
+ TheStream = &Stream;
+
+ // This formatted_raw_ostream inherits from raw_ostream, so it'll do its
+ // own buffering, and it doesn't need or want TheStream to do another
+ // layer of buffering underneath. Resize the buffer to what TheStream
+ // had been using, and tell TheStream not to do its own buffering.
+ if (size_t BufferSize = TheStream->GetBufferSize())
+ SetBufferSize(BufferSize);
+ else
+ SetUnbuffered();
+ TheStream->SetUnbuffered();
+
+ Scanned = nullptr;
+ }
+
+public:
+ /// formatted_raw_ostream - Open the specified file for
+ /// writing. If an error occurs, information about the error is
+ /// put into ErrorInfo, and the stream should be immediately
+ /// destroyed; the string will be empty if no error occurred.
+ ///
+ /// As a side effect, the given Stream is set to be Unbuffered.
+ /// This is because formatted_raw_ostream does its own buffering,
+ /// so it doesn't want another layer of buffering to be happening
+ /// underneath it.
+ ///
+ formatted_raw_ostream(raw_ostream &Stream)
+ : TheStream(nullptr), Position(0, 0) {
+ setStream(Stream);
+ }
+ explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) {
+ Scanned = nullptr;
+ }
+
+ ~formatted_raw_ostream() override {
+ flush();
+ releaseStream();
+ }
+
+ /// PadToColumn - Align the output to some column number. If the current
+ /// column is already equal to or more than NewCol, PadToColumn inserts one
+ /// space.
+ ///
+ /// \param NewCol - The column to move to.
+ formatted_raw_ostream &PadToColumn(unsigned NewCol);
+
+ /// getColumn - Return the column number
+ unsigned getColumn() { return Position.first; }
+
+ /// getLine - Return the line number
+ unsigned getLine() { return Position.second; }
+
+ raw_ostream &resetColor() override {
+ TheStream->resetColor();
+ return *this;
+ }
+
+ raw_ostream &reverseColor() override {
+ TheStream->reverseColor();
+ return *this;
+ }
+
+ raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override {
+ TheStream->changeColor(Color, Bold, BG);
+ return *this;
+ }
+
+ bool is_displayed() const override {
+ return TheStream->is_displayed();
+ }
+
+private:
+ void releaseStream() {
+ // Transfer the buffer settings from this raw_ostream back to the underlying
+ // stream.
+ if (!TheStream)
+ return;
+ if (size_t BufferSize = GetBufferSize())
+ TheStream->SetBufferSize(BufferSize);
+ else
+ TheStream->SetUnbuffered();
+ }
+};
+
+/// fouts() - This returns a reference to a formatted_raw_ostream for
+/// standard output. Use it like: fouts() << "foo" << "bar";
+formatted_raw_ostream &fouts();
+
+/// ferrs() - This returns a reference to a formatted_raw_ostream for
+/// standard error. Use it like: ferrs() << "foo" << "bar";
+formatted_raw_ostream &ferrs();
+
+/// fdbgs() - This returns a reference to a formatted_raw_ostream for
+/// debug output. Use it like: fdbgs() << "foo" << "bar";
+formatted_raw_ostream &fdbgs();
+
+} // end llvm namespace
+
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/Host.h b/third_party/llvm-project/include/llvm/Support/Host.h
new file mode 100644
index 000000000..44f543c36
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Host.h
@@ -0,0 +1,70 @@
+//===- llvm/Support/Host.h - Host machine characteristics --------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Methods for querying the nature of the host machine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_HOST_H
+#define LLVM_SUPPORT_HOST_H
+
+#include "llvm/ADT/StringMap.h"
+
+#include <string>
+
+namespace llvm {
+namespace sys {
+
+ /// getDefaultTargetTriple() - Return the default target triple the compiler
+ /// has been configured to produce code for.
+ ///
+ /// The target triple is a string in the format of:
+ /// CPU_TYPE-VENDOR-OPERATING_SYSTEM
+ /// or
+ /// CPU_TYPE-VENDOR-KERNEL-OPERATING_SYSTEM
+ std::string getDefaultTargetTriple();
+
+ /// getProcessTriple() - Return an appropriate target triple for generating
+ /// code to be loaded into the current process, e.g. when using the JIT.
+ std::string getProcessTriple();
+
+ /// getHostCPUName - Get the LLVM name for the host CPU. The particular format
+ /// of the name is target dependent, and suitable for passing as -mcpu to the
+ /// target which matches the host.
+ ///
+ /// \return - The host CPU name, or empty if the CPU could not be determined.
+ StringRef getHostCPUName();
+
+ /// getHostCPUFeatures - Get the LLVM names for the host CPU features.
+ /// The particular format of the names are target dependent, and suitable for
+ /// passing as -mattr to the target which matches the host.
+ ///
+ /// \param Features - A string mapping feature names to either
+ /// true (if enabled) or false (if disabled). This routine makes no guarantees
+ /// about exactly which features may appear in this map, except that they are
+ /// all valid LLVM feature names.
+ ///
+ /// \return - True on success.
+ bool getHostCPUFeatures(StringMap<bool> &Features);
+
+ /// Get the number of physical cores (as opposed to logical cores returned
+ /// from thread::hardware_concurrency(), which includes hyperthreads).
+ /// Returns -1 if unknown for the current host system.
+ int getHostNumPhysicalCores();
+
+ namespace detail {
+ /// Helper functions to extract HostCPUName from /proc/cpuinfo on linux.
+ StringRef getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent);
+ StringRef getHostCPUNameForARM(StringRef ProcCpuinfoContent);
+ StringRef getHostCPUNameForS390x(StringRef ProcCpuinfoContent);
+ StringRef getHostCPUNameForBPF();
+ }
+}
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/LEB128.h b/third_party/llvm-project/include/llvm/Support/LEB128.h
new file mode 100644
index 000000000..a02b83ca9
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/LEB128.h
@@ -0,0 +1,198 @@
+//===- llvm/Support/LEB128.h - [SU]LEB128 utility functions -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares some utility functions for encoding SLEB128 and
+// ULEB128 values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_LEB128_H
+#define LLVM_SUPPORT_LEB128_H
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+/// Utility function to encode a SLEB128 value to an output stream. Returns
+/// the length in bytes of the encoded value.
+inline unsigned encodeSLEB128(int64_t Value, raw_ostream &OS,
+ unsigned PadTo = 0) {
+ bool More;
+ unsigned Count = 0;
+ do {
+ uint8_t Byte = Value & 0x7f;
+ // NOTE: this assumes that this signed shift is an arithmetic right shift.
+ Value >>= 7;
+ More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
+ ((Value == -1) && ((Byte & 0x40) != 0))));
+ Count++;
+ if (More || Count < PadTo)
+ Byte |= 0x80; // Mark this byte to show that more bytes will follow.
+ OS << char(Byte);
+ } while (More);
+
+ // Pad with 0x80 and emit a terminating byte at the end.
+ if (Count < PadTo) {
+ uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
+ for (; Count < PadTo - 1; ++Count)
+ OS << char(PadValue | 0x80);
+ OS << char(PadValue);
+ Count++;
+ }
+ return Count;
+}
+
+/// Utility function to encode a SLEB128 value to a buffer. Returns
+/// the length in bytes of the encoded value.
+inline unsigned encodeSLEB128(int64_t Value, uint8_t *p, unsigned PadTo = 0) {
+ uint8_t *orig_p = p;
+ unsigned Count = 0;
+ bool More;
+ do {
+ uint8_t Byte = Value & 0x7f;
+ // NOTE: this assumes that this signed shift is an arithmetic right shift.
+ Value >>= 7;
+ More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
+ ((Value == -1) && ((Byte & 0x40) != 0))));
+ Count++;
+ if (More || Count < PadTo)
+ Byte |= 0x80; // Mark this byte to show that more bytes will follow.
+ *p++ = Byte;
+ } while (More);
+
+ // Pad with 0x80 and emit a terminating byte at the end.
+ if (Count < PadTo) {
+ uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
+ for (; Count < PadTo - 1; ++Count)
+ *p++ = (PadValue | 0x80);
+ *p++ = PadValue;
+ }
+ return (unsigned)(p - orig_p);
+}
+
+/// Utility function to encode a ULEB128 value to an output stream. Returns
+/// the length in bytes of the encoded value.
+inline unsigned encodeULEB128(uint64_t Value, raw_ostream &OS,
+ unsigned PadTo = 0) {
+ unsigned Count = 0;
+ do {
+ uint8_t Byte = Value & 0x7f;
+ Value >>= 7;
+ Count++;
+ if (Value != 0 || Count < PadTo)
+ Byte |= 0x80; // Mark this byte to show that more bytes will follow.
+ OS << char(Byte);
+ } while (Value != 0);
+
+ // Pad with 0x80 and emit a null byte at the end.
+ if (Count < PadTo) {
+ for (; Count < PadTo - 1; ++Count)
+ OS << '\x80';
+ OS << '\x00';
+ Count++;
+ }
+ return Count;
+}
+
+/// Utility function to encode a ULEB128 value to a buffer. Returns
+/// the length in bytes of the encoded value.
+inline unsigned encodeULEB128(uint64_t Value, uint8_t *p,
+ unsigned PadTo = 0) {
+ uint8_t *orig_p = p;
+ unsigned Count = 0;
+ do {
+ uint8_t Byte = Value & 0x7f;
+ Value >>= 7;
+ Count++;
+ if (Value != 0 || Count < PadTo)
+ Byte |= 0x80; // Mark this byte to show that more bytes will follow.
+ *p++ = Byte;
+ } while (Value != 0);
+
+ // Pad with 0x80 and emit a null byte at the end.
+ if (Count < PadTo) {
+ for (; Count < PadTo - 1; ++Count)
+ *p++ = '\x80';
+ *p++ = '\x00';
+ }
+
+ return (unsigned)(p - orig_p);
+}
+
+/// Utility function to decode a ULEB128 value.
+inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr,
+ const uint8_t *end = nullptr,
+ const char **error = nullptr) {
+ const uint8_t *orig_p = p;
+ uint64_t Value = 0;
+ unsigned Shift = 0;
+ if (error)
+ *error = nullptr;
+ do {
+ if (end && p == end) {
+ if (error)
+ *error = "malformed uleb128, extends past end";
+ if (n)
+ *n = (unsigned)(p - orig_p);
+ return 0;
+ }
+ uint64_t Slice = *p & 0x7f;
+ if (Shift >= 64 || Slice << Shift >> Shift != Slice) {
+ if (error)
+ *error = "uleb128 too big for uint64";
+ if (n)
+ *n = (unsigned)(p - orig_p);
+ return 0;
+ }
+ Value += uint64_t(*p & 0x7f) << Shift;
+ Shift += 7;
+ } while (*p++ >= 128);
+ if (n)
+ *n = (unsigned)(p - orig_p);
+ return Value;
+}
+
+/// Utility function to decode a SLEB128 value.
+inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr,
+ const uint8_t *end = nullptr,
+ const char **error = nullptr) {
+ const uint8_t *orig_p = p;
+ int64_t Value = 0;
+ unsigned Shift = 0;
+ uint8_t Byte;
+ if (error)
+ *error = nullptr;
+ do {
+ if (end && p == end) {
+ if (error)
+ *error = "malformed sleb128, extends past end";
+ if (n)
+ *n = (unsigned)(p - orig_p);
+ return 0;
+ }
+ Byte = *p++;
+ Value |= (uint64_t(Byte & 0x7f) << Shift);
+ Shift += 7;
+ } while (Byte >= 128);
+ // Sign extend negative numbers if needed.
+ if (Shift < 64 && (Byte & 0x40))
+ Value |= (-1ULL) << Shift;
+ if (n)
+ *n = (unsigned)(p - orig_p);
+ return Value;
+}
+
+/// Utility function to get the size of the ULEB128-encoded value.
+extern unsigned getULEB128Size(uint64_t Value);
+
+/// Utility function to get the size of the SLEB128-encoded value.
+extern unsigned getSLEB128Size(int64_t Value);
+
+} // namespace llvm
+
+#endif // LLVM_SYSTEM_LEB128_H
diff --git a/third_party/llvm-project/include/llvm/Support/LICENSE.TXT b/third_party/llvm-project/include/llvm/Support/LICENSE.TXT
new file mode 100644
index 000000000..3479b3fd7
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/LICENSE.TXT
@@ -0,0 +1,6 @@
+LLVM System Interface Library
+-------------------------------------------------------------------------------
+The LLVM System Interface Library is licensed under the Illinois Open Source
+License and has the following additional copyright:
+
+Copyright (C) 2004 eXtensible Systems, Inc.
diff --git a/third_party/llvm-project/include/llvm/Support/LineIterator.h b/third_party/llvm-project/include/llvm/Support/LineIterator.h
new file mode 100644
index 000000000..2a1e47bfe
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/LineIterator.h
@@ -0,0 +1,87 @@
+//===- LineIterator.h - Iterator to read a text buffer's lines --*- 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_LINEITERATOR_H
+#define LLVM_SUPPORT_LINEITERATOR_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include <iterator>
+
+namespace llvm {
+
+class MemoryBuffer;
+
+/// A forward iterator which reads text lines from a buffer.
+///
+/// This class provides a forward iterator interface for reading one line at
+/// a time from a buffer. When default constructed the iterator will be the
+/// "end" iterator.
+///
+/// The iterator is aware of what line number it is currently processing. It
+/// strips blank lines by default, and comment lines given a comment-starting
+/// character.
+///
+/// Note that this iterator requires the buffer to be nul terminated.
+class line_iterator
+ : public std::iterator<std::forward_iterator_tag, StringRef> {
+ const MemoryBuffer *Buffer = nullptr;
+ char CommentMarker = '\0';
+ bool SkipBlanks = true;
+
+ unsigned LineNumber = 1;
+ StringRef CurrentLine;
+
+public:
+ /// Default construct an "end" iterator.
+ line_iterator() = default;
+
+ /// Construct a new iterator around some memory buffer.
+ explicit line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks = true,
+ char CommentMarker = '\0');
+
+ /// Return true if we've reached EOF or are an "end" iterator.
+ bool is_at_eof() const { return !Buffer; }
+
+ /// Return true if we're an "end" iterator or have reached EOF.
+ bool is_at_end() const { return is_at_eof(); }
+
+ /// Return the current line number. May return any number at EOF.
+ int64_t line_number() const { return LineNumber; }
+
+ /// Advance to the next (non-empty, non-comment) line.
+ line_iterator &operator++() {
+ advance();
+ return *this;
+ }
+ line_iterator operator++(int) {
+ line_iterator tmp(*this);
+ advance();
+ return tmp;
+ }
+
+ /// Get the current line as a \c StringRef.
+ StringRef operator*() const { return CurrentLine; }
+ const StringRef *operator->() const { return &CurrentLine; }
+
+ friend bool operator==(const line_iterator &LHS, const line_iterator &RHS) {
+ return LHS.Buffer == RHS.Buffer &&
+ LHS.CurrentLine.begin() == RHS.CurrentLine.begin();
+ }
+
+ friend bool operator!=(const line_iterator &LHS, const line_iterator &RHS) {
+ return !(LHS == RHS);
+ }
+
+private:
+ /// Advance the iterator to the next line.
+ void advance();
+};
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/Locale.h b/third_party/llvm-project/include/llvm/Support/Locale.h
new file mode 100644
index 000000000..f7a2c036e
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Locale.h
@@ -0,0 +1,17 @@
+#ifndef LLVM_SUPPORT_LOCALE_H
+#define LLVM_SUPPORT_LOCALE_H
+
+namespace llvm {
+class StringRef;
+
+namespace sys {
+namespace locale {
+
+int columnWidth(StringRef s);
+bool isPrint(int c);
+
+}
+}
+}
+
+#endif // LLVM_SUPPORT_LOCALE_H
diff --git a/third_party/llvm-project/include/llvm/Support/MD5.h b/third_party/llvm-project/include/llvm/Support/MD5.h
new file mode 100644
index 000000000..bb2bdbf1b
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/MD5.h
@@ -0,0 +1,122 @@
+/* -*- C++ -*-
+ * This code is derived from (original license follows):
+ *
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001. No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See md5.c for more information.
+ */
+
+#ifndef LLVM_SUPPORT_MD5_H
+#define LLVM_SUPPORT_MD5_H
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Endian.h"
+#include <array>
+#include <cstdint>
+
+namespace llvm {
+
+template <typename T> class ArrayRef;
+
+class MD5 {
+ // Any 32-bit or wider unsigned integer data type will do.
+ typedef uint32_t MD5_u32plus;
+
+ MD5_u32plus a = 0x67452301;
+ MD5_u32plus b = 0xefcdab89;
+ MD5_u32plus c = 0x98badcfe;
+ MD5_u32plus d = 0x10325476;
+ MD5_u32plus hi = 0;
+ MD5_u32plus lo = 0;
+ uint8_t buffer[64];
+ MD5_u32plus block[16];
+
+public:
+ struct MD5Result {
+ std::array<uint8_t, 16> Bytes;
+
+ operator std::array<uint8_t, 16>() const { return Bytes; }
+
+ const uint8_t &operator[](size_t I) const { return Bytes[I]; }
+ uint8_t &operator[](size_t I) { return Bytes[I]; }
+
+ SmallString<32> digest() const;
+
+ uint64_t low() const {
+ // Our MD5 implementation returns the result in little endian, so the low
+ // word is first.
+ using namespace support;
+ return endian::read<uint64_t, little, unaligned>(Bytes.data());
+ }
+
+ uint64_t high() const {
+ using namespace support;
+ return endian::read<uint64_t, little, unaligned>(Bytes.data() + 8);
+ }
+ std::pair<uint64_t, uint64_t> words() const {
+ using namespace support;
+ return std::make_pair(high(), low());
+ }
+ };
+
+ MD5();
+
+ /// Updates the hash for the byte stream provided.
+ void update(ArrayRef<uint8_t> Data);
+
+ /// Updates the hash for the StringRef provided.
+ void update(StringRef Str);
+
+ /// Finishes off the hash and puts the result in result.
+ void final(MD5Result &Result);
+
+ /// Translates the bytes in \p Res to a hex string that is
+ /// deposited into \p Str. The result will be of length 32.
+ static void stringifyResult(MD5Result &Result, SmallString<32> &Str);
+
+ /// Computes the hash for a given bytes.
+ static std::array<uint8_t, 16> hash(ArrayRef<uint8_t> Data);
+
+private:
+ const uint8_t *body(ArrayRef<uint8_t> Data);
+};
+
+inline bool operator==(const MD5::MD5Result &LHS, const MD5::MD5Result &RHS) {
+ return LHS.Bytes == RHS.Bytes;
+}
+
+/// Helper to compute and return lower 64 bits of the given string's MD5 hash.
+inline uint64_t MD5Hash(StringRef Str) {
+ using namespace support;
+
+ MD5 Hash;
+ Hash.update(Str);
+ MD5::MD5Result Result;
+ Hash.final(Result);
+ // Return the least significant word.
+ return Result.low();
+}
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_MD5_H
diff --git a/third_party/llvm-project/include/llvm/Support/ManagedStatic.h b/third_party/llvm-project/include/llvm/Support/ManagedStatic.h
new file mode 100644
index 000000000..4eb30f548
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/ManagedStatic.h
@@ -0,0 +1 @@
+// XXX BINARYEN - we don't need this, but stuff imports it
diff --git a/third_party/llvm-project/include/llvm/Support/MathExtras.h b/third_party/llvm-project/include/llvm/Support/MathExtras.h
new file mode 100644
index 000000000..004a6f5f6
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/MathExtras.h
@@ -0,0 +1,951 @@
+//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains some functions that are useful for math stuff.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MATHEXTRAS_H
+#define LLVM_SUPPORT_MATHEXTRAS_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include <algorithm>
+#include <cassert>
+#include <climits>
+#include <cstring>
+#include <limits>
+#include <type_traits>
+
+#ifdef __ANDROID_NDK__
+#include <android/api-level.h>
+#endif
+
+#ifdef _MSC_VER
+// Declare these intrinsics manually rather including intrin.h. It's very
+// expensive, and MathExtras.h is popular.
+// #include <intrin.h>
+extern "C" {
+unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask);
+unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask);
+unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask);
+unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask);
+}
+#endif
+
+namespace llvm {
+
+/// The behavior an operation has on an input of 0.
+enum ZeroBehavior {
+ /// The returned value is undefined.
+ ZB_Undefined,
+ /// The returned value is numeric_limits<T>::max()
+ ZB_Max,
+ /// The returned value is numeric_limits<T>::digits
+ ZB_Width
+};
+
+/// Mathematical constants.
+namespace numbers {
+// TODO: Track C++20 std::numbers.
+// TODO: Favor using the hexadecimal FP constants (requires C++17).
+constexpr double e = 2.7182818284590452354, // (0x1.5bf0a8b145749P+1) https://oeis.org/A001113
+ egamma = .57721566490153286061, // (0x1.2788cfc6fb619P-1) https://oeis.org/A001620
+ ln2 = .69314718055994530942, // (0x1.62e42fefa39efP-1) https://oeis.org/A002162
+ ln10 = 2.3025850929940456840, // (0x1.24bb1bbb55516P+1) https://oeis.org/A002392
+ log2e = 1.4426950408889634074, // (0x1.71547652b82feP+0)
+ log10e = .43429448190325182765, // (0x1.bcb7b1526e50eP-2)
+ pi = 3.1415926535897932385, // (0x1.921fb54442d18P+1) https://oeis.org/A000796
+ inv_pi = .31830988618379067154, // (0x1.45f306bc9c883P-2) https://oeis.org/A049541
+ sqrtpi = 1.7724538509055160273, // (0x1.c5bf891b4ef6bP+0) https://oeis.org/A002161
+ inv_sqrtpi = .56418958354775628695, // (0x1.20dd750429b6dP-1) https://oeis.org/A087197
+ sqrt2 = 1.4142135623730950488, // (0x1.6a09e667f3bcdP+0) https://oeis.org/A00219
+ inv_sqrt2 = .70710678118654752440, // (0x1.6a09e667f3bcdP-1)
+ sqrt3 = 1.7320508075688772935, // (0x1.bb67ae8584caaP+0) https://oeis.org/A002194
+ inv_sqrt3 = .57735026918962576451, // (0x1.279a74590331cP-1)
+ phi = 1.6180339887498948482; // (0x1.9e3779b97f4a8P+0) https://oeis.org/A001622
+constexpr float ef = 2.71828183F, // (0x1.5bf0a8P+1) https://oeis.org/A001113
+ egammaf = .577215665F, // (0x1.2788d0P-1) https://oeis.org/A001620
+ ln2f = .693147181F, // (0x1.62e430P-1) https://oeis.org/A002162
+ ln10f = 2.30258509F, // (0x1.26bb1cP+1) https://oeis.org/A002392
+ log2ef = 1.44269504F, // (0x1.715476P+0)
+ log10ef = .434294482F, // (0x1.bcb7b2P-2)
+ pif = 3.14159265F, // (0x1.921fb6P+1) https://oeis.org/A000796
+ inv_pif = .318309886F, // (0x1.45f306P-2) https://oeis.org/A049541
+ sqrtpif = 1.77245385F, // (0x1.c5bf8aP+0) https://oeis.org/A002161
+ inv_sqrtpif = .564189584F, // (0x1.20dd76P-1) https://oeis.org/A087197
+ sqrt2f = 1.41421356F, // (0x1.6a09e6P+0) https://oeis.org/A002193
+ inv_sqrt2f = .707106781F, // (0x1.6a09e6P-1)
+ sqrt3f = 1.73205081F, // (0x1.bb67aeP+0) https://oeis.org/A002194
+ inv_sqrt3f = .577350269F, // (0x1.279a74P-1)
+ phif = 1.61803399F; // (0x1.9e377aP+0) https://oeis.org/A001622
+} // namespace numbers
+
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
+ static unsigned count(T Val, ZeroBehavior) {
+ if (!Val)
+ return std::numeric_limits<T>::digits;
+ if (Val & 0x1)
+ return 0;
+
+ // Bisection method.
+ unsigned ZeroBits = 0;
+ T Shift = std::numeric_limits<T>::digits >> 1;
+ T Mask = std::numeric_limits<T>::max() >> Shift;
+ while (Shift) {
+ if ((Val & Mask) == 0) {
+ Val >>= Shift;
+ ZeroBits |= Shift;
+ }
+ Shift >>= 1;
+ Mask >>= Shift;
+ }
+ return ZeroBits;
+ }
+};
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+template <typename T> struct TrailingZerosCounter<T, 4> {
+ static unsigned count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 32;
+
+#if __has_builtin(__builtin_ctz) || defined(__GNUC__)
+ return __builtin_ctz(Val);
+#elif defined(_MSC_VER)
+ unsigned long Index;
+ _BitScanForward(&Index, Val);
+ return Index;
+#endif
+ }
+};
+
+#if !defined(_MSC_VER) || defined(_M_X64)
+template <typename T> struct TrailingZerosCounter<T, 8> {
+ static unsigned count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 64;
+
+#if __has_builtin(__builtin_ctzll) || defined(__GNUC__)
+ return __builtin_ctzll(Val);
+#elif defined(_MSC_VER)
+ unsigned long Index;
+ _BitScanForward64(&Index, Val);
+ return Index;
+#endif
+ }
+};
+#endif
+#endif
+} // namespace detail
+
+/// Count number of 0's from the least significant bit to the most
+/// stopping at the first 1.
+///
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
+/// valid arguments.
+template <typename T>
+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.");
+ return llvm::detail::TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB);
+}
+
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
+ static unsigned count(T Val, ZeroBehavior) {
+ if (!Val)
+ return std::numeric_limits<T>::digits;
+
+ // Bisection method.
+ unsigned ZeroBits = 0;
+ for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
+ T Tmp = Val >> Shift;
+ if (Tmp)
+ Val = Tmp;
+ else
+ ZeroBits |= Shift;
+ }
+ return ZeroBits;
+ }
+};
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+template <typename T> struct LeadingZerosCounter<T, 4> {
+ static unsigned count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 32;
+
+#if __has_builtin(__builtin_clz) || defined(__GNUC__)
+ return __builtin_clz(Val);
+#elif defined(_MSC_VER)
+ unsigned long Index;
+ _BitScanReverse(&Index, Val);
+ return Index ^ 31;
+#endif
+ }
+};
+
+#if !defined(_MSC_VER) || defined(_M_X64)
+template <typename T> struct LeadingZerosCounter<T, 8> {
+ static unsigned count(T Val, ZeroBehavior ZB) {
+ if (ZB != ZB_Undefined && Val == 0)
+ return 64;
+
+#if __has_builtin(__builtin_clzll) || defined(__GNUC__)
+ return __builtin_clzll(Val);
+#elif defined(_MSC_VER)
+ unsigned long Index;
+ _BitScanReverse64(&Index, Val);
+ return Index ^ 63;
+#endif
+ }
+};
+#endif
+#endif
+} // namespace detail
+
+/// Count number of 0's from the most significant bit to the least
+/// stopping at the first 1.
+///
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
+/// valid arguments.
+template <typename T>
+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.");
+ return llvm::detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
+}
+
+/// Get the index of the first set bit starting from the least
+/// significant bit.
+///
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
+/// valid arguments.
+template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
+ if (ZB == ZB_Max && Val == 0)
+ return std::numeric_limits<T>::max();
+
+ return countTrailingZeros(Val, ZB_Undefined);
+}
+
+/// Create a bitmask with the N right-most bits set to 1, and all other
+/// bits set to 0. Only unsigned types are allowed.
+template <typename T> T maskTrailingOnes(unsigned N) {
+ static_assert(std::is_unsigned<T>::value, "Invalid type!");
+ const unsigned Bits = CHAR_BIT * sizeof(T);
+ assert(N <= Bits && "Invalid bit index");
+ return N == 0 ? 0 : (T(-1) >> (Bits - N));
+}
+
+/// Create a bitmask with the N left-most bits set to 1, and all other
+/// bits set to 0. Only unsigned types are allowed.
+template <typename T> T maskLeadingOnes(unsigned N) {
+ return ~maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N);
+}
+
+/// Create a bitmask with the N right-most bits set to 0, and all other
+/// bits set to 1. Only unsigned types are allowed.
+template <typename T> T maskTrailingZeros(unsigned N) {
+ return maskLeadingOnes<T>(CHAR_BIT * sizeof(T) - N);
+}
+
+/// Create a bitmask with the N left-most bits set to 0, and all other
+/// bits set to 1. Only unsigned types are allowed.
+template <typename T> T maskLeadingZeros(unsigned N) {
+ return maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N);
+}
+
+/// Get the index of the last set bit starting from the least
+/// significant bit.
+///
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
+/// valid arguments.
+template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
+ if (ZB == ZB_Max && Val == 0)
+ return std::numeric_limits<T>::max();
+
+ // Use ^ instead of - because both gcc and llvm can remove the associated ^
+ // in the __builtin_clz intrinsic on x86.
+ return countLeadingZeros(Val, ZB_Undefined) ^
+ (std::numeric_limits<T>::digits - 1);
+}
+
+/// Macro compressed bit reversal table for 256 bits.
+///
+/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable
+static const unsigned char BitReverseTable256[256] = {
+#define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64
+#define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16)
+#define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4)
+ R6(0), R6(2), R6(1), R6(3)
+#undef R2
+#undef R4
+#undef R6
+};
+
+/// Reverse the bits in \p Val.
+template <typename T>
+T reverseBits(T Val) {
+ unsigned char in[sizeof(Val)];
+ unsigned char out[sizeof(Val)];
+ std::memcpy(in, &Val, sizeof(Val));
+ for (unsigned i = 0; i < sizeof(Val); ++i)
+ out[(sizeof(Val) - i) - 1] = BitReverseTable256[in[i]];
+ std::memcpy(&Val, out, sizeof(Val));
+ return Val;
+}
+
+// NOTE: The following support functions use the _32/_64 extensions instead of
+// type overloading so that signed and unsigned integers can be used without
+// ambiguity.
+
+/// Return the high 32 bits of a 64 bit value.
+constexpr inline uint32_t Hi_32(uint64_t Value) {
+ return static_cast<uint32_t>(Value >> 32);
+}
+
+/// Return the low 32 bits of a 64 bit value.
+constexpr inline uint32_t Lo_32(uint64_t Value) {
+ return static_cast<uint32_t>(Value);
+}
+
+/// Make a 64-bit integer from a high / low pair of 32-bit integers.
+constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) {
+ return ((uint64_t)High << 32) | (uint64_t)Low;
+}
+
+/// Checks if an integer fits into the given bit width.
+template <unsigned N> constexpr inline bool isInt(int64_t x) {
+ return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1)));
+}
+// Template specializations to get better code for common cases.
+template <> constexpr inline bool isInt<8>(int64_t x) {
+ return static_cast<int8_t>(x) == x;
+}
+template <> constexpr inline bool isInt<16>(int64_t x) {
+ return static_cast<int16_t>(x) == x;
+}
+template <> constexpr inline bool isInt<32>(int64_t x) {
+ return static_cast<int32_t>(x) == x;
+}
+
+/// Checks if a signed integer is an N bit number shifted left by S.
+template <unsigned N, unsigned S>
+constexpr inline bool isShiftedInt(int64_t x) {
+ static_assert(
+ N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number.");
+ static_assert(N + S <= 64, "isShiftedInt<N, S> with N + S > 64 is too wide.");
+ return isInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0);
+}
+
+/// Checks if an unsigned integer fits into the given bit width.
+///
+/// This is written as two functions rather than as simply
+///
+/// return N >= 64 || X < (UINT64_C(1) << N);
+///
+/// to keep MSVC from (incorrectly) warning on isUInt<64> that we're shifting
+/// left too many places.
+template <unsigned N>
+constexpr inline typename std::enable_if<(N < 64), bool>::type
+isUInt(uint64_t X) {
+ static_assert(N > 0, "isUInt<0> doesn't make sense");
+ return X < (UINT64_C(1) << (N));
+}
+template <unsigned N>
+constexpr inline typename std::enable_if<N >= 64, bool>::type
+isUInt(uint64_t X) {
+ return true;
+}
+
+// Template specializations to get better code for common cases.
+template <> constexpr inline bool isUInt<8>(uint64_t x) {
+ return static_cast<uint8_t>(x) == x;
+}
+template <> constexpr inline bool isUInt<16>(uint64_t x) {
+ return static_cast<uint16_t>(x) == x;
+}
+template <> constexpr inline bool isUInt<32>(uint64_t x) {
+ return static_cast<uint32_t>(x) == x;
+}
+
+/// Checks if a unsigned integer is an N bit number shifted left by S.
+template <unsigned N, unsigned S>
+constexpr inline bool isShiftedUInt(uint64_t x) {
+ static_assert(
+ N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)");
+ static_assert(N + S <= 64,
+ "isShiftedUInt<N, S> with N + S > 64 is too wide.");
+ // Per the two static_asserts above, S must be strictly less than 64. So
+ // 1 << S is not undefined behavior.
+ return isUInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0);
+}
+
+/// Gets the maximum value for a N-bit unsigned integer.
+inline uint64_t maxUIntN(uint64_t N) {
+ assert(N > 0 && N <= 64 && "integer width out of range");
+
+ // uint64_t(1) << 64 is undefined behavior, so we can't do
+ // (uint64_t(1) << N) - 1
+ // without checking first that N != 64. But this works and doesn't have a
+ // branch.
+ return UINT64_MAX >> (64 - N);
+}
+
+/// Gets the minimum value for a N-bit signed integer.
+inline int64_t minIntN(int64_t N) {
+ assert(N > 0 && N <= 64 && "integer width out of range");
+
+ return -(UINT64_C(1)<<(N-1));
+}
+
+/// Gets the maximum value for a N-bit signed integer.
+inline int64_t maxIntN(int64_t N) {
+ assert(N > 0 && N <= 64 && "integer width out of range");
+
+ // This relies on two's complement wraparound when N == 64, so we convert to
+ // int64_t only at the very end to avoid UB.
+ return (UINT64_C(1) << (N - 1)) - 1;
+}
+
+/// Checks if an unsigned integer fits into the given (dynamic) bit width.
+inline bool isUIntN(unsigned N, uint64_t x) {
+ return N >= 64 || x <= maxUIntN(N);
+}
+
+/// Checks if an signed integer fits into the given (dynamic) bit width.
+inline bool isIntN(unsigned N, int64_t x) {
+ return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N));
+}
+
+/// Return true if the argument is a non-empty sequence of ones starting at the
+/// least significant bit with the remainder zero (32 bit version).
+/// Ex. isMask_32(0x0000FFFFU) == true.
+constexpr inline bool isMask_32(uint32_t Value) {
+ return Value && ((Value + 1) & Value) == 0;
+}
+
+/// Return true if the argument is a non-empty sequence of ones starting at the
+/// least significant bit with the remainder zero (64 bit version).
+constexpr inline bool isMask_64(uint64_t Value) {
+ return Value && ((Value + 1) & Value) == 0;
+}
+
+/// Return true if the argument contains a non-empty sequence of ones with the
+/// remainder zero (32 bit version.) Ex. isShiftedMask_32(0x0000FF00U) == true.
+constexpr inline bool isShiftedMask_32(uint32_t Value) {
+ return Value && isMask_32((Value - 1) | Value);
+}
+
+/// Return true if the argument contains a non-empty sequence of ones with the
+/// remainder zero (64 bit version.)
+constexpr inline bool isShiftedMask_64(uint64_t Value) {
+ return Value && isMask_64((Value - 1) | Value);
+}
+
+/// Return true if the argument is a power of two > 0.
+/// Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.)
+constexpr inline bool isPowerOf2_32(uint32_t Value) {
+ return Value && !(Value & (Value - 1));
+}
+
+/// Return true if the argument is a power of two > 0 (64 bit edition.)
+constexpr inline bool isPowerOf2_64(uint64_t Value) {
+ return Value && !(Value & (Value - 1));
+}
+
+/// Return a byte-swapped representation of the 16-bit argument.
+inline uint16_t ByteSwap_16(uint16_t Value) {
+ return sys::SwapByteOrder_16(Value);
+}
+
+/// Return a byte-swapped representation of the 32-bit argument.
+inline uint32_t ByteSwap_32(uint32_t Value) {
+ return sys::SwapByteOrder_32(Value);
+}
+
+/// Return a byte-swapped representation of the 64-bit argument.
+inline uint64_t ByteSwap_64(uint64_t Value) {
+ return sys::SwapByteOrder_64(Value);
+}
+
+/// Count the number of ones from the most significant bit to the first
+/// zero bit.
+///
+/// Ex. countLeadingOnes(0xFF0FFF00) == 8.
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of all ones. Only ZB_Width and
+/// ZB_Undefined are valid arguments.
+template <typename T>
+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.");
+ return countLeadingZeros<T>(~Value, ZB);
+}
+
+/// Count the number of ones from the least significant bit to the first
+/// zero bit.
+///
+/// Ex. countTrailingOnes(0x00FF00FF) == 8.
+/// Only unsigned integral types are allowed.
+///
+/// \param ZB the behavior on an input of all ones. Only ZB_Width and
+/// ZB_Undefined are valid arguments.
+template <typename T>
+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.");
+ return countTrailingZeros<T>(~Value, ZB);
+}
+
+namespace detail {
+template <typename T, std::size_t SizeOfT> struct PopulationCounter {
+ static unsigned count(T Value) {
+ // Generic version, forward to 32 bits.
+ static_assert(SizeOfT <= 4, "Not implemented!");
+#if defined(__GNUC__)
+ return __builtin_popcount(Value);
+#else
+ uint32_t v = Value;
+ v = v - ((v >> 1) & 0x55555555);
+ v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
+ return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
+#endif
+ }
+};
+
+template <typename T> struct PopulationCounter<T, 8> {
+ static unsigned count(T Value) {
+#if defined(__GNUC__)
+ return __builtin_popcountll(Value);
+#else
+ uint64_t v = Value;
+ v = v - ((v >> 1) & 0x5555555555555555ULL);
+ v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
+ v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
+ return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56);
+#endif
+ }
+};
+} // namespace detail
+
+/// Count the number of set bits in a value.
+/// Ex. countPopulation(0xF000F000) = 8
+/// Returns 0 if the word is zero.
+template <typename T>
+inline unsigned countPopulation(T Value) {
+ static_assert(std::numeric_limits<T>::is_integer &&
+ !std::numeric_limits<T>::is_signed,
+ "Only unsigned integral types are allowed.");
+ return detail::PopulationCounter<T, sizeof(T)>::count(Value);
+}
+
+/// Compile time Log2.
+/// Valid only for positive powers of two.
+template <size_t kValue> constexpr inline size_t CTLog2() {
+ static_assert(kValue > 0 && llvm::isPowerOf2_64(kValue),
+ "Value is not a valid power of 2");
+ return 1 + CTLog2<kValue / 2>();
+}
+
+template <> constexpr inline size_t CTLog2<1>() { return 0; }
+
+/// Return the log base 2 of the specified value.
+inline double Log2(double Value) {
+#if defined(__ANDROID_API__) && __ANDROID_API__ < 18
+ return __builtin_log(Value) / __builtin_log(2.0);
+#else
+ return log2(Value);
+#endif
+}
+
+/// Return the floor log base 2 of the specified value, -1 if the value is zero.
+/// (32 bit edition.)
+/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2
+inline unsigned Log2_32(uint32_t Value) {
+ return 31 - countLeadingZeros(Value);
+}
+
+/// Return the floor log base 2 of the specified value, -1 if the value is zero.
+/// (64 bit edition.)
+inline unsigned Log2_64(uint64_t Value) {
+ return 63 - countLeadingZeros(Value);
+}
+
+/// Return the ceil log base 2 of the specified value, 32 if the value is zero.
+/// (32 bit edition).
+/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3
+inline unsigned Log2_32_Ceil(uint32_t Value) {
+ return 32 - countLeadingZeros(Value - 1);
+}
+
+/// Return the ceil log base 2 of the specified value, 64 if the value is zero.
+/// (64 bit edition.)
+inline unsigned Log2_64_Ceil(uint64_t Value) {
+ return 64 - countLeadingZeros(Value - 1);
+}
+
+/// Return the greatest common divisor of the values using Euclid's algorithm.
+template <typename T>
+inline T greatestCommonDivisor(T A, T B) {
+ while (B) {
+ T Tmp = B;
+ B = A % B;
+ A = Tmp;
+ }
+ return A;
+}
+
+inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) {
+ return greatestCommonDivisor<uint64_t>(A, B);
+}
+
+/// This function takes a 64-bit integer and returns the bit equivalent double.
+inline double BitsToDouble(uint64_t Bits) {
+ double D;
+ static_assert(sizeof(uint64_t) == sizeof(double), "Unexpected type sizes");
+ memcpy(&D, &Bits, sizeof(Bits));
+ return D;
+}
+
+/// This function takes a 32-bit integer and returns the bit equivalent float.
+inline float BitsToFloat(uint32_t Bits) {
+ float F;
+ static_assert(sizeof(uint32_t) == sizeof(float), "Unexpected type sizes");
+ memcpy(&F, &Bits, sizeof(Bits));
+ return F;
+}
+
+/// This function takes a double and returns the bit equivalent 64-bit integer.
+/// Note that copying doubles around changes the bits of NaNs on some hosts,
+/// notably x86, so this routine cannot be used if these bits are needed.
+inline uint64_t DoubleToBits(double Double) {
+ uint64_t Bits;
+ static_assert(sizeof(uint64_t) == sizeof(double), "Unexpected type sizes");
+ memcpy(&Bits, &Double, sizeof(Double));
+ return Bits;
+}
+
+/// This function takes a float and returns the bit equivalent 32-bit integer.
+/// Note that copying floats around changes the bits of NaNs on some hosts,
+/// notably x86, so this routine cannot be used if these bits are needed.
+inline uint32_t FloatToBits(float Float) {
+ uint32_t Bits;
+ static_assert(sizeof(uint32_t) == sizeof(float), "Unexpected type sizes");
+ memcpy(&Bits, &Float, sizeof(Float));
+ return Bits;
+}
+
+/// A and B are either alignments or offsets. Return the minimum alignment that
+/// may be assumed after adding the two together.
+constexpr inline uint64_t MinAlign(uint64_t A, uint64_t B) {
+ // The largest power of 2 that divides both A and B.
+ //
+ // Replace "-Value" by "1+~Value" in the following commented code to avoid
+ // MSVC warning C4146
+ // return (A | B) & -(A | B);
+ return (A | B) & (1 + ~(A | B));
+}
+
+/// Returns the next power of two (in 64-bits) that is strictly greater than A.
+/// Returns zero on overflow.
+inline uint64_t NextPowerOf2(uint64_t A) {
+ A |= (A >> 1);
+ A |= (A >> 2);
+ A |= (A >> 4);
+ A |= (A >> 8);
+ A |= (A >> 16);
+ A |= (A >> 32);
+ return A + 1;
+}
+
+/// Returns the power of two which is less than or equal to the given value.
+/// Essentially, it is a floor operation across the domain of powers of two.
+inline uint64_t PowerOf2Floor(uint64_t A) {
+ if (!A) return 0;
+ return 1ull << (63 - countLeadingZeros(A, ZB_Undefined));
+}
+
+/// Returns the power of two which is greater than or equal to the given value.
+/// Essentially, it is a ceil operation across the domain of powers of two.
+inline uint64_t PowerOf2Ceil(uint64_t A) {
+ if (!A)
+ return 0;
+ return NextPowerOf2(A - 1);
+}
+
+/// Returns the next integer (mod 2**64) that is greater than or equal to
+/// \p Value and is a multiple of \p Align. \p Align must be non-zero.
+///
+/// If non-zero \p Skew is specified, the return value will be a minimal
+/// integer that is greater than or equal to \p Value and equal to
+/// \p Align * N + \p Skew for some integer N. If \p Skew is larger than
+/// \p Align, its value is adjusted to '\p Skew mod \p Align'.
+///
+/// Examples:
+/// \code
+/// alignTo(5, 8) = 8
+/// alignTo(17, 8) = 24
+/// alignTo(~0LL, 8) = 0
+/// alignTo(321, 255) = 510
+///
+/// alignTo(5, 8, 7) = 7
+/// alignTo(17, 8, 1) = 17
+/// alignTo(~0LL, 8, 3) = 3
+/// alignTo(321, 255, 42) = 552
+/// \endcode
+inline uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
+ assert(Align != 0u && "Align can't be 0.");
+ Skew %= Align;
+ return (Value + Align - 1 - Skew) / Align * Align + Skew;
+}
+
+/// Returns the next integer (mod 2**64) that is greater than or equal to
+/// \p Value and is a multiple of \c Align. \c Align must be non-zero.
+template <uint64_t Align> constexpr inline uint64_t alignTo(uint64_t Value) {
+ static_assert(Align != 0u, "Align must be non-zero");
+ return (Value + Align - 1) / Align * Align;
+}
+
+/// Returns the integer ceil(Numerator / Denominator).
+inline uint64_t divideCeil(uint64_t Numerator, uint64_t Denominator) {
+ return alignTo(Numerator, Denominator) / Denominator;
+}
+
+/// Returns the largest uint64_t less than or equal to \p Value and is
+/// \p Skew mod \p Align. \p Align must be non-zero
+inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
+ assert(Align != 0u && "Align can't be 0.");
+ Skew %= Align;
+ return (Value - Skew) / Align * Align + Skew;
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
+/// Requires 0 < B <= 32.
+template <unsigned B> constexpr inline int32_t SignExtend32(uint32_t X) {
+ static_assert(B > 0, "Bit width can't be 0.");
+ static_assert(B <= 32, "Bit width out of range.");
+ return int32_t(X << (32 - B)) >> (32 - B);
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
+/// Requires 0 < B < 32.
+inline int32_t SignExtend32(uint32_t X, unsigned B) {
+ assert(B > 0 && "Bit width can't be 0.");
+ assert(B <= 32 && "Bit width out of range.");
+ return int32_t(X << (32 - B)) >> (32 - B);
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
+/// Requires 0 < B < 64.
+template <unsigned B> constexpr inline int64_t SignExtend64(uint64_t x) {
+ static_assert(B > 0, "Bit width can't be 0.");
+ static_assert(B <= 64, "Bit width out of range.");
+ return int64_t(x << (64 - B)) >> (64 - B);
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
+/// Requires 0 < B < 64.
+inline int64_t SignExtend64(uint64_t X, unsigned B) {
+ assert(B > 0 && "Bit width can't be 0.");
+ assert(B <= 64 && "Bit width out of range.");
+ return int64_t(X << (64 - B)) >> (64 - B);
+}
+
+/// Subtract two unsigned integers, X and Y, of type T and return the absolute
+/// value of the result.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, T>::type
+AbsoluteDifference(T X, T Y) {
+ return std::max(X, Y) - std::min(X, Y);
+}
+
+/// Add two unsigned integers, X and Y, of type T. Clamp the result to the
+/// maximum representable value of T on overflow. ResultOverflowed indicates if
+/// the result is larger than the maximum representable value of type T.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, T>::type
+SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
+ bool Dummy;
+ bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
+ // Hacker's Delight, p. 29
+ T Z = X + Y;
+ Overflowed = (Z < X || Z < Y);
+ if (Overflowed)
+ return std::numeric_limits<T>::max();
+ else
+ return Z;
+}
+
+/// Multiply two unsigned integers, X and Y, of type T. Clamp the result to the
+/// maximum representable value of T on overflow. ResultOverflowed indicates if
+/// the result is larger than the maximum representable value of type T.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, T>::type
+SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
+ bool Dummy;
+ bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
+
+ // Hacker's Delight, p. 30 has a different algorithm, but we don't use that
+ // because it fails for uint16_t (where multiplication can have undefined
+ // behavior due to promotion to int), and requires a division in addition
+ // to the multiplication.
+
+ Overflowed = false;
+
+ // Log2(Z) would be either Log2Z or Log2Z + 1.
+ // Special case: if X or Y is 0, Log2_64 gives -1, and Log2Z
+ // will necessarily be less than Log2Max as desired.
+ int Log2Z = Log2_64(X) + Log2_64(Y);
+ const T Max = std::numeric_limits<T>::max();
+ int Log2Max = Log2_64(Max);
+ if (Log2Z < Log2Max) {
+ return X * Y;
+ }
+ if (Log2Z > Log2Max) {
+ Overflowed = true;
+ return Max;
+ }
+
+ // We're going to use the top bit, and maybe overflow one
+ // bit past it. Multiply all but the bottom bit then add
+ // that on at the end.
+ T Z = (X >> 1) * Y;
+ if (Z & ~(Max >> 1)) {
+ Overflowed = true;
+ return Max;
+ }
+ Z <<= 1;
+ if (X & 1)
+ return SaturatingAdd(Z, Y, ResultOverflowed);
+
+ return Z;
+}
+
+/// Multiply two unsigned integers, X and Y, and add the unsigned integer, A to
+/// the product. Clamp the result to the maximum representable value of T on
+/// overflow. ResultOverflowed indicates if the result is larger than the
+/// maximum representable value of type T.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, T>::type
+SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
+ bool Dummy;
+ bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
+
+ T Product = SaturatingMultiply(X, Y, &Overflowed);
+ if (Overflowed)
+ return Product;
+
+ return SaturatingAdd(A, Product, &Overflowed);
+}
+
+/// Use this rather than HUGE_VALF; the latter causes warnings on MSVC.
+extern const float huge_valf;
+
+
+/// Add two signed integers, computing the two's complement truncated result,
+/// returning true if overflow occured.
+template <typename T>
+typename std::enable_if<std::is_signed<T>::value, T>::type
+AddOverflow(T X, T Y, T &Result) {
+#if __has_builtin(__builtin_add_overflow)
+ return __builtin_add_overflow(X, Y, &Result);
+#else
+ // Perform the unsigned addition.
+ using U = typename std::make_unsigned<T>::type;
+ const U UX = static_cast<U>(X);
+ const U UY = static_cast<U>(Y);
+ const U UResult = UX + UY;
+
+ // Convert to signed.
+ Result = static_cast<T>(UResult);
+
+ // Adding two positive numbers should result in a positive number.
+ if (X > 0 && Y > 0)
+ return Result <= 0;
+ // Adding two negatives should result in a negative number.
+ if (X < 0 && Y < 0)
+ return Result >= 0;
+ return false;
+#endif
+}
+
+/// Subtract two signed integers, computing the two's complement truncated
+/// result, returning true if an overflow ocurred.
+template <typename T>
+typename std::enable_if<std::is_signed<T>::value, T>::type
+SubOverflow(T X, T Y, T &Result) {
+#if __has_builtin(__builtin_sub_overflow)
+ return __builtin_sub_overflow(X, Y, &Result);
+#else
+ // Perform the unsigned addition.
+ using U = typename std::make_unsigned<T>::type;
+ const U UX = static_cast<U>(X);
+ const U UY = static_cast<U>(Y);
+ const U UResult = UX - UY;
+
+ // Convert to signed.
+ Result = static_cast<T>(UResult);
+
+ // Subtracting a positive number from a negative results in a negative number.
+ if (X <= 0 && Y > 0)
+ return Result >= 0;
+ // Subtracting a negative number from a positive results in a positive number.
+ if (X >= 0 && Y < 0)
+ return Result <= 0;
+ return false;
+#endif
+}
+
+
+/// Multiply two signed integers, computing the two's complement truncated
+/// result, returning true if an overflow ocurred.
+template <typename T>
+typename std::enable_if<std::is_signed<T>::value, T>::type
+MulOverflow(T X, T Y, T &Result) {
+ // Perform the unsigned multiplication on absolute values.
+ using U = typename std::make_unsigned<T>::type;
+ const U UX = X < 0 ? (0 - static_cast<U>(X)) : static_cast<U>(X);
+ const U UY = Y < 0 ? (0 - static_cast<U>(Y)) : static_cast<U>(Y);
+ const U UResult = UX * UY;
+
+ // Convert to signed.
+ const bool IsNegative = (X < 0) ^ (Y < 0);
+ Result = IsNegative ? (0 - UResult) : UResult;
+
+ // If any of the args was 0, result is 0 and no overflow occurs.
+ if (UX == 0 || UY == 0)
+ return false;
+
+ // UX and UY are in [1, 2^n], where n is the number of digits.
+ // Check how the max allowed absolute value (2^n for negative, 2^(n-1) for
+ // positive) divided by an argument compares to the other.
+ if (IsNegative)
+ return UX > (static_cast<U>(std::numeric_limits<T>::max()) + U(1)) / UY;
+ else
+ return UX > (static_cast<U>(std::numeric_limits<T>::max())) / UY;
+}
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/MemAlloc.h b/third_party/llvm-project/include/llvm/Support/MemAlloc.h
new file mode 100644
index 000000000..0e5869141
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/MemAlloc.h
@@ -0,0 +1,66 @@
+//===- MemAlloc.h - Memory allocation functions -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines counterparts of C library allocation functions defined in
+/// the namespace 'std'. The new allocation functions crash on allocation
+/// failure instead of returning null pointer.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MEMALLOC_H
+#define LLVM_SUPPORT_MEMALLOC_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cstdlib>
+
+namespace llvm {
+
+LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_malloc(size_t Sz) {
+ void *Result = std::malloc(Sz);
+ 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) {
+ // 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) {
+ // 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;
+}
+
+}
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/MemoryBuffer.h b/third_party/llvm-project/include/llvm/Support/MemoryBuffer.h
new file mode 100644
index 000000000..b5196cd84
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/MemoryBuffer.h
@@ -0,0 +1,286 @@
+//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the MemoryBuffer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MEMORYBUFFER_H
+#define LLVM_SUPPORT_MEMORYBUFFER_H
+
+#include "llvm-c/Types.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+
+namespace llvm {
+
+class MemoryBufferRef;
+
+/// This interface provides simple read-only access to a block of memory, and
+/// provides simple methods for reading files and standard input into a memory
+/// buffer. In addition to basic access to the characters in the file, this
+/// interface guarantees you can read one character past the end of the file,
+/// and that this character will read as '\0'.
+///
+/// The '\0' guarantee is needed to support an optimization -- it's intended to
+/// be more efficient for clients which are reading all the data to stop
+/// reading when they encounter a '\0' than to continually check the file
+/// position to see if it has reached the end of the file.
+class MemoryBuffer {
+ const char *BufferStart; // Start of the buffer.
+ const char *BufferEnd; // End of the buffer.
+
+protected:
+ MemoryBuffer() = default;
+
+ void init(const char *BufStart, const char *BufEnd,
+ bool RequiresNullTerminator);
+
+ static constexpr sys::fs::mapped_file_region::mapmode Mapmode =
+ sys::fs::mapped_file_region::readonly;
+
+public:
+ MemoryBuffer(const MemoryBuffer &) = delete;
+ MemoryBuffer &operator=(const MemoryBuffer &) = delete;
+ virtual ~MemoryBuffer();
+
+ const char *getBufferStart() const { return BufferStart; }
+ const char *getBufferEnd() const { return BufferEnd; }
+ size_t getBufferSize() const { return BufferEnd-BufferStart; }
+
+ StringRef getBuffer() const {
+ return StringRef(BufferStart, getBufferSize());
+ }
+
+ /// Return an identifier for this buffer, typically the filename it was read
+ /// from.
+ virtual StringRef getBufferIdentifier() const { return "Unknown buffer"; }
+
+ /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer
+ /// if successful, otherwise returning null. If FileSize is specified, this
+ /// means that the client knows that the file exists and that it has the
+ /// specified size.
+ ///
+ /// \param IsVolatile Set to true to indicate that the contents of the file
+ /// 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>>
+ getFile(const Twine &Filename, int64_t FileSize = -1,
+ bool RequiresNullTerminator = true, bool IsVolatile = false);
+
+ /// Read all of the specified file into a MemoryBuffer as a stream
+ /// (i.e. until EOF reached). This is useful for special files that
+ /// look like a regular file but have 0 size (e.g. /proc/cpuinfo on Linux).
+ static ErrorOr<std::unique_ptr<MemoryBuffer>>
+ getFileAsStream(const Twine &Filename);
+
+ /// Given an already-open file descriptor, map some slice of it into a
+ /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize.
+ /// Since this is in the middle of a file, the buffer is not null terminated.
+ static ErrorOr<std::unique_ptr<MemoryBuffer>>
+ 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
+ /// MemoryBuffer.
+ ///
+ /// \param IsVolatile Set to true to indicate that the contents of the file
+ /// 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(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
+ /// must be null terminated if RequiresNullTerminator is true.
+ static std::unique_ptr<MemoryBuffer>
+ getMemBuffer(StringRef InputData, StringRef BufferName = "",
+ bool RequiresNullTerminator = true);
+
+ static std::unique_ptr<MemoryBuffer>
+ getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true);
+
+ /// Open the specified memory range as a MemoryBuffer, copying the contents
+ /// and taking ownership of it. InputData does not have to be null terminated.
+ static std::unique_ptr<MemoryBuffer>
+ getMemBufferCopy(StringRef InputData, const Twine &BufferName = "");
+
+ /// Read all of stdin into a file buffer, and return it.
+ static ErrorOr<std::unique_ptr<MemoryBuffer>> getSTDIN();
+
+ /// Open the specified file as a MemoryBuffer, or open stdin if the Filename
+ /// is "-".
+ static ErrorOr<std::unique_ptr<MemoryBuffer>>
+ getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1,
+ bool RequiresNullTerminator = true);
+
+ /// Map a subrange of the specified file as a MemoryBuffer.
+ static ErrorOr<std::unique_ptr<MemoryBuffer>>
+ getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset,
+ bool IsVolatile = false);
+
+ //===--------------------------------------------------------------------===//
+ // Provided for performance analysis.
+ //===--------------------------------------------------------------------===//
+
+ /// The kind of memory backing used to support the MemoryBuffer.
+ enum BufferKind {
+ MemoryBuffer_Malloc,
+ MemoryBuffer_MMap
+ };
+
+ /// Return information on the memory mechanism used to support the
+ /// MemoryBuffer.
+ virtual BufferKind getBufferKind() const = 0;
+
+ MemoryBufferRef getMemBufferRef() const;
+};
+
+/// This class is an extension of MemoryBuffer, which allows copy-on-write
+/// access to the underlying contents. It only supports creation methods that
+/// are guaranteed to produce a writable buffer. For example, mapping a file
+/// read-only is not supported.
+class WritableMemoryBuffer : public MemoryBuffer {
+protected:
+ WritableMemoryBuffer() = default;
+
+ static constexpr sys::fs::mapped_file_region::mapmode Mapmode =
+ sys::fs::mapped_file_region::priv;
+
+public:
+ using MemoryBuffer::getBuffer;
+ using MemoryBuffer::getBufferEnd;
+ using MemoryBuffer::getBufferStart;
+
+ // const_cast is well-defined here, because the underlying buffer is
+ // guaranteed to have been initialized with a mutable buffer.
+ char *getBufferStart() {
+ return const_cast<char *>(MemoryBuffer::getBufferStart());
+ }
+ char *getBufferEnd() {
+ return const_cast<char *>(MemoryBuffer::getBufferEnd());
+ }
+ MutableArrayRef<char> getBuffer() {
+ return {getBufferStart(), getBufferEnd()};
+ }
+
+ static ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
+ getFile(const Twine &Filename, int64_t FileSize = -1,
+ bool IsVolatile = false);
+
+ /// Map a subrange of the specified file as a WritableMemoryBuffer.
+ static ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
+ getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset,
+ bool IsVolatile = false);
+
+ /// Allocate a new MemoryBuffer of the specified size that is not initialized.
+ /// Note that the caller should initialize the memory allocated by this
+ /// method. The memory is owned by the MemoryBuffer object.
+ static std::unique_ptr<WritableMemoryBuffer>
+ getNewUninitMemBuffer(size_t Size, const Twine &BufferName = "");
+
+ /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note
+ /// that the caller need not initialize the memory allocated by this method.
+ /// The memory is owned by the MemoryBuffer object.
+ static std::unique_ptr<WritableMemoryBuffer>
+ getNewMemBuffer(size_t Size, const Twine &BufferName = "");
+
+private:
+ // Hide these base class factory function so one can't write
+ // WritableMemoryBuffer::getXXX()
+ // and be surprised that he got a read-only Buffer.
+ using MemoryBuffer::getFileAsStream;
+ using MemoryBuffer::getFileOrSTDIN;
+ using MemoryBuffer::getMemBuffer;
+ using MemoryBuffer::getMemBufferCopy;
+ using MemoryBuffer::getOpenFile;
+ using MemoryBuffer::getOpenFileSlice;
+ using MemoryBuffer::getSTDIN;
+};
+
+/// This class is an extension of MemoryBuffer, which allows write access to
+/// the underlying contents and committing those changes to the original source.
+/// It only supports creation methods that are guaranteed to produce a writable
+/// buffer. For example, mapping a file read-only is not supported.
+class WriteThroughMemoryBuffer : public MemoryBuffer {
+protected:
+ WriteThroughMemoryBuffer() = default;
+
+ static constexpr sys::fs::mapped_file_region::mapmode Mapmode =
+ sys::fs::mapped_file_region::readwrite;
+
+public:
+ using MemoryBuffer::getBuffer;
+ using MemoryBuffer::getBufferEnd;
+ using MemoryBuffer::getBufferStart;
+
+ // const_cast is well-defined here, because the underlying buffer is
+ // guaranteed to have been initialized with a mutable buffer.
+ char *getBufferStart() {
+ return const_cast<char *>(MemoryBuffer::getBufferStart());
+ }
+ char *getBufferEnd() {
+ return const_cast<char *>(MemoryBuffer::getBufferEnd());
+ }
+ MutableArrayRef<char> getBuffer() {
+ return {getBufferStart(), getBufferEnd()};
+ }
+
+ static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
+ getFile(const Twine &Filename, int64_t FileSize = -1);
+
+ /// Map a subrange of the specified file as a ReadWriteMemoryBuffer.
+ static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
+ getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset);
+
+private:
+ // Hide these base class factory function so one can't write
+ // WritableMemoryBuffer::getXXX()
+ // and be surprised that he got a read-only Buffer.
+ using MemoryBuffer::getFileAsStream;
+ using MemoryBuffer::getFileOrSTDIN;
+ using MemoryBuffer::getMemBuffer;
+ using MemoryBuffer::getMemBufferCopy;
+ using MemoryBuffer::getOpenFile;
+ using MemoryBuffer::getOpenFileSlice;
+ using MemoryBuffer::getSTDIN;
+};
+
+class MemoryBufferRef {
+ StringRef Buffer;
+ StringRef Identifier;
+
+public:
+ MemoryBufferRef() = default;
+ MemoryBufferRef(const MemoryBuffer& Buffer)
+ : Buffer(Buffer.getBuffer()), Identifier(Buffer.getBufferIdentifier()) {}
+ MemoryBufferRef(StringRef Buffer, StringRef Identifier)
+ : Buffer(Buffer), Identifier(Identifier) {}
+
+ StringRef getBuffer() const { return Buffer; }
+
+ StringRef getBufferIdentifier() const { return Identifier; }
+
+ const char *getBufferStart() const { return Buffer.begin(); }
+ const char *getBufferEnd() const { return Buffer.end(); }
+ size_t getBufferSize() const { return Buffer.size(); }
+};
+
+// Create wrappers for C Binding types (see CBindingWrapping.h).
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef)
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_MEMORYBUFFER_H
diff --git a/third_party/llvm-project/include/llvm/Support/NativeFormatting.h b/third_party/llvm-project/include/llvm/Support/NativeFormatting.h
new file mode 100644
index 000000000..825a44c77
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/NativeFormatting.h
@@ -0,0 +1,48 @@
+//===- NativeFormatting.h - Low level formatting helpers ---------*- 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_NATIVE_FORMATTING_H
+#define LLVM_SUPPORT_NATIVE_FORMATTING_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <cstdint>
+
+namespace llvm {
+enum class FloatStyle { Exponent, ExponentUpper, Fixed, Percent };
+enum class IntegerStyle {
+ Integer,
+ Number,
+};
+enum class HexPrintStyle { Upper, Lower, PrefixUpper, PrefixLower };
+
+size_t getDefaultPrecision(FloatStyle Style);
+
+bool isPrefixedHexStyle(HexPrintStyle S);
+
+void write_integer(raw_ostream &S, unsigned int N, size_t MinDigits,
+ IntegerStyle Style);
+void write_integer(raw_ostream &S, int N, size_t MinDigits, IntegerStyle Style);
+void write_integer(raw_ostream &S, unsigned long N, size_t MinDigits,
+ IntegerStyle Style);
+void write_integer(raw_ostream &S, long N, size_t MinDigits,
+ IntegerStyle Style);
+void write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits,
+ IntegerStyle Style);
+void write_integer(raw_ostream &S, long long N, size_t MinDigits,
+ IntegerStyle Style);
+
+void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
+ Optional<size_t> Width = None);
+void write_double(raw_ostream &S, double D, FloatStyle Style,
+ Optional<size_t> Precision = None);
+}
+
+#endif
+
diff --git a/third_party/llvm-project/include/llvm/Support/Path.h b/third_party/llvm-project/include/llvm/Support/Path.h
new file mode 100644
index 000000000..488f17427
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Path.h
@@ -0,0 +1,464 @@
+//===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the llvm::sys::path namespace. It is designed after
+// TR2/boost filesystem (v3), but modified to remove exception handling and the
+// path class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_PATH_H
+#define LLVM_SUPPORT_PATH_H
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/DataTypes.h"
+#include <iterator>
+#include <system_error>
+
+namespace llvm {
+namespace sys {
+namespace path {
+
+enum class Style { windows, posix, native };
+
+/// @name Lexical Component Iterator
+/// @{
+
+/// Path iterator.
+///
+/// This is an input iterator that iterates over the individual components in
+/// \a path. The traversal order is as follows:
+/// * The root-name element, if present.
+/// * The root-directory element, if present.
+/// * Each successive filename element, if present.
+/// * Dot, if one or more trailing non-root slash characters are present.
+/// Traversing backwards is possible with \a reverse_iterator
+///
+/// Iteration examples. Each component is separated by ',':
+/// @code
+/// / => /
+/// /foo => /,foo
+/// foo/ => foo,.
+/// /foo/bar => /,foo,bar
+/// ../ => ..,.
+/// C:\foo\bar => C:,/,foo,bar
+/// @endcode
+class const_iterator
+ : public iterator_facade_base<const_iterator, std::input_iterator_tag,
+ const StringRef> {
+ StringRef Path; ///< The entire path.
+ StringRef Component; ///< The current component. Not necessarily in Path.
+ size_t Position = 0; ///< The iterators current position within Path.
+ Style S = Style::native; ///< The path style to use.
+
+ // An end iterator has Position = Path.size() + 1.
+ friend const_iterator begin(StringRef path, Style style);
+ friend const_iterator end(StringRef path);
+
+public:
+ reference operator*() const { return Component; }
+ const_iterator &operator++(); // preincrement
+ bool operator==(const const_iterator &RHS) const;
+
+ /// Difference in bytes between this and RHS.
+ ptrdiff_t operator-(const const_iterator &RHS) const;
+};
+
+/// Reverse path iterator.
+///
+/// This is an input iterator that iterates over the individual components in
+/// \a path in reverse order. The traversal order is exactly reversed from that
+/// of \a const_iterator
+class reverse_iterator
+ : public iterator_facade_base<reverse_iterator, std::input_iterator_tag,
+ const StringRef> {
+ StringRef Path; ///< The entire path.
+ StringRef Component; ///< The current component. Not necessarily in Path.
+ size_t Position = 0; ///< The iterators current position within Path.
+ Style S = Style::native; ///< The path style to use.
+
+ friend reverse_iterator rbegin(StringRef path, Style style);
+ friend reverse_iterator rend(StringRef path);
+
+public:
+ reference operator*() const { return Component; }
+ reverse_iterator &operator++(); // preincrement
+ bool operator==(const reverse_iterator &RHS) const;
+
+ /// Difference in bytes between this and RHS.
+ ptrdiff_t operator-(const reverse_iterator &RHS) const;
+};
+
+/// Get begin iterator over \a path.
+/// @param path Input path.
+/// @returns Iterator initialized with the first component of \a path.
+const_iterator begin(StringRef path, Style style = Style::native);
+
+/// Get end iterator over \a path.
+/// @param path Input path.
+/// @returns Iterator initialized to the end of \a path.
+const_iterator end(StringRef path);
+
+/// Get reverse begin iterator over \a path.
+/// @param path Input path.
+/// @returns Iterator initialized with the first reverse component of \a path.
+reverse_iterator rbegin(StringRef path, Style style = Style::native);
+
+/// Get reverse end iterator over \a path.
+/// @param path Input path.
+/// @returns Iterator initialized to the reverse end of \a path.
+reverse_iterator rend(StringRef path);
+
+/// @}
+/// @name Lexical Modifiers
+/// @{
+
+/// Remove the last component from \a path unless it is the root dir.
+///
+/// Similar to the POSIX "dirname" utility.
+///
+/// @code
+/// directory/filename.cpp => directory/
+/// directory/ => directory
+/// filename.cpp => <empty>
+/// / => /
+/// @endcode
+///
+/// @param path A path that is modified to not have a file component.
+void remove_filename(SmallVectorImpl<char> &path, Style style = Style::native);
+
+/// Replace the file extension of \a path with \a extension.
+///
+/// @code
+/// ./filename.cpp => ./filename.extension
+/// ./filename => ./filename.extension
+/// ./ => ./.extension
+/// @endcode
+///
+/// @param path A path that has its extension replaced with \a extension.
+/// @param extension The extension to be added. It may be empty. It may also
+/// optionally start with a '.', if it does not, one will be
+/// prepended.
+void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
+ Style style = Style::native);
+
+/// Replace matching path prefix with another path.
+///
+/// @code
+/// /foo, /old, /new => /foo
+/// /old/foo, /old, /new => /new/foo
+/// /foo, <empty>, /new => /new/foo
+/// /old/foo, /old, <empty> => /foo
+/// @endcode
+///
+/// @param Path If \a Path starts with \a OldPrefix modify to instead
+/// start with \a NewPrefix.
+/// @param OldPrefix The path prefix to strip from \a Path.
+/// @param NewPrefix The path prefix to replace \a NewPrefix with.
+void replace_path_prefix(SmallVectorImpl<char> &Path,
+ const StringRef &OldPrefix, const StringRef &NewPrefix,
+ Style style = Style::native);
+
+/// Append to path.
+///
+/// @code
+/// /foo + bar/f => /foo/bar/f
+/// /foo/ + bar/f => /foo/bar/f
+/// foo + bar/f => foo/bar/f
+/// @endcode
+///
+/// @param path Set to \a path + \a component.
+/// @param a The component to be appended to \a path.
+void append(SmallVectorImpl<char> &path, const Twine &a,
+ const Twine &b = "",
+ const Twine &c = "",
+ const Twine &d = "");
+
+void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
+ const Twine &b = "", const Twine &c = "", const Twine &d = "");
+
+/// Append to path.
+///
+/// @code
+/// /foo + [bar,f] => /foo/bar/f
+/// /foo/ + [bar,f] => /foo/bar/f
+/// foo + [bar,f] => foo/bar/f
+/// @endcode
+///
+/// @param path Set to \a path + [\a begin, \a end).
+/// @param begin Start of components to append.
+/// @param end One past the end of components to append.
+void append(SmallVectorImpl<char> &path, const_iterator begin,
+ const_iterator end, Style style = Style::native);
+
+/// @}
+/// @name Transforms (or some other better name)
+/// @{
+
+/// Convert path to the native form. This is used to give paths to users and
+/// operating system calls in the platform's normal way. For example, on Windows
+/// all '/' are converted to '\'.
+///
+/// @param path A path that is transformed to native format.
+/// @param result Holds the result of the transformation.
+void native(const Twine &path, SmallVectorImpl<char> &result,
+ Style style = Style::native);
+
+/// Convert path to the native form in place. This is used to give paths to
+/// users and operating system calls in the platform's normal way. For example,
+/// on Windows all '/' are converted to '\'.
+///
+/// @param path A path that is transformed to native format.
+void native(SmallVectorImpl<char> &path, Style style = Style::native);
+
+/// Replaces backslashes with slashes if Windows.
+///
+/// @param path processed path
+/// @result The result of replacing backslashes with forward slashes if Windows.
+/// On Unix, this function is a no-op because backslashes are valid path
+/// chracters.
+std::string convert_to_slash(StringRef path, Style style = Style::native);
+
+/// @}
+/// @name Lexical Observers
+/// @{
+
+/// Get root name.
+///
+/// @code
+/// //net/hello => //net
+/// c:/hello => c: (on Windows, on other platforms nothing)
+/// /hello => <empty>
+/// @endcode
+///
+/// @param path Input path.
+/// @result The root name of \a path if it has one, otherwise "".
+StringRef root_name(StringRef path, Style style = Style::native);
+
+/// Get root directory.
+///
+/// @code
+/// /goo/hello => /
+/// c:/hello => /
+/// d/file.txt => <empty>
+/// @endcode
+///
+/// @param path Input path.
+/// @result The root directory of \a path if it has one, otherwise
+/// "".
+StringRef root_directory(StringRef path, Style style = Style::native);
+
+/// Get root path.
+///
+/// Equivalent to root_name + root_directory.
+///
+/// @param path Input path.
+/// @result The root path of \a path if it has one, otherwise "".
+StringRef root_path(StringRef path, Style style = Style::native);
+
+/// Get relative path.
+///
+/// @code
+/// C:\hello\world => hello\world
+/// foo/bar => foo/bar
+/// /foo/bar => foo/bar
+/// @endcode
+///
+/// @param path Input path.
+/// @result The path starting after root_path if one exists, otherwise "".
+StringRef relative_path(StringRef path, Style style = Style::native);
+
+/// Get parent path.
+///
+/// @code
+/// / => <empty>
+/// /foo => /
+/// foo/../bar => foo/..
+/// @endcode
+///
+/// @param path Input path.
+/// @result The parent path of \a path if one exists, otherwise "".
+StringRef parent_path(StringRef path, Style style = Style::native);
+
+/// Get filename.
+///
+/// @code
+/// /foo.txt => foo.txt
+/// . => .
+/// .. => ..
+/// / => /
+/// @endcode
+///
+/// @param path Input path.
+/// @result The filename part of \a path. This is defined as the last component
+/// of \a path. Similar to the POSIX "basename" utility.
+StringRef filename(StringRef path, Style style = Style::native);
+
+/// Get stem.
+///
+/// If filename contains a dot but not solely one or two dots, result is the
+/// substring of filename ending at (but not including) the last dot. Otherwise
+/// it is filename.
+///
+/// @code
+/// /foo/bar.txt => bar
+/// /foo/bar => bar
+/// /foo/.txt => <empty>
+/// /foo/. => .
+/// /foo/.. => ..
+/// @endcode
+///
+/// @param path Input path.
+/// @result The stem of \a path.
+StringRef stem(StringRef path, Style style = Style::native);
+
+/// Get extension.
+///
+/// If filename contains a dot but not solely one or two dots, result is the
+/// substring of filename starting at (and including) the last dot, and ending
+/// at the end of \a path. Otherwise "".
+///
+/// @code
+/// /foo/bar.txt => .txt
+/// /foo/bar => <empty>
+/// /foo/.txt => .txt
+/// @endcode
+///
+/// @param path Input path.
+/// @result The extension of \a path.
+StringRef extension(StringRef path, Style style = Style::native);
+
+/// Check whether the given char is a path separator on the host OS.
+///
+/// @param value a character
+/// @result true if \a value is a path separator character on the host OS
+bool is_separator(char value, Style style = Style::native);
+
+/// Return the preferred separator for this platform.
+///
+/// @result StringRef of the preferred separator, null-terminated.
+StringRef get_separator(Style style = Style::native);
+
+/// Get the typical temporary directory for the system, e.g.,
+/// "/var/tmp" or "C:/TEMP"
+///
+/// @param erasedOnReboot Whether to favor a path that is erased on reboot
+/// rather than one that potentially persists longer. This parameter will be
+/// ignored if the user or system has set the typical environment variable
+/// (e.g., TEMP on Windows, TMPDIR on *nix) to specify a temporary directory.
+///
+/// @param result Holds the resulting path name.
+void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result);
+
+/// Get the user's home directory.
+///
+/// @param result Holds the resulting path name.
+/// @result True if a home directory is set, false otherwise.
+bool home_directory(SmallVectorImpl<char> &result);
+
+/// Has root name?
+///
+/// root_name != ""
+///
+/// @param path Input path.
+/// @result True if the path has a root name, false otherwise.
+bool has_root_name(const Twine &path, Style style = Style::native);
+
+/// Has root directory?
+///
+/// root_directory != ""
+///
+/// @param path Input path.
+/// @result True if the path has a root directory, false otherwise.
+bool has_root_directory(const Twine &path, Style style = Style::native);
+
+/// Has root path?
+///
+/// root_path != ""
+///
+/// @param path Input path.
+/// @result True if the path has a root path, false otherwise.
+bool has_root_path(const Twine &path, Style style = Style::native);
+
+/// Has relative path?
+///
+/// relative_path != ""
+///
+/// @param path Input path.
+/// @result True if the path has a relative path, false otherwise.
+bool has_relative_path(const Twine &path, Style style = Style::native);
+
+/// Has parent path?
+///
+/// parent_path != ""
+///
+/// @param path Input path.
+/// @result True if the path has a parent path, false otherwise.
+bool has_parent_path(const Twine &path, Style style = Style::native);
+
+/// Has filename?
+///
+/// filename != ""
+///
+/// @param path Input path.
+/// @result True if the path has a filename, false otherwise.
+bool has_filename(const Twine &path, Style style = Style::native);
+
+/// Has stem?
+///
+/// stem != ""
+///
+/// @param path Input path.
+/// @result True if the path has a stem, false otherwise.
+bool has_stem(const Twine &path, Style style = Style::native);
+
+/// Has extension?
+///
+/// extension != ""
+///
+/// @param path Input path.
+/// @result True if the path has a extension, false otherwise.
+bool has_extension(const Twine &path, Style style = Style::native);
+
+/// Is path absolute?
+///
+/// @param path Input path.
+/// @result True if the path is absolute, false if it is not.
+bool is_absolute(const Twine &path, Style style = Style::native);
+
+/// Is path relative?
+///
+/// @param path Input path.
+/// @result True if the path is relative, false if it is not.
+bool is_relative(const Twine &path, Style style = Style::native);
+
+/// Remove redundant leading "./" pieces and consecutive separators.
+///
+/// @param path Input path.
+/// @result The cleaned-up \a path.
+StringRef remove_leading_dotslash(StringRef path, Style style = Style::native);
+
+/// In-place remove any './' and optionally '../' components from a path.
+///
+/// @param path processed path
+/// @param remove_dot_dot specify if '../' (except for leading "../") should be
+/// removed
+/// @result True if path was changed
+bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot = false,
+ Style style = Style::native);
+
+#if defined(_WIN32)
+std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16);
+#endif
+
+} // end namespace path
+} // end namespace sys
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/PointerLikeTypeTraits.h b/third_party/llvm-project/include/llvm/Support/PointerLikeTypeTraits.h
new file mode 100644
index 000000000..1e7e5b53c
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/PointerLikeTypeTraits.h
@@ -0,0 +1,149 @@
+//===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PointerLikeTypeTraits class. This allows data
+// structures to reason about pointers and other things that are pointer sized.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
+#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
+
+#include "llvm/Support/DataTypes.h"
+#include <assert.h>
+#include <type_traits>
+
+namespace llvm {
+
+/// A traits type that is used to handle pointer types and things that are just
+/// wrappers for pointers as a uniform entity.
+template <typename T> struct PointerLikeTypeTraits;
+
+namespace detail {
+/// A tiny meta function to compute the log2 of a compile time constant.
+template <size_t N>
+struct ConstantLog2
+ : std::integral_constant<size_t, ConstantLog2<N / 2>::value + 1> {};
+template <> struct ConstantLog2<1> : std::integral_constant<size_t, 0> {};
+
+// Provide a trait to check if T is pointer-like.
+template <typename T, typename U = void> struct HasPointerLikeTypeTraits {
+ static const bool value = false;
+};
+
+// sizeof(T) is valid only for a complete T.
+template <typename T> struct HasPointerLikeTypeTraits<
+ T, decltype((sizeof(PointerLikeTypeTraits<T>) + sizeof(T)), void())> {
+ static const bool value = true;
+};
+
+template <typename T> struct IsPointerLike {
+ static const bool value = HasPointerLikeTypeTraits<T>::value;
+};
+
+template <typename T> struct IsPointerLike<T *> {
+ static const bool value = true;
+};
+} // namespace detail
+
+// Provide PointerLikeTypeTraits for non-cvr pointers.
+template <typename T> struct PointerLikeTypeTraits<T *> {
+ static inline void *getAsVoidPointer(T *P) { return P; }
+ static inline T *getFromVoidPointer(void *P) { return static_cast<T *>(P); }
+
+ enum { NumLowBitsAvailable = detail::ConstantLog2<alignof(T)>::value };
+};
+
+template <> struct PointerLikeTypeTraits<void *> {
+ static inline void *getAsVoidPointer(void *P) { return P; }
+ static inline void *getFromVoidPointer(void *P) { return P; }
+
+ /// Note, we assume here that void* is related to raw malloc'ed memory and
+ /// that malloc returns objects at least 4-byte aligned. However, this may be
+ /// wrong, or pointers may be from something other than malloc. In this case,
+ /// you should specify a real typed pointer or avoid this template.
+ ///
+ /// All clients should use assertions to do a run-time check to ensure that
+ /// this is actually true.
+ enum { NumLowBitsAvailable = 2 };
+};
+
+// Provide PointerLikeTypeTraits for const things.
+template <typename T> struct PointerLikeTypeTraits<const T> {
+ typedef PointerLikeTypeTraits<T> NonConst;
+
+ static inline const void *getAsVoidPointer(const T P) {
+ return NonConst::getAsVoidPointer(P);
+ }
+ static inline const T getFromVoidPointer(const void *P) {
+ return NonConst::getFromVoidPointer(const_cast<void *>(P));
+ }
+ enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable };
+};
+
+// Provide PointerLikeTypeTraits for const pointers.
+template <typename T> struct PointerLikeTypeTraits<const T *> {
+ typedef PointerLikeTypeTraits<T *> NonConst;
+
+ static inline const void *getAsVoidPointer(const T *P) {
+ return NonConst::getAsVoidPointer(const_cast<T *>(P));
+ }
+ static inline const T *getFromVoidPointer(const void *P) {
+ return NonConst::getFromVoidPointer(const_cast<void *>(P));
+ }
+ enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable };
+};
+
+// Provide PointerLikeTypeTraits for uintptr_t.
+template <> struct PointerLikeTypeTraits<uintptr_t> {
+ static inline void *getAsVoidPointer(uintptr_t P) {
+ return reinterpret_cast<void *>(P);
+ }
+ static inline uintptr_t getFromVoidPointer(void *P) {
+ return reinterpret_cast<uintptr_t>(P);
+ }
+ // No bits are available!
+ enum { NumLowBitsAvailable = 0 };
+};
+
+/// Provide suitable custom traits struct for function pointers.
+///
+/// Function pointers can't be directly given these traits as functions can't
+/// have their alignment computed with `alignof` and we need different casting.
+///
+/// To rely on higher alignment for a specialized use, you can provide a
+/// customized form of this template explicitly with higher alignment, and
+/// potentially use alignment attributes on functions to satisfy that.
+template <int Alignment, typename FunctionPointerT>
+struct FunctionPointerLikeTypeTraits {
+ enum { NumLowBitsAvailable = detail::ConstantLog2<Alignment>::value };
+ static inline void *getAsVoidPointer(FunctionPointerT P) {
+ assert((reinterpret_cast<uintptr_t>(P) &
+ ~((uintptr_t)-1 << NumLowBitsAvailable)) == 0 &&
+ "Alignment not satisfied for an actual function pointer!");
+ return reinterpret_cast<void *>(P);
+ }
+ static inline FunctionPointerT getFromVoidPointer(void *P) {
+ return reinterpret_cast<FunctionPointerT>(P);
+ }
+};
+
+/// Provide a default specialization for function pointers that assumes 4-byte
+/// alignment.
+///
+/// We assume here that functions used with this are always at least 4-byte
+/// aligned. This means that, for example, thumb functions won't work or systems
+/// with weird unaligned function pointers won't work. But all practical systems
+/// we support satisfy this requirement.
+template <typename ReturnT, typename... ParamTs>
+struct PointerLikeTypeTraits<ReturnT (*)(ParamTs...)>
+ : FunctionPointerLikeTypeTraits<4, ReturnT (*)(ParamTs...)> {};
+
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/Printable.h b/third_party/llvm-project/include/llvm/Support/Printable.h
new file mode 100644
index 000000000..0f8670d04
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Printable.h
@@ -0,0 +1,51 @@
+//===--- Printable.h - Print function helpers -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Printable struct.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_PRINTABLE_H
+#define LLVM_SUPPORT_PRINTABLE_H
+
+#include <functional>
+
+namespace llvm {
+
+class raw_ostream;
+
+/// Simple wrapper around std::function<void(raw_ostream&)>.
+/// This class is useful to construct print helpers for raw_ostream.
+///
+/// Example:
+/// Printable PrintRegister(unsigned Register) {
+/// return Printable([Register](raw_ostream &OS) {
+/// OS << getRegisterName(Register);
+/// }
+/// }
+/// ... OS << PrintRegister(Register); ...
+///
+/// Implementation note: Ideally this would just be a typedef, but doing so
+/// leads to operator << being ambiguous as function has matching constructors
+/// in some STL versions. I have seen the problem on gcc 4.6 libstdc++ and
+/// microsoft STL.
+class Printable {
+public:
+ std::function<void(raw_ostream &OS)> Print;
+ Printable(std::function<void(raw_ostream &OS)> Print)
+ : Print(std::move(Print)) {}
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const Printable &P) {
+ P.Print(OS);
+ return OS;
+}
+
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/Process.h b/third_party/llvm-project/include/llvm/Support/Process.h
new file mode 100644
index 000000000..67e379125
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Process.h
@@ -0,0 +1,209 @@
+//===- llvm/Support/Process.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// Provides a library for accessing information about this process and other
+/// processes on the operating system. Also provides means of spawning
+/// subprocess for commands. The design of this library is modeled after the
+/// proposed design of the Boost.Process library, and is design specifically to
+/// follow the style of standard libraries and potentially become a proposal
+/// for a standard library.
+///
+/// This file declares the llvm::sys::Process class which contains a collection
+/// of legacy static interfaces for extracting various information about the
+/// current process. The goal is to migrate users of this API over to the new
+/// interfaces.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_PROCESS_H
+#define LLVM_SUPPORT_PROCESS_H
+
+#include "llvm/ADT/Optional.h"
+#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 {
+template <typename T> class ArrayRef;
+class StringRef;
+
+namespace sys {
+
+
+/// A collection of legacy interfaces for querying information about the
+/// current executing process.
+class Process {
+public:
+ /// 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
+ /// by the process. This only counts the memory allocated via the malloc,
+ /// calloc and realloc functions and includes any "free" holes in the
+ /// allocated space.
+ static size_t GetMallocUsage();
+
+ /// This static function will set \p user_time to the amount of CPU time
+ /// spent in user (non-kernel) mode and \p sys_time to the amount of CPU
+ /// time spent in system (kernel) mode. If the operating system does not
+ /// support collection of these metrics, a zero duration will be for both
+ /// values.
+ /// \param elapsed Returns the system_clock::now() giving current time
+ /// \param user_time Returns the current amount of user time for the process
+ /// \param sys_time Returns the current amount of system time for the process
+ static void GetTimeUsage(TimePoint<> &elapsed,
+ std::chrono::nanoseconds &user_time,
+ std::chrono::nanoseconds &sys_time);
+
+ /// This function makes the necessary calls to the operating system to
+ /// prevent core files or any other kind of large memory dumps that can
+ /// occur when a program fails.
+ /// Prevent core file generation.
+ static void PreventCoreFiles();
+
+ /// true if PreventCoreFiles has been called, false otherwise.
+ static bool AreCoreFilesPrevented();
+
+ // This function returns the environment variable \arg name's value as a UTF-8
+ // string. \arg Name is assumed to be in UTF-8 encoding too.
+ static Optional<std::string> GetEnv(StringRef name);
+
+ /// This function searches for an existing file in the list of directories
+ /// in a PATH like environment variable, and returns the first file found,
+ /// according to the order of the entries in the PATH like environment
+ /// variable. If an ignore list is specified, then any folder which is in
+ /// the PATH like environment variable but is also in IgnoreList is not
+ /// considered.
+ static Optional<std::string> FindInEnvPath(StringRef EnvName,
+ StringRef FileName,
+ ArrayRef<std::string> IgnoreList);
+
+ static Optional<std::string> FindInEnvPath(StringRef EnvName,
+ StringRef FileName);
+
+ // This functions ensures that the standard file descriptors (input, output,
+ // and error) are properly mapped to a file descriptor before we use any of
+ // them. This should only be called by standalone programs, library
+ // components should not call this.
+ static std::error_code FixupStandardFileDescriptors();
+
+ // This function safely closes a file descriptor. It is not safe to retry
+ // close(2) when it returns with errno equivalent to EINTR; this is because
+ // *nixen cannot agree if the file descriptor is, in fact, closed when this
+ // occurs.
+ //
+ // N.B. Some operating systems, due to thread cancellation, cannot properly
+ // guarantee that it will or will not be closed one way or the other!
+ static std::error_code SafelyCloseFileDescriptor(int FD);
+
+ /// This function determines if the standard input is connected directly
+ /// to a user's input (keyboard probably), rather than coming from a file
+ /// or pipe.
+ static bool StandardInIsUserInput();
+
+ /// This function determines if the standard output is connected to a
+ /// "tty" or "console" window. That is, the output would be displayed to
+ /// the user rather than being put on a pipe or stored in a file.
+ static bool StandardOutIsDisplayed();
+
+ /// This function determines if the standard error is connected to a
+ /// "tty" or "console" window. That is, the output would be displayed to
+ /// the user rather than being put on a pipe or stored in a file.
+ static bool StandardErrIsDisplayed();
+
+ /// This function determines if the given file descriptor is connected to
+ /// a "tty" or "console" window. That is, the output would be displayed to
+ /// the user rather than being put on a pipe or stored in a file.
+ static bool FileDescriptorIsDisplayed(int fd);
+
+ /// This function determines if the given file descriptor is displayd and
+ /// supports colors.
+ static bool FileDescriptorHasColors(int fd);
+
+ /// This function determines the number of columns in the window
+ /// if standard output is connected to a "tty" or "console"
+ /// window. If standard output is not connected to a tty or
+ /// console, or if the number of columns cannot be determined,
+ /// this routine returns zero.
+ static unsigned StandardOutColumns();
+
+ /// This function determines the number of columns in the window
+ /// if standard error is connected to a "tty" or "console"
+ /// window. If standard error is not connected to a tty or
+ /// console, or if the number of columns cannot be determined,
+ /// this routine returns zero.
+ static unsigned StandardErrColumns();
+
+ /// This function determines whether the terminal connected to standard
+ /// output supports colors. If standard output is not connected to a
+ /// terminal, this function returns false.
+ static bool StandardOutHasColors();
+
+ /// This function determines whether the terminal connected to standard
+ /// error supports colors. If standard error is not connected to a
+ /// terminal, this function returns false.
+ static bool StandardErrHasColors();
+
+ /// Enables or disables whether ANSI escape sequences are used to output
+ /// colors. This only has an effect on Windows.
+ /// Note: Setting this option is not thread-safe and should only be done
+ /// during initialization.
+ static void UseANSIEscapeCodes(bool enable);
+
+ /// Whether changing colors requires the output to be flushed.
+ /// This is needed on systems that don't support escape sequences for
+ /// changing colors.
+ static bool ColorNeedsFlush();
+
+ /// This function returns the colorcode escape sequences.
+ /// If ColorNeedsFlush() is true then this function will change the colors
+ /// and return an empty escape sequence. In that case it is the
+ /// responsibility of the client to flush the output stream prior to
+ /// calling this function.
+ static const char *OutputColor(char c, bool bold, bool bg);
+
+ /// Same as OutputColor, but only enables the bold attribute.
+ static const char *OutputBold(bool bg);
+
+ /// This function returns the escape sequence to reverse forground and
+ /// background colors.
+ static const char *OutputReverse();
+
+ /// Resets the terminals colors, or returns an escape sequence to do so.
+ static const char *ResetColor();
+
+ /// Get the result of a process wide random number generator. The
+ /// generator will be automatically seeded in non-deterministic fashion.
+ static unsigned GetRandomNumber();
+};
+
+}
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/Program.h b/third_party/llvm-project/include/llvm/Support/Program.h
new file mode 100644
index 000000000..6b2315c5d
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Program.h
@@ -0,0 +1,208 @@
+//===- llvm/Support/Program.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 declares the llvm::sys::Program class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_PROGRAM_H
+#define LLVM_SUPPORT_PROGRAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/ErrorOr.h"
+#include <system_error>
+
+namespace llvm {
+namespace sys {
+
+ /// This is the OS-specific separator for PATH like environment variables:
+ // a colon on Unix or a semicolon on Windows.
+#if defined(LLVM_ON_UNIX)
+ const char EnvPathSeparator = ':';
+#elif defined (_WIN32)
+ const char EnvPathSeparator = ';';
+#endif
+
+#if defined(_WIN32)
+ typedef unsigned long procid_t; // Must match the type of DWORD on Windows.
+ typedef void *process_t; // Must match the type of HANDLE on Windows.
+#else
+ typedef pid_t procid_t;
+ typedef procid_t process_t;
+#endif
+
+ /// This struct encapsulates information about a process.
+ struct ProcessInfo {
+ enum : procid_t { InvalidPid = 0 };
+
+ procid_t Pid; /// The process identifier.
+ process_t Process; /// Platform-dependent process object.
+
+ /// The return code, set after execution.
+ int ReturnCode;
+
+ ProcessInfo();
+ };
+
+ /// Find the first executable file \p Name in \p Paths.
+ ///
+ /// This does not perform hashing as a shell would but instead stats each PATH
+ /// entry individually so should generally be avoided. Core LLVM library
+ /// functions and options should instead require fully specified paths.
+ ///
+ /// \param Name name of the executable to find. If it contains any system
+ /// slashes, it will be returned as is.
+ /// \param Paths optional list of paths to search for \p Name. If empty it
+ /// will use the system PATH environment instead.
+ ///
+ /// \returns The fully qualified path to the first \p Name in \p Paths if it
+ /// exists. \p Name if \p Name has slashes in it. Otherwise an error.
+ ErrorOr<std::string>
+ findProgramByName(StringRef Name, ArrayRef<StringRef> Paths = {});
+
+ // These functions change the specified standard stream (stdin or stdout) to
+ // binary mode. They return errc::success if the specified stream
+ // was changed. Otherwise a platform dependent error is returned.
+ std::error_code ChangeStdinToBinary();
+ std::error_code ChangeStdoutToBinary();
+
+ /// This function executes the program using the arguments provided. The
+ /// invoked program will inherit the stdin, stdout, and stderr file
+ /// descriptors, the environment and other configuration settings of the
+ /// invoking program.
+ /// This function waits for the program to finish, so should be avoided in
+ /// library functions that aren't expected to block. Consider using
+ /// ExecuteNoWait() instead.
+ /// \returns an integer result code indicating the status of the program.
+ /// A zero or positive value indicates the result code of the program.
+ /// -1 indicates failure to execute
+ /// -2 indicates a crash during execution or timeout
+ int ExecuteAndWait(
+ StringRef Program, ///< Path of the program to be executed. It is
+ ///< presumed this is the result of the findProgramByName method.
+ ArrayRef<StringRef> Args, ///< An array of strings that are passed to the
+ ///< program. The first element should be the name of the program.
+ ///< The array should **not** be terminated by an empty StringRef.
+ Optional<ArrayRef<StringRef>> Env = None, ///< An optional vector of
+ ///< strings to use for the program's environment. If not provided, the
+ ///< current program's environment will be used. If specified, the
+ ///< vector should **not** be terminated by an empty StringRef.
+ ArrayRef<Optional<StringRef>> Redirects = {}, ///<
+ ///< An array of optional paths. Should have a size of zero or three.
+ ///< If the array is empty, no redirections are performed.
+ ///< Otherwise, the inferior process's stdin(0), stdout(1), and stderr(2)
+ ///< will be redirected to the corresponding paths, if the optional path
+ ///< is present (not \c llvm::None).
+ ///< When an empty path is passed in, the corresponding file descriptor
+ ///< will be disconnected (ie, /dev/null'd) in a portable way.
+ unsigned SecondsToWait = 0, ///< If non-zero, this specifies the amount
+ ///< of time to wait for the child process to exit. If the time
+ ///< expires, the child is killed and this call returns. If zero,
+ ///< this function will wait until the child finishes or forever if
+ ///< it doesn't.
+ unsigned MemoryLimit = 0, ///< If non-zero, this specifies max. amount
+ ///< of memory can be allocated by process. If memory usage will be
+ ///< higher limit, the child is killed and this call returns. If zero
+ ///< - no memory limit.
+ std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a
+ ///< string instance in which error messages will be returned. If the
+ ///< string is non-empty upon return an error occurred while invoking the
+ ///< program.
+ bool *ExecutionFailed = nullptr);
+
+ /// Similar to ExecuteAndWait, but returns immediately.
+ /// @returns The \see ProcessInfo of the newly launced process.
+ /// \note On Microsoft Windows systems, users will need to either call
+ /// \see Wait until the process finished execution or win32 CloseHandle() API
+ /// on ProcessInfo.ProcessHandle to avoid memory leaks.
+ ProcessInfo ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args,
+ Optional<ArrayRef<StringRef>> Env,
+ ArrayRef<Optional<StringRef>> Redirects = {},
+ unsigned MemoryLimit = 0,
+ std::string *ErrMsg = nullptr,
+ bool *ExecutionFailed = nullptr);
+
+ /// Return true if the given arguments fit within system-specific
+ /// argument length limits.
+ bool commandLineFitsWithinSystemLimits(StringRef Program,
+ ArrayRef<StringRef> Args);
+
+ /// Return true if the given arguments fit within system-specific
+ /// argument length limits.
+ bool commandLineFitsWithinSystemLimits(StringRef Program,
+ ArrayRef<const char *> Args);
+
+ /// File encoding options when writing contents that a non-UTF8 tool will
+ /// read (on Windows systems). For UNIX, we always use UTF-8.
+ enum WindowsEncodingMethod {
+ /// UTF-8 is the LLVM native encoding, being the same as "do not perform
+ /// encoding conversion".
+ WEM_UTF8,
+ WEM_CurrentCodePage,
+ WEM_UTF16
+ };
+
+ /// Saves the UTF8-encoded \p contents string into the file \p FileName
+ /// using a specific encoding.
+ ///
+ /// This write file function adds the possibility to choose which encoding
+ /// to use when writing a text file. On Windows, this is important when
+ /// writing files with internationalization support with an encoding that is
+ /// different from the one used in LLVM (UTF-8). We use this when writing
+ /// response files, since GCC tools on MinGW only understand legacy code
+ /// pages, and VisualStudio tools only understand UTF-16.
+ /// For UNIX, using different encodings is silently ignored, since all tools
+ /// work well with UTF-8.
+ /// This function assumes that you only use UTF-8 *text* data and will convert
+ /// it to your desired encoding before writing to the file.
+ ///
+ /// FIXME: We use EM_CurrentCodePage to write response files for GNU tools in
+ /// a MinGW/MinGW-w64 environment, which has serious flaws but currently is
+ /// our best shot to make gcc/ld understand international characters. This
+ /// should be changed as soon as binutils fix this to support UTF16 on mingw.
+ ///
+ /// \returns non-zero error_code if failed
+ std::error_code
+ writeFileWithEncoding(StringRef FileName, StringRef Contents,
+ WindowsEncodingMethod Encoding = WEM_UTF8);
+
+ /// This function waits for the process specified by \p PI to finish.
+ /// \returns A \see ProcessInfo struct with Pid set to:
+ /// \li The process id of the child process if the child process has changed
+ /// state.
+ /// \li 0 if the child process has not changed state.
+ /// \note Users of this function should always check the ReturnCode member of
+ /// the \see ProcessInfo returned from this function.
+ ProcessInfo Wait(
+ const ProcessInfo &PI, ///< The child process that should be waited on.
+ unsigned SecondsToWait, ///< If non-zero, this specifies the amount of
+ ///< time to wait for the child process to exit. If the time expires, the
+ ///< child is killed and this function returns. If zero, this function
+ ///< will perform a non-blocking wait on the child process.
+ bool WaitUntilTerminates, ///< If true, ignores \p SecondsToWait and waits
+ ///< until child has terminated.
+ std::string *ErrMsg = nullptr ///< If non-zero, provides a pointer to a
+ ///< string instance in which error messages will be returned. If the
+ ///< string is non-empty upon return an error occurred while invoking the
+ ///< program.
+ );
+
+#if defined(_WIN32)
+ /// Given a list of command line arguments, quote and escape them as necessary
+ /// to build a single flat command line appropriate for calling CreateProcess
+ /// on
+ /// Windows.
+ std::string flattenWindowsCommandLine(ArrayRef<StringRef> Args);
+#endif
+ }
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/Regex.h b/third_party/llvm-project/include/llvm/Support/Regex.h
new file mode 100644
index 000000000..b2620ab4c
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Regex.h
@@ -0,0 +1,109 @@
+//===-- Regex.h - Regular Expression matcher implementation -*- C++ -*-----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a POSIX regular expression matcher. Both Basic and
+// Extended POSIX regular expressions (ERE) are supported. EREs were extended
+// to support backreferences in matches.
+// This implementation also supports matching strings with embedded NUL chars.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_REGEX_H
+#define LLVM_SUPPORT_REGEX_H
+
+#include <string>
+
+struct llvm_regex;
+
+namespace llvm {
+ class StringRef;
+ template<typename T> class SmallVectorImpl;
+
+ class Regex {
+ public:
+ enum {
+ NoFlags=0,
+ /// Compile for matching that ignores upper/lower case distinctions.
+ IgnoreCase=1,
+ /// Compile for newline-sensitive matching. With this flag '[^' bracket
+ /// expressions and '.' never match newline. A ^ anchor matches the
+ /// null string after any newline in the string in addition to its normal
+ /// function, and the $ anchor matches the null string before any
+ /// newline in the string in addition to its normal function.
+ Newline=2,
+ /// By default, the POSIX extended regular expression (ERE) syntax is
+ /// assumed. Pass this flag to turn on basic regular expressions (BRE)
+ /// instead.
+ BasicRegex=4
+ };
+
+ Regex();
+ /// Compiles the given regular expression \p Regex.
+ ///
+ /// \param Regex - referenced string is no longer needed after this
+ /// constructor does finish. Only its compiled form is kept stored.
+ Regex(StringRef Regex, unsigned Flags = NoFlags);
+ Regex(const Regex &) = delete;
+ Regex &operator=(Regex regex) {
+ std::swap(preg, regex.preg);
+ std::swap(error, regex.error);
+ return *this;
+ }
+ Regex(Regex &&regex);
+ ~Regex();
+
+ /// isValid - returns the error encountered during regex compilation, if
+ /// any.
+ bool isValid(std::string &Error) const;
+ bool isValid() const { return !error; }
+
+ /// getNumMatches - In a valid regex, return the number of parenthesized
+ /// matches it contains. The number filled in by match will include this
+ /// many entries plus one for the whole regex (as element 0).
+ unsigned getNumMatches() const;
+
+ /// matches - Match the regex against a given \p String.
+ ///
+ /// \param Matches - If given, on a successful match this will be filled in
+ /// with references to the matched group expressions (inside \p String),
+ /// the first group is always the entire pattern.
+ ///
+ /// \param Error - If non-null, any errors in the matching will be recorded
+ /// as a non-empty string. If there is no error, it will be an empty string.
+ ///
+ /// This returns true on a successful match.
+ bool match(StringRef String, SmallVectorImpl<StringRef> *Matches = nullptr,
+ std::string *Error = nullptr) const;
+
+ /// sub - Return the result of replacing the first match of the regex in
+ /// \p String with the \p Repl string. Backreferences like "\0" in the
+ /// replacement string are replaced with the appropriate match substring.
+ ///
+ /// Note that the replacement string has backslash escaping performed on
+ /// it. Invalid backreferences are ignored (replaced by empty strings).
+ ///
+ /// \param Error If non-null, any errors in the substitution (invalid
+ /// backreferences, trailing backslashes) will be recorded as a non-empty
+ /// string. If there is no error, it will be an empty string.
+ std::string sub(StringRef Repl, StringRef String,
+ std::string *Error = nullptr) const;
+
+ /// If this function returns true, ^Str$ is an extended regular
+ /// expression that matches Str and only Str.
+ static bool isLiteralERE(StringRef Str);
+
+ /// Turn String into a regex by escaping its special characters.
+ static std::string escape(StringRef String);
+
+ private:
+ struct llvm_regex *preg;
+ int error;
+ };
+}
+
+#endif // LLVM_SUPPORT_REGEX_H
diff --git a/third_party/llvm-project/include/llvm/Support/ReverseIteration.h b/third_party/llvm-project/include/llvm/Support/ReverseIteration.h
new file mode 100644
index 000000000..5e0238d81
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/ReverseIteration.h
@@ -0,0 +1,19 @@
+#ifndef LLVM_SUPPORT_REVERSEITERATION_H
+#define LLVM_SUPPORT_REVERSEITERATION_H
+
+#include "llvm/Config/abi-breaking.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+
+namespace llvm {
+
+template<class T = void *>
+bool shouldReverseIterate() {
+#if LLVM_ENABLE_REVERSE_ITERATION
+ return detail::IsPointerLike<T>::value;
+#else
+ return false;
+#endif
+}
+
+}
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/SMLoc.h b/third_party/llvm-project/include/llvm/Support/SMLoc.h
new file mode 100644
index 000000000..d8607034e
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/SMLoc.h
@@ -0,0 +1,64 @@
+//===- SMLoc.h - Source location for use with diagnostics -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SMLoc class. This class encapsulates a location in
+// source code for use in diagnostics.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SMLOC_H
+#define LLVM_SUPPORT_SMLOC_H
+
+#include "llvm/ADT/None.h"
+#include <cassert>
+
+namespace llvm {
+
+/// Represents a location in source code.
+class SMLoc {
+ const char *Ptr = nullptr;
+
+public:
+ SMLoc() = default;
+
+ bool isValid() const { return Ptr != nullptr; }
+
+ bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; }
+ bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; }
+
+ const char *getPointer() const { return Ptr; }
+
+ static SMLoc getFromPointer(const char *Ptr) {
+ SMLoc L;
+ L.Ptr = Ptr;
+ return L;
+ }
+};
+
+/// Represents a range in source code.
+///
+/// SMRange is implemented using a half-open range, as is the convention in C++.
+/// In the string "abc", the range [1,3) represents the substring "bc", and the
+/// range [2,2) represents an empty range between the characters "b" and "c".
+class SMRange {
+public:
+ SMLoc Start, End;
+
+ SMRange() = default;
+ SMRange(NoneType) {}
+ SMRange(SMLoc St, SMLoc En) : Start(St), End(En) {
+ assert(Start.isValid() == End.isValid() &&
+ "Start and End should either both be valid or both be invalid!");
+ }
+
+ bool isValid() const { return Start.isValid(); }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_SMLOC_H
diff --git a/third_party/llvm-project/include/llvm/Support/ScopedPrinter.h b/third_party/llvm-project/include/llvm/Support/ScopedPrinter.h
new file mode 100644
index 000000000..88daedc87
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/ScopedPrinter.h
@@ -0,0 +1,388 @@
+//===-- 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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SCOPEDPRINTER_H
+#define LLVM_SUPPORT_SCOPEDPRINTER_H
+
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+
+namespace llvm {
+
+template <typename T> struct EnumEntry {
+ StringRef Name;
+ // While Name suffices in most of the cases, in certain cases
+ // GNU style and LLVM style of ELFDumper do not
+ // display same string for same enum. The AltName if initialized appropriately
+ // will hold the string that GNU style emits.
+ // Example:
+ // "EM_X86_64" string on LLVM style for Elf_Ehdr->e_machine corresponds to
+ // "Advanced Micro Devices X86-64" on GNU style
+ StringRef AltName;
+ T Value;
+ EnumEntry(StringRef N, StringRef A, T V) : Name(N), AltName(A), Value(V) {}
+ EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {}
+};
+
+struct HexNumber {
+ // To avoid sign-extension we have to explicitly cast to the appropriate
+ // unsigned type. The overloads are here so that every type that is implicitly
+ // convertible to an integer (including enums and endian helpers) can be used
+ // without requiring type traits or call-site changes.
+ HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) {}
+ HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) {}
+ HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) {}
+ HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) {}
+ HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) {}
+ HexNumber(signed long long Value)
+ : Value(static_cast<unsigned long long>(Value)) {}
+ HexNumber(unsigned char Value) : Value(Value) {}
+ HexNumber(unsigned short Value) : Value(Value) {}
+ HexNumber(unsigned int Value) : Value(Value) {}
+ HexNumber(unsigned long Value) : Value(Value) {}
+ HexNumber(unsigned long long Value) : Value(Value) {}
+ uint64_t Value;
+};
+
+raw_ostream &operator<<(raw_ostream &OS, const HexNumber &Value);
+const std::string to_hexString(uint64_t Value, bool UpperCase = true);
+
+template <class T> const std::string to_string(const T &Value) {
+ std::string number;
+ llvm::raw_string_ostream stream(number);
+ stream << Value;
+ return stream.str();
+}
+
+class ScopedPrinter {
+public:
+ ScopedPrinter(raw_ostream &OS) : OS(OS), IndentLevel(0) {}
+
+ void flush() { OS.flush(); }
+
+ void indent(int Levels = 1) { IndentLevel += Levels; }
+
+ void unindent(int Levels = 1) {
+ IndentLevel = std::max(0, IndentLevel - Levels);
+ }
+
+ void resetIndent() { IndentLevel = 0; }
+
+ int getIndentLevel() { return IndentLevel; }
+
+ void setPrefix(StringRef P) { Prefix = P; }
+
+ void printIndent() {
+ OS << Prefix;
+ for (int i = 0; i < IndentLevel; ++i)
+ OS << " ";
+ }
+
+ template <typename T> HexNumber hex(T Value) { return HexNumber(Value); }
+
+ template <typename T, typename TEnum>
+ void printEnum(StringRef Label, T Value,
+ ArrayRef<EnumEntry<TEnum>> EnumValues) {
+ StringRef Name;
+ bool Found = false;
+ for (const auto &EnumItem : EnumValues) {
+ if (EnumItem.Value == Value) {
+ Name = EnumItem.Name;
+ Found = true;
+ break;
+ }
+ }
+
+ if (Found) {
+ startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n";
+ } else {
+ startLine() << Label << ": " << hex(Value) << "\n";
+ }
+ }
+
+ template <typename T, typename TFlag>
+ void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags,
+ TFlag EnumMask1 = {}, TFlag EnumMask2 = {},
+ TFlag EnumMask3 = {}) {
+ typedef EnumEntry<TFlag> FlagEntry;
+ typedef SmallVector<FlagEntry, 10> FlagVector;
+ FlagVector SetFlags;
+
+ for (const auto &Flag : Flags) {
+ if (Flag.Value == 0)
+ continue;
+
+ TFlag EnumMask{};
+ if (Flag.Value & EnumMask1)
+ EnumMask = EnumMask1;
+ else if (Flag.Value & EnumMask2)
+ EnumMask = EnumMask2;
+ else if (Flag.Value & EnumMask3)
+ EnumMask = EnumMask3;
+ bool IsEnum = (Flag.Value & EnumMask) != 0;
+ if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
+ (IsEnum && (Value & EnumMask) == Flag.Value)) {
+ SetFlags.push_back(Flag);
+ }
+ }
+
+ llvm::sort(SetFlags, &flagName<TFlag>);
+
+ startLine() << Label << " [ (" << hex(Value) << ")\n";
+ for (const auto &Flag : SetFlags) {
+ startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n";
+ }
+ startLine() << "]\n";
+ }
+
+ template <typename T> void printFlags(StringRef Label, T Value) {
+ startLine() << Label << " [ (" << hex(Value) << ")\n";
+ uint64_t Flag = 1;
+ uint64_t Curr = Value;
+ while (Curr > 0) {
+ if (Curr & 1)
+ startLine() << " " << hex(Flag) << "\n";
+ Curr >>= 1;
+ Flag <<= 1;
+ }
+ startLine() << "]\n";
+ }
+
+ void printNumber(StringRef Label, uint64_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, uint32_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, uint16_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, uint8_t Value) {
+ startLine() << Label << ": " << unsigned(Value) << "\n";
+ }
+
+ void printNumber(StringRef Label, int64_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, int32_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, int16_t Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printNumber(StringRef Label, int8_t Value) {
+ startLine() << Label << ": " << int(Value) << "\n";
+ }
+
+ void printNumber(StringRef Label, const APSInt &Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printBoolean(StringRef Label, bool Value) {
+ startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
+ }
+
+ template <typename... T> void printVersion(StringRef Label, T... Version) {
+ startLine() << Label << ": ";
+ printVersionInternal(Version...);
+ getOStream() << "\n";
+ }
+
+ template <typename T> void printList(StringRef Label, const T &List) {
+ startLine() << Label << ": [";
+ bool Comma = false;
+ for (const auto &Item : List) {
+ if (Comma)
+ OS << ", ";
+ OS << Item;
+ Comma = true;
+ }
+ OS << "]\n";
+ }
+
+ template <typename T, typename U>
+ void printList(StringRef Label, const T &List, const U &Printer) {
+ startLine() << Label << ": [";
+ bool Comma = false;
+ for (const auto &Item : List) {
+ if (Comma)
+ OS << ", ";
+ Printer(OS, Item);
+ Comma = true;
+ }
+ OS << "]\n";
+ }
+
+ template <typename T> void printHexList(StringRef Label, const T &List) {
+ startLine() << Label << ": [";
+ bool Comma = false;
+ for (const auto &Item : List) {
+ if (Comma)
+ OS << ", ";
+ OS << hex(Item);
+ Comma = true;
+ }
+ OS << "]\n";
+ }
+
+ template <typename T> void printHex(StringRef Label, T Value) {
+ startLine() << Label << ": " << hex(Value) << "\n";
+ }
+
+ template <typename T> void printHex(StringRef Label, StringRef Str, T Value) {
+ startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n";
+ }
+
+ template <typename T>
+ void printSymbolOffset(StringRef Label, StringRef Symbol, T Value) {
+ startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n';
+ }
+
+ void printString(StringRef Value) { startLine() << Value << "\n"; }
+
+ void printString(StringRef Label, StringRef Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ void printString(StringRef Label, const std::string &Value) {
+ printString(Label, StringRef(Value));
+ }
+
+ void printString(StringRef Label, const char* Value) {
+ printString(Label, StringRef(Value));
+ }
+
+ template <typename T>
+ void printNumber(StringRef Label, StringRef Str, T Value) {
+ startLine() << Label << ": " << Str << " (" << Value << ")\n";
+ }
+
+ void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) {
+ printBinaryImpl(Label, Str, Value, false);
+ }
+
+ void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) {
+ auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
+ Value.size());
+ printBinaryImpl(Label, Str, V, false);
+ }
+
+ void printBinary(StringRef Label, ArrayRef<uint8_t> Value) {
+ printBinaryImpl(Label, StringRef(), Value, false);
+ }
+
+ void printBinary(StringRef Label, ArrayRef<char> Value) {
+ auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
+ Value.size());
+ printBinaryImpl(Label, StringRef(), V, false);
+ }
+
+ void printBinary(StringRef Label, StringRef Value) {
+ auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
+ Value.size());
+ printBinaryImpl(Label, StringRef(), V, false);
+ }
+
+ void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value,
+ uint32_t StartOffset) {
+ printBinaryImpl(Label, StringRef(), Value, true, StartOffset);
+ }
+
+ void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) {
+ printBinaryImpl(Label, StringRef(), Value, true);
+ }
+
+ void printBinaryBlock(StringRef Label, StringRef Value) {
+ auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
+ Value.size());
+ printBinaryImpl(Label, StringRef(), V, true);
+ }
+
+ template <typename T> void printObject(StringRef Label, const T &Value) {
+ startLine() << Label << ": " << Value << "\n";
+ }
+
+ raw_ostream &startLine() {
+ printIndent();
+ return OS;
+ }
+
+ raw_ostream &getOStream() { return OS; }
+
+private:
+ template <typename T> void printVersionInternal(T Value) {
+ getOStream() << Value;
+ }
+
+ template <typename S, typename T, typename... TArgs>
+ void printVersionInternal(S Value, T Value2, TArgs... Args) {
+ getOStream() << Value << ".";
+ printVersionInternal(Value2, Args...);
+ }
+
+ template <typename T>
+ static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
+ return lhs.Name < rhs.Name;
+ }
+
+ void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
+ bool Block, uint32_t StartOffset = 0);
+
+ raw_ostream &OS;
+ int IndentLevel;
+ StringRef Prefix;
+};
+
+template <>
+inline void
+ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
+ support::ulittle16_t Value) {
+ startLine() << Label << ": " << hex(Value) << "\n";
+}
+
+template<char Open, char Close>
+struct DelimitedScope {
+ explicit DelimitedScope(ScopedPrinter &W) : W(W) {
+ W.startLine() << Open << '\n';
+ W.indent();
+ }
+
+ DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) {
+ W.startLine() << N;
+ if (!N.empty())
+ W.getOStream() << ' ';
+ W.getOStream() << Open << '\n';
+ W.indent();
+ }
+
+ ~DelimitedScope() {
+ W.unindent();
+ W.startLine() << Close << '\n';
+ }
+
+ ScopedPrinter &W;
+};
+
+using DictScope = DelimitedScope<'{', '}'>;
+using ListScope = DelimitedScope<'[', ']'>;
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/Signals.h b/third_party/llvm-project/include/llvm/Support/Signals.h
new file mode 100644
index 000000000..a6b215a24
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Signals.h
@@ -0,0 +1,90 @@
+//===- llvm/Support/Signals.h - Signal Handling support ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines some helpful functions for dealing with the possibility of
+// unix signals occurring while your program is running.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SIGNALS_H
+#define LLVM_SUPPORT_SIGNALS_H
+
+#include <string>
+
+namespace llvm {
+class StringRef;
+class raw_ostream;
+
+namespace sys {
+
+ /// This function runs all the registered interrupt handlers, including the
+ /// removal of files registered by RemoveFileOnSignal.
+ void RunInterruptHandlers();
+
+ /// This function registers signal handlers to ensure that if a signal gets
+ /// delivered that the named file is removed.
+ /// Remove a file if a fatal signal occurs.
+ bool RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg = nullptr);
+
+ /// This function removes a file from the list of files to be removed on
+ /// signal delivery.
+ void DontRemoveFileOnSignal(StringRef Filename);
+
+ /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
+ /// process, print a stack trace and then exit.
+ /// Print a stack trace if a fatal signal occurs.
+ /// \param Argv0 the current binary name, used to find the symbolizer
+ /// relative to the current binary before searching $PATH; can be
+ /// StringRef(), in which case we will only search $PATH.
+ /// \param DisableCrashReporting if \c true, disable the normal crash
+ /// reporting mechanisms on the underlying operating system.
+ void PrintStackTraceOnErrorSignal(StringRef Argv0,
+ bool DisableCrashReporting = false);
+
+ /// Disable all system dialog boxes that appear when the process crashes.
+ void DisableSystemDialogsOnCrash();
+
+ /// Print the stack trace using the given \c raw_ostream object.
+ void PrintStackTrace(raw_ostream &OS);
+
+ // Run all registered signal handlers.
+ void RunSignalHandlers();
+
+ using SignalHandlerCallback = void (*)(void *);
+
+ /// Add a function to be called when an abort/kill signal is delivered to the
+ /// process. The handler can have a cookie passed to it to identify what
+ /// instance of the handler it is.
+ void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie);
+
+ /// This function registers a function to be called when the user "interrupts"
+ /// the program (typically by pressing ctrl-c). When the user interrupts the
+ /// program, the specified interrupt function is called instead of the program
+ /// being killed, and the interrupt function automatically disabled.
+ ///
+ /// Note that interrupt functions are not allowed to call any non-reentrant
+ /// functions. An null interrupt function pointer disables the current
+ /// installed function. Note also that the handler may be executed on a
+ /// different thread on some platforms.
+ void SetInterruptFunction(void (*IF)());
+
+ /// Registers a function to be called when an "info" signal is delivered to
+ /// the process.
+ ///
+ /// On POSIX systems, this will be SIGUSR1; on systems that have it, SIGINFO
+ /// will also be used (typically ctrl-t).
+ ///
+ /// Note that signal handlers are not allowed to call any non-reentrant
+ /// functions. An null function pointer disables the current installed
+ /// function. Note also that the handler may be executed on a different
+ /// thread on some platforms.
+ void SetInfoSignalFunction(void (*Handler)());
+} // End sys namespace
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/SmallVectorMemoryBuffer.h b/third_party/llvm-project/include/llvm/Support/SmallVectorMemoryBuffer.h
new file mode 100644
index 000000000..b63b58e3a
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/SmallVectorMemoryBuffer.h
@@ -0,0 +1,65 @@
+//===- SmallVectorMemoryBuffer.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 declares a wrapper class to hold the memory into which an
+// object will be generated.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H
+#define LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+/// SmallVector-backed MemoryBuffer instance.
+///
+/// This class enables efficient construction of MemoryBuffers from SmallVector
+/// instances. This is useful for MCJIT and Orc, where object files are streamed
+/// into SmallVectors, then inspected using ObjectFile (which takes a
+/// MemoryBuffer).
+class SmallVectorMemoryBuffer : public MemoryBuffer {
+public:
+ /// Construct an SmallVectorMemoryBuffer from the given SmallVector
+ /// r-value.
+ ///
+ /// FIXME: It'd be nice for this to be a non-templated constructor taking a
+ /// SmallVectorImpl here instead of a templated one taking a SmallVector<N>,
+ /// but SmallVector's move-construction/assignment currently only take
+ /// SmallVectors. If/when that is fixed we can simplify this constructor and
+ /// the following one.
+ SmallVectorMemoryBuffer(SmallVectorImpl<char> &&SV)
+ : SV(std::move(SV)), BufferName("<in-memory object>") {
+ init(this->SV.begin(), this->SV.end(), false);
+ }
+
+ /// Construct a named SmallVectorMemoryBuffer from the given
+ /// SmallVector r-value and StringRef.
+ SmallVectorMemoryBuffer(SmallVectorImpl<char> &&SV, StringRef Name)
+ : SV(std::move(SV)), BufferName(Name) {
+ init(this->SV.begin(), this->SV.end(), false);
+ }
+
+ // Key function.
+ ~SmallVectorMemoryBuffer() override;
+
+ StringRef getBufferIdentifier() const override { return BufferName; }
+
+ BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
+
+private:
+ SmallVector<char, 0> SV;
+ std::string BufferName;
+};
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/SourceMgr.h b/third_party/llvm-project/include/llvm/Support/SourceMgr.h
new file mode 100644
index 000000000..aa6026c23
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/SourceMgr.h
@@ -0,0 +1,310 @@
+//===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SMDiagnostic and SourceMgr classes. This
+// provides a simple substrate for diagnostics, #include handling, and other low
+// level things for simple parsers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SOURCEMGR_H
+#define LLVM_SUPPORT_SOURCEMGR_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SMLoc.h"
+#include <algorithm>
+#include <cassert>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+class SMDiagnostic;
+class SMFixIt;
+
+/// This owns the files read by a parser, handles include stacks,
+/// and handles diagnostic wrangling.
+class SourceMgr {
+public:
+ enum DiagKind {
+ DK_Error,
+ DK_Warning,
+ DK_Remark,
+ DK_Note,
+ };
+
+ /// Clients that want to handle their own diagnostics in a custom way can
+ /// register a function pointer+context as a diagnostic handler.
+ /// It gets called each time PrintMessage is invoked.
+ using DiagHandlerTy = void (*)(const SMDiagnostic &, void *Context);
+
+private:
+ struct SrcBuffer {
+ /// The memory buffer for the file.
+ std::unique_ptr<MemoryBuffer> Buffer;
+
+ /// Helper type for OffsetCache below: since we're storing many offsets
+ /// into relatively small files (often smaller than 2^8 or 2^16 bytes),
+ /// we select the offset vector element type dynamically based on the
+ /// size of Buffer.
+ using VariableSizeOffsets = PointerUnion4<std::vector<uint8_t> *,
+ std::vector<uint16_t> *,
+ std::vector<uint32_t> *,
+ std::vector<uint64_t> *>;
+
+ /// Vector of offsets into Buffer at which there are line-endings
+ /// (lazily populated). Once populated, the '\n' that marks the end of
+ /// line number N from [1..] is at Buffer[OffsetCache[N-1]]. Since
+ /// these offsets are in sorted (ascending) order, they can be
+ /// binary-searched for the first one after any given offset (eg. an
+ /// offset corresponding to a particular SMLoc).
+ mutable VariableSizeOffsets OffsetCache;
+
+ /// Populate \c OffsetCache and look up a given \p Ptr in it, assuming
+ /// it points somewhere into \c Buffer. The static type parameter \p T
+ /// must be an unsigned integer type from uint{8,16,32,64}_t large
+ /// enough to store offsets inside \c Buffer.
+ template<typename T>
+ unsigned getLineNumber(const char *Ptr) const;
+
+ /// This is the location of the parent include, or null if at the top level.
+ SMLoc IncludeLoc;
+
+ SrcBuffer() = default;
+ SrcBuffer(SrcBuffer &&);
+ SrcBuffer(const SrcBuffer &) = delete;
+ SrcBuffer &operator=(const SrcBuffer &) = delete;
+ ~SrcBuffer();
+ };
+
+ /// This is all of the buffers that we are reading from.
+ std::vector<SrcBuffer> Buffers;
+
+ // This is the list of directories we should search for include files in.
+ std::vector<std::string> IncludeDirectories;
+
+ DiagHandlerTy DiagHandler = nullptr;
+ void *DiagContext = nullptr;
+
+ bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); }
+
+public:
+ SourceMgr() = default;
+ SourceMgr(const SourceMgr &) = delete;
+ SourceMgr &operator=(const SourceMgr &) = delete;
+ SourceMgr(SourceMgr &&) = default;
+ SourceMgr &operator=(SourceMgr &&) = default;
+ ~SourceMgr() = default;
+
+ void setIncludeDirs(const std::vector<std::string> &Dirs) {
+ IncludeDirectories = Dirs;
+ }
+
+ /// Specify a diagnostic handler to be invoked every time PrintMessage is
+ /// called. \p Ctx is passed into the handler when it is invoked.
+ void setDiagHandler(DiagHandlerTy DH, void *Ctx = nullptr) {
+ DiagHandler = DH;
+ DiagContext = Ctx;
+ }
+
+ DiagHandlerTy getDiagHandler() const { return DiagHandler; }
+ void *getDiagContext() const { return DiagContext; }
+
+ const SrcBuffer &getBufferInfo(unsigned i) const {
+ assert(isValidBufferID(i));
+ return Buffers[i - 1];
+ }
+
+ const MemoryBuffer *getMemoryBuffer(unsigned i) const {
+ assert(isValidBufferID(i));
+ return Buffers[i - 1].Buffer.get();
+ }
+
+ unsigned getNumBuffers() const {
+ return Buffers.size();
+ }
+
+ unsigned getMainFileID() const {
+ assert(getNumBuffers());
+ return 1;
+ }
+
+ SMLoc getParentIncludeLoc(unsigned i) const {
+ assert(isValidBufferID(i));
+ return Buffers[i - 1].IncludeLoc;
+ }
+
+ /// Add a new source buffer to this source manager. This takes ownership of
+ /// the memory buffer.
+ unsigned AddNewSourceBuffer(std::unique_ptr<MemoryBuffer> F,
+ SMLoc IncludeLoc) {
+ SrcBuffer NB;
+ NB.Buffer = std::move(F);
+ NB.IncludeLoc = IncludeLoc;
+ Buffers.push_back(std::move(NB));
+ return Buffers.size();
+ }
+
+ /// Search for a file with the specified name in the current directory or in
+ /// one of the IncludeDirs.
+ ///
+ /// If no file is found, this returns 0, otherwise it returns the buffer ID
+ /// of the stacked file. The full path to the included file can be found in
+ /// \p IncludedFile.
+ unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc,
+ std::string &IncludedFile);
+
+ /// Return the ID of the buffer containing the specified location.
+ ///
+ /// 0 is returned if the buffer is not found.
+ unsigned FindBufferContainingLoc(SMLoc Loc) const;
+
+ /// Find the line number for the specified location in the specified file.
+ /// This is not a fast method.
+ unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const {
+ return getLineAndColumn(Loc, BufferID).first;
+ }
+
+ /// Find the line and column number for the specified location in the
+ /// specified file. This is not a fast method.
+ std::pair<unsigned, unsigned> getLineAndColumn(SMLoc Loc,
+ unsigned BufferID = 0) const;
+
+ /// Emit a message about the specified location with the specified string.
+ ///
+ /// \param ShowColors Display colored messages if output is a terminal and
+ /// the default error handler is used.
+ void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind,
+ const Twine &Msg,
+ ArrayRef<SMRange> Ranges = None,
+ ArrayRef<SMFixIt> FixIts = None,
+ bool ShowColors = true) const;
+
+ /// Emits a diagnostic to llvm::errs().
+ void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
+ ArrayRef<SMRange> Ranges = None,
+ ArrayRef<SMFixIt> FixIts = None,
+ bool ShowColors = true) const;
+
+ /// Emits a manually-constructed diagnostic to the given output stream.
+ ///
+ /// \param ShowColors Display colored messages if output is a terminal and
+ /// the default error handler is used.
+ void PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic,
+ bool ShowColors = true) const;
+
+ /// Return an SMDiagnostic at the specified location with the specified
+ /// string.
+ ///
+ /// \param Msg If non-null, the kind of message (e.g., "error") which is
+ /// prefixed to the message.
+ SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
+ ArrayRef<SMRange> Ranges = None,
+ ArrayRef<SMFixIt> FixIts = None) const;
+
+ /// Prints the names of included files and the line of the file they were
+ /// included from. A diagnostic handler can use this before printing its
+ /// custom formatted message.
+ ///
+ /// \param IncludeLoc The location of the include.
+ /// \param OS the raw_ostream to print on.
+ void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const;
+};
+
+/// Represents a single fixit, a replacement of one range of text with another.
+class SMFixIt {
+ SMRange Range;
+
+ std::string Text;
+
+public:
+ // FIXME: Twine.str() is not very efficient.
+ SMFixIt(SMLoc Loc, const Twine &Insertion)
+ : Range(Loc, Loc), Text(Insertion.str()) {
+ assert(Loc.isValid());
+ }
+
+ // FIXME: Twine.str() is not very efficient.
+ SMFixIt(SMRange R, const Twine &Replacement)
+ : Range(R), Text(Replacement.str()) {
+ assert(R.isValid());
+ }
+
+ StringRef getText() const { return Text; }
+ SMRange getRange() const { return Range; }
+
+ bool operator<(const SMFixIt &Other) const {
+ if (Range.Start.getPointer() != Other.Range.Start.getPointer())
+ return Range.Start.getPointer() < Other.Range.Start.getPointer();
+ if (Range.End.getPointer() != Other.Range.End.getPointer())
+ return Range.End.getPointer() < Other.Range.End.getPointer();
+ return Text < Other.Text;
+ }
+};
+
+/// Instances of this class encapsulate one diagnostic report, allowing
+/// printing to a raw_ostream as a caret diagnostic.
+class SMDiagnostic {
+ const SourceMgr *SM = nullptr;
+ SMLoc Loc;
+ std::string Filename;
+ int LineNo = 0;
+ int ColumnNo = 0;
+ SourceMgr::DiagKind Kind = SourceMgr::DK_Error;
+ std::string Message, LineContents;
+ std::vector<std::pair<unsigned, unsigned>> Ranges;
+ SmallVector<SMFixIt, 4> FixIts;
+
+public:
+ // Null diagnostic.
+ SMDiagnostic() = default;
+ // Diagnostic with no location (e.g. file not found, command line arg error).
+ SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg)
+ : Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {}
+
+ // Diagnostic with a location.
+ SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN,
+ int Line, int Col, SourceMgr::DiagKind Kind,
+ StringRef Msg, StringRef LineStr,
+ ArrayRef<std::pair<unsigned,unsigned>> Ranges,
+ ArrayRef<SMFixIt> FixIts = None);
+
+ const SourceMgr *getSourceMgr() const { return SM; }
+ SMLoc getLoc() const { return Loc; }
+ StringRef getFilename() const { return Filename; }
+ int getLineNo() const { return LineNo; }
+ int getColumnNo() const { return ColumnNo; }
+ SourceMgr::DiagKind getKind() const { return Kind; }
+ StringRef getMessage() const { return Message; }
+ StringRef getLineContents() const { return LineContents; }
+ ArrayRef<std::pair<unsigned, unsigned>> getRanges() const { return Ranges; }
+
+ void addFixIt(const SMFixIt &Hint) {
+ FixIts.push_back(Hint);
+ }
+
+ ArrayRef<SMFixIt> getFixIts() const {
+ return FixIts;
+ }
+
+ void print(const char *ProgName, raw_ostream &S, bool ShowColors = true,
+ bool ShowKindLabel = true) const;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_SOURCEMGR_H
diff --git a/third_party/llvm-project/include/llvm/Support/SwapByteOrder.h b/third_party/llvm-project/include/llvm/Support/SwapByteOrder.h
new file mode 100644
index 000000000..6cec87006
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/SwapByteOrder.h
@@ -0,0 +1,160 @@
+//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares generic and optimized functions to swap the byte order of
+// an integral type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H
+#define LLVM_SUPPORT_SWAPBYTEORDER_H
+
+#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
+
+#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__)
+#include <endian.h>
+#elif defined(_AIX)
+#include <sys/machine.h>
+#elif defined(__sun)
+/* Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h */
+#include <sys/types.h>
+#define BIG_ENDIAN 4321
+#define LITTLE_ENDIAN 1234
+#if defined(_BIG_ENDIAN)
+#define BYTE_ORDER BIG_ENDIAN
+#else
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+#else
+#if !defined(BYTE_ORDER) && !defined(_WIN32)
+#include <machine/endian.h>
+#endif
+#endif
+
+namespace llvm {
+namespace sys {
+
+#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
+constexpr bool IsBigEndianHost = true;
+#else
+constexpr bool IsBigEndianHost = false;
+#endif
+
+static const bool IsLittleEndianHost = !IsBigEndianHost;
+
+/// SwapByteOrder_16 - This function returns a byte-swapped representation of
+/// the 16-bit argument.
+inline uint16_t SwapByteOrder_16(uint16_t value) {
+#if defined(_MSC_VER) && !defined(_DEBUG)
+ // The DLL version of the runtime lacks these functions (bug!?), but in a
+ // release build they're replaced with BSWAP instructions anyway.
+ return _byteswap_ushort(value);
+#else
+ uint16_t Hi = value << 8;
+ uint16_t Lo = value >> 8;
+ return Hi | Lo;
+#endif
+}
+
+/// This function returns a byte-swapped representation of the 32-bit argument.
+inline uint32_t SwapByteOrder_32(uint32_t value) {
+#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
+ return __builtin_bswap32(value);
+#elif defined(_MSC_VER) && !defined(_DEBUG)
+ return _byteswap_ulong(value);
+#else
+ uint32_t Byte0 = value & 0x000000FF;
+ uint32_t Byte1 = value & 0x0000FF00;
+ uint32_t Byte2 = value & 0x00FF0000;
+ uint32_t Byte3 = value & 0xFF000000;
+ return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
+#endif
+}
+
+/// This function returns a byte-swapped representation of the 64-bit argument.
+inline uint64_t SwapByteOrder_64(uint64_t value) {
+#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
+ return __builtin_bswap64(value);
+#elif defined(_MSC_VER) && !defined(_DEBUG)
+ return _byteswap_uint64(value);
+#else
+ uint64_t Hi = SwapByteOrder_32(uint32_t(value));
+ uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32));
+ return (Hi << 32) | Lo;
+#endif
+}
+
+inline unsigned char getSwappedBytes(unsigned char C) { return C; }
+inline signed char getSwappedBytes(signed char C) { return C; }
+inline char getSwappedBytes(char C) { return C; }
+
+inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); }
+inline signed short getSwappedBytes( signed short C) { return SwapByteOrder_16(C); }
+
+inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); }
+inline signed int getSwappedBytes( signed int C) { return SwapByteOrder_32(C); }
+
+#if __LONG_MAX__ == __INT_MAX__
+inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); }
+inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_32(C); }
+#elif __LONG_MAX__ == __LONG_LONG_MAX__
+inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); }
+inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); }
+#else
+#error "Unknown long size!"
+#endif
+
+inline unsigned long long getSwappedBytes(unsigned long long C) {
+ return SwapByteOrder_64(C);
+}
+inline signed long long getSwappedBytes(signed long long C) {
+ return SwapByteOrder_64(C);
+}
+
+inline float getSwappedBytes(float C) {
+ union {
+ uint32_t i;
+ float f;
+ } in, out;
+ in.f = C;
+ out.i = SwapByteOrder_32(in.i);
+ return out.f;
+}
+
+inline double getSwappedBytes(double C) {
+ union {
+ uint64_t i;
+ double d;
+ } in, out;
+ in.d = C;
+ out.i = SwapByteOrder_64(in.i);
+ 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);
+}
+
+} // end namespace sys
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/TargetParser.h b/third_party/llvm-project/include/llvm/Support/TargetParser.h
new file mode 100644
index 000000000..a7e1a752d
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/TargetParser.h
@@ -0,0 +1,174 @@
+//===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise hardware features such as
+// FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TARGETPARSER_H
+#define LLVM_SUPPORT_TARGETPARSER_H
+
+// FIXME: vector is used because that's what clang uses for subtarget feature
+// lists, but SmallVector would probably be better
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/ARMTargetParser.h"
+#include "llvm/Support/AArch64TargetParser.h"
+#include <vector>
+
+namespace llvm {
+class StringRef;
+
+// Target specific information in their own namespaces.
+// (ARM/AArch64 are declared in ARM/AArch64TargetParser.h)
+// These should be generated from TableGen because the information is already
+// there, and there is where new information about targets will be added.
+// FIXME: To TableGen this we need to make some table generated files available
+// even if the back-end is not compiled with LLVM, plus we need to create a new
+// back-end to TableGen to create these clean tables.
+namespace X86 {
+
+// This should be kept in sync with libcc/compiler-rt as its included by clang
+// as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorVendors : unsigned {
+ VENDOR_DUMMY,
+#define X86_VENDOR(ENUM, STRING) \
+ ENUM,
+#include "llvm/Support/X86TargetParser.def"
+ VENDOR_OTHER
+};
+
+// This should be kept in sync with libcc/compiler-rt as its included by clang
+// as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorTypes : unsigned {
+ CPU_TYPE_DUMMY,
+#define X86_CPU_TYPE(ARCHNAME, ENUM) \
+ ENUM,
+#include "llvm/Support/X86TargetParser.def"
+ CPU_TYPE_MAX
+};
+
+// This should be kept in sync with libcc/compiler-rt as its included by clang
+// as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorSubtypes : unsigned {
+ CPU_SUBTYPE_DUMMY,
+#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \
+ ENUM,
+#include "llvm/Support/X86TargetParser.def"
+ CPU_SUBTYPE_MAX
+};
+
+// This should be kept in sync with libcc/compiler-rt as it should be used
+// by clang as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorFeatures {
+#define X86_FEATURE(VAL, ENUM) \
+ ENUM = VAL,
+#include "llvm/Support/X86TargetParser.def"
+
+};
+
+} // namespace X86
+
+namespace AMDGPU {
+
+/// GPU kinds supported by the AMDGPU target.
+enum GPUKind : uint32_t {
+ // Not specified processor.
+ GK_NONE = 0,
+
+ // R600-based processors.
+ GK_R600 = 1,
+ GK_R630 = 2,
+ GK_RS880 = 3,
+ GK_RV670 = 4,
+ GK_RV710 = 5,
+ GK_RV730 = 6,
+ GK_RV770 = 7,
+ GK_CEDAR = 8,
+ GK_CYPRESS = 9,
+ GK_JUNIPER = 10,
+ GK_REDWOOD = 11,
+ GK_SUMO = 12,
+ GK_BARTS = 13,
+ GK_CAICOS = 14,
+ GK_CAYMAN = 15,
+ GK_TURKS = 16,
+
+ GK_R600_FIRST = GK_R600,
+ GK_R600_LAST = GK_TURKS,
+
+ // AMDGCN-based processors.
+ GK_GFX600 = 32,
+ GK_GFX601 = 33,
+
+ GK_GFX700 = 40,
+ GK_GFX701 = 41,
+ GK_GFX702 = 42,
+ GK_GFX703 = 43,
+ GK_GFX704 = 44,
+
+ GK_GFX801 = 50,
+ GK_GFX802 = 51,
+ GK_GFX803 = 52,
+ GK_GFX810 = 53,
+
+ GK_GFX900 = 60,
+ 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_GFX1012,
+};
+
+/// Instruction set architecture version.
+struct IsaVersion {
+ unsigned Major;
+ unsigned Minor;
+ unsigned Stepping;
+};
+
+// This isn't comprehensive for now, just things that are needed from the
+// frontend driver.
+enum ArchFeatureKind : uint32_t {
+ FEATURE_NONE = 0,
+
+ // These features only exist for r600, and are implied true for amdgcn.
+ FEATURE_FMA = 1 << 1,
+ FEATURE_LDEXP = 1 << 2,
+ FEATURE_FP64 = 1 << 3,
+
+ // Common features.
+ FEATURE_FAST_FMA_F32 = 1 << 4,
+ FEATURE_FAST_DENORMAL_F32 = 1 << 5
+};
+
+StringRef getArchNameAMDGCN(GPUKind AK);
+StringRef getArchNameR600(GPUKind AK);
+StringRef getCanonicalArchName(StringRef Arch);
+GPUKind parseArchAMDGCN(StringRef CPU);
+GPUKind parseArchR600(StringRef CPU);
+unsigned getArchAttrAMDGCN(GPUKind AK);
+unsigned getArchAttrR600(GPUKind AK);
+
+void fillValidArchListAMDGCN(SmallVectorImpl<StringRef> &Values);
+void fillValidArchListR600(SmallVectorImpl<StringRef> &Values);
+
+IsaVersion getIsaVersion(StringRef GPU);
+
+} // namespace AMDGPU
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/TargetRegistry.h b/third_party/llvm-project/include/llvm/Support/TargetRegistry.h
new file mode 100644
index 000000000..d91eabae8
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/TargetRegistry.h
@@ -0,0 +1,1209 @@
+//===- Support/TargetRegistry.h - Target Registration -----------*- 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 exposes the TargetRegistry interface, which tools can use to access
+// the appropriate target specific classes (TargetMachine, AsmPrinter, etc.)
+// which have been registered.
+//
+// Target specific class implementations should register themselves using the
+// appropriate TargetRegistry interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TARGETREGISTRY_H
+#define LLVM_SUPPORT_TARGETREGISTRY_H
+
+#include "llvm-c/DisassemblerTypes.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <memory>
+#include <string>
+
+namespace llvm {
+
+class AsmPrinter;
+class MCAsmBackend;
+class MCAsmInfo;
+class MCAsmParser;
+class MCCodeEmitter;
+class MCContext;
+class MCDisassembler;
+class MCInstPrinter;
+class MCInstrAnalysis;
+class MCInstrInfo;
+class MCObjectWriter;
+class MCRegisterInfo;
+class MCRelocationInfo;
+class MCStreamer;
+class MCSubtargetInfo;
+class MCSymbolizer;
+class MCTargetAsmParser;
+class MCTargetOptions;
+class MCTargetStreamer;
+class raw_ostream;
+class raw_pwrite_stream;
+class TargetMachine;
+class TargetOptions;
+
+MCStreamer *createNullStreamer(MCContext &Ctx);
+// Takes ownership of \p TAB and \p CE.
+
+/// Create a machine code streamer which will print out assembly for the native
+/// target, suitable for compiling with a native assembler.
+///
+/// \param InstPrint - If given, the instruction printer to use. If not given
+/// the MCInst representation will be printed. This method takes ownership of
+/// InstPrint.
+///
+/// \param CE - If given, a code emitter to use to show the instruction
+/// encoding inline with the assembly. This method takes ownership of \p CE.
+///
+/// \param TAB - If given, a target asm backend to use to show the fixup
+/// information in conjunction with encoding information. This method takes
+/// ownership of \p TAB.
+///
+/// \param ShowInst - Whether to show the MCInst representation inline with
+/// the assembly.
+MCStreamer *
+createAsmStreamer(MCContext &Ctx, std::unique_ptr<formatted_raw_ostream> OS,
+ bool isVerboseAsm, bool useDwarfDirectory,
+ MCInstPrinter *InstPrint, std::unique_ptr<MCCodeEmitter> &&CE,
+ std::unique_ptr<MCAsmBackend> &&TAB, bool ShowInst);
+
+MCStreamer *createELFStreamer(MCContext &Ctx,
+ std::unique_ptr<MCAsmBackend> &&TAB,
+ std::unique_ptr<MCObjectWriter> &&OW,
+ std::unique_ptr<MCCodeEmitter> &&CE,
+ bool RelaxAll);
+MCStreamer *createMachOStreamer(MCContext &Ctx,
+ std::unique_ptr<MCAsmBackend> &&TAB,
+ std::unique_ptr<MCObjectWriter> &&OW,
+ std::unique_ptr<MCCodeEmitter> &&CE,
+ bool RelaxAll, bool DWARFMustBeAtTheEnd,
+ bool LabelSections = false);
+MCStreamer *createWasmStreamer(MCContext &Ctx,
+ std::unique_ptr<MCAsmBackend> &&TAB,
+ 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);
+
+MCSymbolizer *createMCSymbolizer(const Triple &TT, LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp,
+ void *DisInfo, MCContext *Ctx,
+ std::unique_ptr<MCRelocationInfo> &&RelInfo);
+
+/// Target - Wrapper for Target specific information.
+///
+/// For registration purposes, this is a POD type so that targets can be
+/// registered without the use of static constructors.
+///
+/// Targets should implement a single global instance of this class (which
+/// will be zero initialized), and pass that instance to the TargetRegistry as
+/// part of their initialization.
+class Target {
+public:
+ friend struct TargetRegistry;
+
+ using ArchMatchFnTy = bool (*)(Triple::ArchType Arch);
+
+ using MCAsmInfoCtorFnTy = MCAsmInfo *(*)(const MCRegisterInfo &MRI,
+ const Triple &TT,
+ const MCTargetOptions &Options);
+ using MCInstrInfoCtorFnTy = MCInstrInfo *(*)();
+ using MCInstrAnalysisCtorFnTy = MCInstrAnalysis *(*)(const MCInstrInfo *Info);
+ using MCRegInfoCtorFnTy = MCRegisterInfo *(*)(const Triple &TT);
+ using MCSubtargetInfoCtorFnTy = MCSubtargetInfo *(*)(const Triple &TT,
+ StringRef CPU,
+ StringRef Features);
+ using TargetMachineCtorTy = TargetMachine
+ *(*)(const Target &T, const Triple &TT, StringRef CPU, StringRef Features,
+ const TargetOptions &Options, Optional<Reloc::Model> RM,
+ Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT);
+ // If it weren't for layering issues (this header is in llvm/Support, but
+ // depends on MC?) this should take the Streamer by value rather than rvalue
+ // reference.
+ using AsmPrinterCtorTy = AsmPrinter *(*)(
+ TargetMachine &TM, std::unique_ptr<MCStreamer> &&Streamer);
+ using MCAsmBackendCtorTy = MCAsmBackend *(*)(const Target &T,
+ const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options);
+ using MCAsmParserCtorTy = MCTargetAsmParser *(*)(
+ const MCSubtargetInfo &STI, MCAsmParser &P, const MCInstrInfo &MII,
+ const MCTargetOptions &Options);
+ using MCDisassemblerCtorTy = MCDisassembler *(*)(const Target &T,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx);
+ using MCInstPrinterCtorTy = MCInstPrinter *(*)(const Triple &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI);
+ using MCCodeEmitterCtorTy = MCCodeEmitter *(*)(const MCInstrInfo &II,
+ const MCRegisterInfo &MRI,
+ MCContext &Ctx);
+ using ELFStreamerCtorTy =
+ MCStreamer *(*)(const Triple &T, MCContext &Ctx,
+ std::unique_ptr<MCAsmBackend> &&TAB,
+ std::unique_ptr<MCObjectWriter> &&OW,
+ std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll);
+ using MachOStreamerCtorTy =
+ MCStreamer *(*)(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB,
+ std::unique_ptr<MCObjectWriter> &&OW,
+ std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll,
+ bool DWARFMustBeAtTheEnd);
+ using COFFStreamerCtorTy =
+ MCStreamer *(*)(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB,
+ std::unique_ptr<MCObjectWriter> &&OW,
+ std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll,
+ bool IncrementalLinkerCompatible);
+ using WasmStreamerCtorTy =
+ MCStreamer *(*)(const Triple &T, MCContext &Ctx,
+ std::unique_ptr<MCAsmBackend> &&TAB,
+ std::unique_ptr<MCObjectWriter> &&OW,
+ std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll);
+ using NullTargetStreamerCtorTy = MCTargetStreamer *(*)(MCStreamer &S);
+ using AsmTargetStreamerCtorTy = MCTargetStreamer *(*)(
+ MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint,
+ bool IsVerboseAsm);
+ using ObjectTargetStreamerCtorTy = MCTargetStreamer *(*)(
+ MCStreamer &S, const MCSubtargetInfo &STI);
+ using MCRelocationInfoCtorTy = MCRelocationInfo *(*)(const Triple &TT,
+ MCContext &Ctx);
+ using MCSymbolizerCtorTy = MCSymbolizer *(*)(
+ const Triple &TT, LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx,
+ std::unique_ptr<MCRelocationInfo> &&RelInfo);
+
+private:
+ /// Next - The next registered target in the linked list, maintained by the
+ /// TargetRegistry.
+ Target *Next;
+
+ /// The target function for checking if an architecture is supported.
+ ArchMatchFnTy ArchMatchFn;
+
+ /// Name - The target name.
+ const char *Name;
+
+ /// ShortDesc - A short description of the target.
+ const char *ShortDesc;
+
+ /// BackendName - The name of the backend implementation. This must match the
+ /// name of the 'def X : Target ...' in TableGen.
+ const char *BackendName;
+
+ /// HasJIT - Whether this target supports the JIT.
+ bool HasJIT;
+
+ /// MCAsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if
+ /// registered.
+ MCAsmInfoCtorFnTy MCAsmInfoCtorFn;
+
+ /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo,
+ /// if registered.
+ MCInstrInfoCtorFnTy MCInstrInfoCtorFn;
+
+ /// MCInstrAnalysisCtorFn - Constructor function for this target's
+ /// MCInstrAnalysis, if registered.
+ MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn;
+
+ /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo,
+ /// if registered.
+ MCRegInfoCtorFnTy MCRegInfoCtorFn;
+
+ /// MCSubtargetInfoCtorFn - Constructor function for this target's
+ /// MCSubtargetInfo, if registered.
+ MCSubtargetInfoCtorFnTy MCSubtargetInfoCtorFn;
+
+ /// TargetMachineCtorFn - Construction function for this target's
+ /// TargetMachine, if registered.
+ TargetMachineCtorTy TargetMachineCtorFn;
+
+ /// MCAsmBackendCtorFn - Construction function for this target's
+ /// MCAsmBackend, if registered.
+ MCAsmBackendCtorTy MCAsmBackendCtorFn;
+
+ /// MCAsmParserCtorFn - Construction function for this target's
+ /// MCTargetAsmParser, if registered.
+ MCAsmParserCtorTy MCAsmParserCtorFn;
+
+ /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter,
+ /// if registered.
+ AsmPrinterCtorTy AsmPrinterCtorFn;
+
+ /// MCDisassemblerCtorFn - Construction function for this target's
+ /// MCDisassembler, if registered.
+ MCDisassemblerCtorTy MCDisassemblerCtorFn;
+
+ /// MCInstPrinterCtorFn - Construction function for this target's
+ /// MCInstPrinter, if registered.
+ MCInstPrinterCtorTy MCInstPrinterCtorFn;
+
+ /// MCCodeEmitterCtorFn - Construction function for this target's
+ /// CodeEmitter, if registered.
+ MCCodeEmitterCtorTy MCCodeEmitterCtorFn;
+
+ // Construction functions for the various object formats, if registered.
+ COFFStreamerCtorTy COFFStreamerCtorFn = nullptr;
+ MachOStreamerCtorTy MachOStreamerCtorFn = nullptr;
+ ELFStreamerCtorTy ELFStreamerCtorFn = nullptr;
+ WasmStreamerCtorTy WasmStreamerCtorFn = nullptr;
+
+ /// Construction function for this target's null TargetStreamer, if
+ /// registered (default = nullptr).
+ NullTargetStreamerCtorTy NullTargetStreamerCtorFn = nullptr;
+
+ /// Construction function for this target's asm TargetStreamer, if
+ /// registered (default = nullptr).
+ AsmTargetStreamerCtorTy AsmTargetStreamerCtorFn = nullptr;
+
+ /// Construction function for this target's obj TargetStreamer, if
+ /// registered (default = nullptr).
+ ObjectTargetStreamerCtorTy ObjectTargetStreamerCtorFn = nullptr;
+
+ /// MCRelocationInfoCtorFn - Construction function for this target's
+ /// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo)
+ MCRelocationInfoCtorTy MCRelocationInfoCtorFn = nullptr;
+
+ /// MCSymbolizerCtorFn - Construction function for this target's
+ /// MCSymbolizer, if registered (default = llvm::createMCSymbolizer)
+ MCSymbolizerCtorTy MCSymbolizerCtorFn = nullptr;
+
+public:
+ Target() = default;
+
+ /// @name Target Information
+ /// @{
+
+ // getNext - Return the next registered target.
+ const Target *getNext() const { return Next; }
+
+ /// getName - Get the target name.
+ const char *getName() const { return Name; }
+
+ /// getShortDescription - Get a short description of the target.
+ const char *getShortDescription() const { return ShortDesc; }
+
+ /// getBackendName - Get the backend name.
+ const char *getBackendName() const { return BackendName; }
+
+ /// @}
+ /// @name Feature Predicates
+ /// @{
+
+ /// hasJIT - Check if this targets supports the just-in-time compilation.
+ bool hasJIT() const { return HasJIT; }
+
+ /// hasTargetMachine - Check if this target supports code generation.
+ bool hasTargetMachine() const { return TargetMachineCtorFn != nullptr; }
+
+ /// hasMCAsmBackend - Check if this target supports .o generation.
+ bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != nullptr; }
+
+ /// hasMCAsmParser - Check if this target supports assembly parsing.
+ bool hasMCAsmParser() const { return MCAsmParserCtorFn != nullptr; }
+
+ /// @}
+ /// @name Feature Constructors
+ /// @{
+
+ /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified
+ /// target triple.
+ ///
+ /// \param TheTriple This argument is used to determine the target machine
+ /// feature set; it should always be provided. Generally this should be
+ /// either the target triple from the module, or the target triple of the
+ /// host if that does not exist.
+ MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI, StringRef TheTriple,
+ const MCTargetOptions &Options) const {
+ if (!MCAsmInfoCtorFn)
+ return nullptr;
+ return MCAsmInfoCtorFn(MRI, Triple(TheTriple), Options);
+ }
+
+ /// createMCInstrInfo - Create a MCInstrInfo implementation.
+ ///
+ MCInstrInfo *createMCInstrInfo() const {
+ if (!MCInstrInfoCtorFn)
+ return nullptr;
+ return MCInstrInfoCtorFn();
+ }
+
+ /// createMCInstrAnalysis - Create a MCInstrAnalysis implementation.
+ ///
+ MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const {
+ if (!MCInstrAnalysisCtorFn)
+ return nullptr;
+ return MCInstrAnalysisCtorFn(Info);
+ }
+
+ /// createMCRegInfo - Create a MCRegisterInfo implementation.
+ ///
+ MCRegisterInfo *createMCRegInfo(StringRef TT) const {
+ if (!MCRegInfoCtorFn)
+ return nullptr;
+ return MCRegInfoCtorFn(Triple(TT));
+ }
+
+ /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation.
+ ///
+ /// \param TheTriple This argument is used to determine the target machine
+ /// feature set; it should always be provided. Generally this should be
+ /// either the target triple from the module, or the target triple of the
+ /// host if that does not exist.
+ /// \param CPU This specifies the name of the target CPU.
+ /// \param Features This specifies the string representation of the
+ /// additional target features.
+ MCSubtargetInfo *createMCSubtargetInfo(StringRef TheTriple, StringRef CPU,
+ StringRef Features) const {
+ if (!MCSubtargetInfoCtorFn)
+ return nullptr;
+ return MCSubtargetInfoCtorFn(Triple(TheTriple), CPU, Features);
+ }
+
+ /// createTargetMachine - Create a target specific machine implementation
+ /// for the specified \p Triple.
+ ///
+ /// \param TT This argument is used to determine the target machine
+ /// feature set; it should always be provided. Generally this should be
+ /// either the target triple from the module, or the target triple of the
+ /// host if that does not exist.
+ TargetMachine *createTargetMachine(StringRef TT, StringRef CPU,
+ StringRef Features,
+ const TargetOptions &Options,
+ Optional<Reloc::Model> RM,
+ Optional<CodeModel::Model> CM = None,
+ CodeGenOpt::Level OL = CodeGenOpt::Default,
+ bool JIT = false) const {
+ if (!TargetMachineCtorFn)
+ return nullptr;
+ return TargetMachineCtorFn(*this, Triple(TT), CPU, Features, Options, RM,
+ CM, OL, JIT);
+ }
+
+ /// createMCAsmBackend - Create a target specific assembly parser.
+ MCAsmBackend *createMCAsmBackend(const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options) const {
+ if (!MCAsmBackendCtorFn)
+ return nullptr;
+ return MCAsmBackendCtorFn(*this, STI, MRI, Options);
+ }
+
+ /// createMCAsmParser - Create a target specific assembly parser.
+ ///
+ /// \param Parser The target independent parser implementation to use for
+ /// parsing and lexing.
+ MCTargetAsmParser *createMCAsmParser(const MCSubtargetInfo &STI,
+ MCAsmParser &Parser,
+ const MCInstrInfo &MII,
+ const MCTargetOptions &Options) const {
+ if (!MCAsmParserCtorFn)
+ return nullptr;
+ return MCAsmParserCtorFn(STI, Parser, MII, Options);
+ }
+
+ /// createAsmPrinter - Create a target specific assembly printer pass. This
+ /// takes ownership of the MCStreamer object.
+ AsmPrinter *createAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> &&Streamer) const {
+ if (!AsmPrinterCtorFn)
+ return nullptr;
+ return AsmPrinterCtorFn(TM, std::move(Streamer));
+ }
+
+ MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI,
+ MCContext &Ctx) const {
+ if (!MCDisassemblerCtorFn)
+ return nullptr;
+ return MCDisassemblerCtorFn(*this, STI, Ctx);
+ }
+
+ MCInstPrinter *createMCInstPrinter(const Triple &T, unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI) const {
+ if (!MCInstPrinterCtorFn)
+ return nullptr;
+ return MCInstPrinterCtorFn(T, SyntaxVariant, MAI, MII, MRI);
+ }
+
+ /// createMCCodeEmitter - Create a target specific code emitter.
+ MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II,
+ const MCRegisterInfo &MRI,
+ MCContext &Ctx) const {
+ if (!MCCodeEmitterCtorFn)
+ return nullptr;
+ return MCCodeEmitterCtorFn(II, MRI, Ctx);
+ }
+
+ /// Create a target specific MCStreamer.
+ ///
+ /// \param T The target triple.
+ /// \param Ctx The target context.
+ /// \param TAB The target assembler backend object. Takes ownership.
+ /// \param OW The stream object.
+ /// \param Emitter The target independent assembler object.Takes ownership.
+ /// \param RelaxAll Relax all fixups?
+ MCStreamer *createMCObjectStreamer(const Triple &T, MCContext &Ctx,
+ std::unique_ptr<MCAsmBackend> &&TAB,
+ std::unique_ptr<MCObjectWriter> &&OW,
+ std::unique_ptr<MCCodeEmitter> &&Emitter,
+ const MCSubtargetInfo &STI, bool RelaxAll,
+ bool IncrementalLinkerCompatible,
+ bool DWARFMustBeAtTheEnd) const {
+ MCStreamer *S = nullptr;
+ switch (T.getObjectFormat()) {
+ case Triple::UnknownObjectFormat:
+ llvm_unreachable("Unknown object format");
+ case Triple::COFF:
+ assert(T.isOSWindows() && "only Windows COFF is supported");
+ S = COFFStreamerCtorFn(Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll,
+ IncrementalLinkerCompatible);
+ break;
+ case Triple::MachO:
+ if (MachOStreamerCtorFn)
+ S = MachOStreamerCtorFn(Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll,
+ DWARFMustBeAtTheEnd);
+ else
+ S = createMachOStreamer(Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll,
+ DWARFMustBeAtTheEnd);
+ break;
+ case Triple::ELF:
+ if (ELFStreamerCtorFn)
+ S = ELFStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll);
+ else
+ S = createELFStreamer(Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll);
+ break;
+ case Triple::Wasm:
+ if (WasmStreamerCtorFn)
+ S = WasmStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll);
+ else
+ 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);
+ return S;
+ }
+
+ MCStreamer *createAsmStreamer(MCContext &Ctx,
+ std::unique_ptr<formatted_raw_ostream> OS,
+ bool IsVerboseAsm, bool UseDwarfDirectory,
+ MCInstPrinter *InstPrint,
+ std::unique_ptr<MCCodeEmitter> &&CE,
+ std::unique_ptr<MCAsmBackend> &&TAB,
+ bool ShowInst) const {
+ formatted_raw_ostream &OSRef = *OS;
+ MCStreamer *S = llvm::createAsmStreamer(
+ Ctx, std::move(OS), IsVerboseAsm, UseDwarfDirectory, InstPrint,
+ std::move(CE), std::move(TAB), ShowInst);
+ createAsmTargetStreamer(*S, OSRef, InstPrint, IsVerboseAsm);
+ return S;
+ }
+
+ MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S,
+ formatted_raw_ostream &OS,
+ MCInstPrinter *InstPrint,
+ bool IsVerboseAsm) const {
+ if (AsmTargetStreamerCtorFn)
+ return AsmTargetStreamerCtorFn(S, OS, InstPrint, IsVerboseAsm);
+ return nullptr;
+ }
+
+ MCStreamer *createNullStreamer(MCContext &Ctx) const {
+ MCStreamer *S = llvm::createNullStreamer(Ctx);
+ createNullTargetStreamer(*S);
+ return S;
+ }
+
+ MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) const {
+ if (NullTargetStreamerCtorFn)
+ return NullTargetStreamerCtorFn(S);
+ return nullptr;
+ }
+
+ /// createMCRelocationInfo - Create a target specific MCRelocationInfo.
+ ///
+ /// \param TT The target triple.
+ /// \param Ctx The target context.
+ MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx) const {
+ MCRelocationInfoCtorTy Fn = MCRelocationInfoCtorFn
+ ? MCRelocationInfoCtorFn
+ : llvm::createMCRelocationInfo;
+ return Fn(Triple(TT), Ctx);
+ }
+
+ /// createMCSymbolizer - Create a target specific MCSymbolizer.
+ ///
+ /// \param TT The target triple.
+ /// \param GetOpInfo The function to get the symbolic information for
+ /// operands.
+ /// \param SymbolLookUp The function to lookup a symbol name.
+ /// \param DisInfo The pointer to the block of symbolic information for above
+ /// call
+ /// back.
+ /// \param Ctx The target context.
+ /// \param RelInfo The relocation information for this target. Takes
+ /// ownership.
+ MCSymbolizer *
+ createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo,
+ MCContext *Ctx,
+ std::unique_ptr<MCRelocationInfo> &&RelInfo) const {
+ MCSymbolizerCtorTy Fn =
+ MCSymbolizerCtorFn ? MCSymbolizerCtorFn : llvm::createMCSymbolizer;
+ return Fn(Triple(TT), GetOpInfo, SymbolLookUp, DisInfo, Ctx,
+ std::move(RelInfo));
+ }
+
+ /// @}
+};
+
+/// TargetRegistry - Generic interface to target specific features.
+struct TargetRegistry {
+ // FIXME: Make this a namespace, probably just move all the Register*
+ // functions into Target (currently they all just set members on the Target
+ // anyway, and Target friends this class so those functions can...
+ // function).
+ TargetRegistry() = delete;
+
+ class iterator
+ : public std::iterator<std::forward_iterator_tag, Target, ptrdiff_t> {
+ friend struct TargetRegistry;
+
+ const Target *Current = nullptr;
+
+ explicit iterator(Target *T) : Current(T) {}
+
+ public:
+ iterator() = default;
+
+ bool operator==(const iterator &x) const { return Current == x.Current; }
+ bool operator!=(const iterator &x) const { return !operator==(x); }
+
+ // Iterator traversal: forward iteration only
+ iterator &operator++() { // Preincrement
+ assert(Current && "Cannot increment end iterator!");
+ Current = Current->getNext();
+ return *this;
+ }
+ iterator operator++(int) { // Postincrement
+ iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ const Target &operator*() const {
+ assert(Current && "Cannot dereference end iterator!");
+ return *Current;
+ }
+
+ const Target *operator->() const { return &operator*(); }
+ };
+
+ /// printRegisteredTargetsForVersion - Print the registered targets
+ /// appropriately for inclusion in a tool's version output.
+ static void printRegisteredTargetsForVersion(raw_ostream &OS);
+
+ /// @name Registry Access
+ /// @{
+
+ static iterator_range<iterator> targets();
+
+ /// lookupTarget - Lookup a target based on a target triple.
+ ///
+ /// \param Triple - The triple to use for finding a target.
+ /// \param Error - On failure, an error string describing why no target was
+ /// found.
+ static const Target *lookupTarget(const std::string &Triple,
+ std::string &Error);
+
+ /// lookupTarget - Lookup a target based on an architecture name
+ /// and a target triple. If the architecture name is non-empty,
+ /// then the lookup is done by architecture. Otherwise, the target
+ /// triple is used.
+ ///
+ /// \param ArchName - The architecture to use for finding a target.
+ /// \param TheTriple - The triple to use for finding a target. The
+ /// triple is updated with canonical architecture name if a lookup
+ /// by architecture is done.
+ /// \param Error - On failure, an error string describing why no target was
+ /// found.
+ static const Target *lookupTarget(const std::string &ArchName,
+ Triple &TheTriple, std::string &Error);
+
+ /// @}
+ /// @name Target Registration
+ /// @{
+
+ /// RegisterTarget - Register the given target. Attempts to register a
+ /// target which has already been registered will be ignored.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Name - The target name. This should be a static string.
+ /// @param ShortDesc - A short target description. This should be a static
+ /// string.
+ /// @param BackendName - The name of the backend. This should be a static
+ /// string that is the same for all targets that share a backend
+ /// implementation and must match the name used in the 'def X : Target ...' in
+ /// TableGen.
+ /// @param ArchMatchFn - The arch match checking function for this target.
+ /// @param HasJIT - Whether the target supports JIT code
+ /// generation.
+ static void RegisterTarget(Target &T, const char *Name, const char *ShortDesc,
+ const char *BackendName,
+ Target::ArchMatchFnTy ArchMatchFn,
+ bool HasJIT = false);
+
+ /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCAsmInfo for the target.
+ static void RegisterMCAsmInfo(Target &T, Target::MCAsmInfoCtorFnTy Fn) {
+ T.MCAsmInfoCtorFn = Fn;
+ }
+
+ /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCInstrInfo for the target.
+ static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) {
+ T.MCInstrInfoCtorFn = Fn;
+ }
+
+ /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for
+ /// the given target.
+ static void RegisterMCInstrAnalysis(Target &T,
+ Target::MCInstrAnalysisCtorFnTy Fn) {
+ T.MCInstrAnalysisCtorFn = Fn;
+ }
+
+ /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCRegisterInfo for the target.
+ static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) {
+ T.MCRegInfoCtorFn = Fn;
+ }
+
+ /// RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for
+ /// the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a MCSubtargetInfo for the target.
+ static void RegisterMCSubtargetInfo(Target &T,
+ Target::MCSubtargetInfoCtorFnTy Fn) {
+ T.MCSubtargetInfoCtorFn = Fn;
+ }
+
+ /// RegisterTargetMachine - Register a TargetMachine implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct a TargetMachine for the target.
+ static void RegisterTargetMachine(Target &T, Target::TargetMachineCtorTy Fn) {
+ T.TargetMachineCtorFn = Fn;
+ }
+
+ /// RegisterMCAsmBackend - Register a MCAsmBackend implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an AsmBackend for the target.
+ static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn) {
+ T.MCAsmBackendCtorFn = Fn;
+ }
+
+ /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for
+ /// the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCTargetAsmParser for the target.
+ static void RegisterMCAsmParser(Target &T, Target::MCAsmParserCtorTy Fn) {
+ T.MCAsmParserCtorFn = Fn;
+ }
+
+ /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given
+ /// target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an AsmPrinter for the target.
+ static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) {
+ T.AsmPrinterCtorFn = Fn;
+ }
+
+ /// RegisterMCDisassembler - Register a MCDisassembler implementation for
+ /// the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCDisassembler for the target.
+ static void RegisterMCDisassembler(Target &T,
+ Target::MCDisassemblerCtorTy Fn) {
+ T.MCDisassemblerCtorFn = Fn;
+ }
+
+ /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCInstPrinter for the target.
+ static void RegisterMCInstPrinter(Target &T, Target::MCInstPrinterCtorTy Fn) {
+ T.MCInstPrinterCtorFn = Fn;
+ }
+
+ /// RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the
+ /// given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCCodeEmitter for the target.
+ static void RegisterMCCodeEmitter(Target &T, Target::MCCodeEmitterCtorTy Fn) {
+ T.MCCodeEmitterCtorFn = Fn;
+ }
+
+ static void RegisterCOFFStreamer(Target &T, Target::COFFStreamerCtorTy Fn) {
+ T.COFFStreamerCtorFn = Fn;
+ }
+
+ static void RegisterMachOStreamer(Target &T, Target::MachOStreamerCtorTy Fn) {
+ T.MachOStreamerCtorFn = Fn;
+ }
+
+ static void RegisterELFStreamer(Target &T, Target::ELFStreamerCtorTy Fn) {
+ T.ELFStreamerCtorFn = Fn;
+ }
+
+ static void RegisterWasmStreamer(Target &T, Target::WasmStreamerCtorTy Fn) {
+ T.WasmStreamerCtorFn = Fn;
+ }
+
+ static void RegisterNullTargetStreamer(Target &T,
+ Target::NullTargetStreamerCtorTy Fn) {
+ T.NullTargetStreamerCtorFn = Fn;
+ }
+
+ static void RegisterAsmTargetStreamer(Target &T,
+ Target::AsmTargetStreamerCtorTy Fn) {
+ T.AsmTargetStreamerCtorFn = Fn;
+ }
+
+ static void
+ RegisterObjectTargetStreamer(Target &T,
+ Target::ObjectTargetStreamerCtorTy Fn) {
+ T.ObjectTargetStreamerCtorFn = Fn;
+ }
+
+ /// RegisterMCRelocationInfo - Register an MCRelocationInfo
+ /// implementation for the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCRelocationInfo for the target.
+ static void RegisterMCRelocationInfo(Target &T,
+ Target::MCRelocationInfoCtorTy Fn) {
+ T.MCRelocationInfoCtorFn = Fn;
+ }
+
+ /// RegisterMCSymbolizer - Register an MCSymbolizer
+ /// implementation for the given target.
+ ///
+ /// Clients are responsible for ensuring that registration doesn't occur
+ /// while another thread is attempting to access the registry. Typically
+ /// this is done by initializing all targets at program startup.
+ ///
+ /// @param T - The target being registered.
+ /// @param Fn - A function to construct an MCSymbolizer for the target.
+ static void RegisterMCSymbolizer(Target &T, Target::MCSymbolizerCtorTy Fn) {
+ T.MCSymbolizerCtorFn = Fn;
+ }
+
+ /// @}
+};
+
+//===--------------------------------------------------------------------===//
+
+/// RegisterTarget - Helper template for registering a target, for use in the
+/// target's initialization function. Usage:
+///
+///
+/// Target &getTheFooTarget() { // The global target instance.
+/// static Target TheFooTarget;
+/// return TheFooTarget;
+/// }
+/// extern "C" void LLVMInitializeFooTargetInfo() {
+/// RegisterTarget<Triple::foo> X(getTheFooTarget(), "foo", "Foo
+/// description", "Foo" /* Backend Name */);
+/// }
+template <Triple::ArchType TargetArchType = Triple::UnknownArch,
+ bool HasJIT = false>
+struct RegisterTarget {
+ RegisterTarget(Target &T, const char *Name, const char *Desc,
+ const char *BackendName) {
+ TargetRegistry::RegisterTarget(T, Name, Desc, BackendName, &getArchMatch,
+ HasJIT);
+ }
+
+ static bool getArchMatch(Triple::ArchType Arch) {
+ return Arch == TargetArchType;
+ }
+};
+
+/// RegisterMCAsmInfo - Helper template for registering a target assembly info
+/// implementation. This invokes the static "Create" method on the class to
+/// actually do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCAsmInfo<FooMCAsmInfo> X(TheFooTarget);
+/// }
+template <class MCAsmInfoImpl> struct RegisterMCAsmInfo {
+ RegisterMCAsmInfo(Target &T) {
+ TargetRegistry::RegisterMCAsmInfo(T, &Allocator);
+ }
+
+private:
+ static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/, const Triple &TT,
+ const MCTargetOptions &Options) {
+ return new MCAsmInfoImpl(TT, Options);
+ }
+};
+
+/// RegisterMCAsmInfoFn - Helper template for registering a target assembly info
+/// implementation. This invokes the specified function to do the
+/// construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCAsmInfoFn X(TheFooTarget, TheFunction);
+/// }
+struct RegisterMCAsmInfoFn {
+ RegisterMCAsmInfoFn(Target &T, Target::MCAsmInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCAsmInfo(T, Fn);
+ }
+};
+
+/// RegisterMCInstrInfo - Helper template for registering a target instruction
+/// info implementation. This invokes the static "Create" method on the class
+/// to actually do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCInstrInfo<FooMCInstrInfo> X(TheFooTarget);
+/// }
+template <class MCInstrInfoImpl> struct RegisterMCInstrInfo {
+ RegisterMCInstrInfo(Target &T) {
+ TargetRegistry::RegisterMCInstrInfo(T, &Allocator);
+ }
+
+private:
+ static MCInstrInfo *Allocator() { return new MCInstrInfoImpl(); }
+};
+
+/// RegisterMCInstrInfoFn - Helper template for registering a target
+/// instruction info implementation. This invokes the specified function to
+/// do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction);
+/// }
+struct RegisterMCInstrInfoFn {
+ RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCInstrInfo(T, Fn);
+ }
+};
+
+/// RegisterMCInstrAnalysis - Helper template for registering a target
+/// instruction analyzer implementation. This invokes the static "Create"
+/// method on the class to actually do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCInstrAnalysis<FooMCInstrAnalysis> X(TheFooTarget);
+/// }
+template <class MCInstrAnalysisImpl> struct RegisterMCInstrAnalysis {
+ RegisterMCInstrAnalysis(Target &T) {
+ TargetRegistry::RegisterMCInstrAnalysis(T, &Allocator);
+ }
+
+private:
+ static MCInstrAnalysis *Allocator(const MCInstrInfo *Info) {
+ return new MCInstrAnalysisImpl(Info);
+ }
+};
+
+/// RegisterMCInstrAnalysisFn - Helper template for registering a target
+/// instruction analyzer implementation. This invokes the specified function
+/// to do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCInstrAnalysisFn X(TheFooTarget, TheFunction);
+/// }
+struct RegisterMCInstrAnalysisFn {
+ RegisterMCInstrAnalysisFn(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) {
+ TargetRegistry::RegisterMCInstrAnalysis(T, Fn);
+ }
+};
+
+/// RegisterMCRegInfo - Helper template for registering a target register info
+/// implementation. This invokes the static "Create" method on the class to
+/// actually do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCRegInfo<FooMCRegInfo> X(TheFooTarget);
+/// }
+template <class MCRegisterInfoImpl> struct RegisterMCRegInfo {
+ RegisterMCRegInfo(Target &T) {
+ TargetRegistry::RegisterMCRegInfo(T, &Allocator);
+ }
+
+private:
+ static MCRegisterInfo *Allocator(const Triple & /*TT*/) {
+ return new MCRegisterInfoImpl();
+ }
+};
+
+/// RegisterMCRegInfoFn - Helper template for registering a target register
+/// info implementation. This invokes the specified function to do the
+/// construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCRegInfoFn X(TheFooTarget, TheFunction);
+/// }
+struct RegisterMCRegInfoFn {
+ RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCRegInfo(T, Fn);
+ }
+};
+
+/// RegisterMCSubtargetInfo - Helper template for registering a target
+/// subtarget info implementation. This invokes the static "Create" method
+/// on the class to actually do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCSubtargetInfo<FooMCSubtargetInfo> X(TheFooTarget);
+/// }
+template <class MCSubtargetInfoImpl> struct RegisterMCSubtargetInfo {
+ RegisterMCSubtargetInfo(Target &T) {
+ TargetRegistry::RegisterMCSubtargetInfo(T, &Allocator);
+ }
+
+private:
+ static MCSubtargetInfo *Allocator(const Triple & /*TT*/, StringRef /*CPU*/,
+ StringRef /*FS*/) {
+ return new MCSubtargetInfoImpl();
+ }
+};
+
+/// RegisterMCSubtargetInfoFn - Helper template for registering a target
+/// subtarget info implementation. This invokes the specified function to
+/// do the construction. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterMCSubtargetInfoFn X(TheFooTarget, TheFunction);
+/// }
+struct RegisterMCSubtargetInfoFn {
+ RegisterMCSubtargetInfoFn(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) {
+ TargetRegistry::RegisterMCSubtargetInfo(T, Fn);
+ }
+};
+
+/// RegisterTargetMachine - Helper template for registering a target machine
+/// implementation, for use in the target machine initialization
+/// function. Usage:
+///
+/// extern "C" void LLVMInitializeFooTarget() {
+/// extern Target TheFooTarget;
+/// RegisterTargetMachine<FooTargetMachine> X(TheFooTarget);
+/// }
+template <class TargetMachineImpl> struct RegisterTargetMachine {
+ RegisterTargetMachine(Target &T) {
+ TargetRegistry::RegisterTargetMachine(T, &Allocator);
+ }
+
+private:
+ static TargetMachine *
+ Allocator(const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
+ const TargetOptions &Options, Optional<Reloc::Model> RM,
+ Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT) {
+ return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL, JIT);
+ }
+};
+
+/// RegisterMCAsmBackend - Helper template for registering a target specific
+/// assembler backend. Usage:
+///
+/// extern "C" void LLVMInitializeFooMCAsmBackend() {
+/// extern Target TheFooTarget;
+/// RegisterMCAsmBackend<FooAsmLexer> X(TheFooTarget);
+/// }
+template <class MCAsmBackendImpl> struct RegisterMCAsmBackend {
+ RegisterMCAsmBackend(Target &T) {
+ TargetRegistry::RegisterMCAsmBackend(T, &Allocator);
+ }
+
+private:
+ static MCAsmBackend *Allocator(const Target &T, const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options) {
+ return new MCAsmBackendImpl(T, STI, MRI);
+ }
+};
+
+/// RegisterMCAsmParser - Helper template for registering a target specific
+/// assembly parser, for use in the target machine initialization
+/// function. Usage:
+///
+/// extern "C" void LLVMInitializeFooMCAsmParser() {
+/// extern Target TheFooTarget;
+/// RegisterMCAsmParser<FooAsmParser> X(TheFooTarget);
+/// }
+template <class MCAsmParserImpl> struct RegisterMCAsmParser {
+ RegisterMCAsmParser(Target &T) {
+ TargetRegistry::RegisterMCAsmParser(T, &Allocator);
+ }
+
+private:
+ static MCTargetAsmParser *Allocator(const MCSubtargetInfo &STI,
+ MCAsmParser &P, const MCInstrInfo &MII,
+ const MCTargetOptions &Options) {
+ return new MCAsmParserImpl(STI, P, MII, Options);
+ }
+};
+
+/// RegisterAsmPrinter - Helper template for registering a target specific
+/// assembly printer, for use in the target machine initialization
+/// function. Usage:
+///
+/// extern "C" void LLVMInitializeFooAsmPrinter() {
+/// extern Target TheFooTarget;
+/// RegisterAsmPrinter<FooAsmPrinter> X(TheFooTarget);
+/// }
+template <class AsmPrinterImpl> struct RegisterAsmPrinter {
+ RegisterAsmPrinter(Target &T) {
+ TargetRegistry::RegisterAsmPrinter(T, &Allocator);
+ }
+
+private:
+ static AsmPrinter *Allocator(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> &&Streamer) {
+ return new AsmPrinterImpl(TM, std::move(Streamer));
+ }
+};
+
+/// RegisterMCCodeEmitter - Helper template for registering a target specific
+/// machine code emitter, for use in the target initialization
+/// function. Usage:
+///
+/// extern "C" void LLVMInitializeFooMCCodeEmitter() {
+/// extern Target TheFooTarget;
+/// RegisterMCCodeEmitter<FooCodeEmitter> X(TheFooTarget);
+/// }
+template <class MCCodeEmitterImpl> struct RegisterMCCodeEmitter {
+ RegisterMCCodeEmitter(Target &T) {
+ TargetRegistry::RegisterMCCodeEmitter(T, &Allocator);
+ }
+
+private:
+ static MCCodeEmitter *Allocator(const MCInstrInfo & /*II*/,
+ const MCRegisterInfo & /*MRI*/,
+ MCContext & /*Ctx*/) {
+ return new MCCodeEmitterImpl();
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_TARGETREGISTRY_H
diff --git a/third_party/llvm-project/include/llvm/Support/Threading.h b/third_party/llvm-project/include/llvm/Support/Threading.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Threading.h
diff --git a/third_party/llvm-project/include/llvm/Support/TypeSize.h b/third_party/llvm-project/include/llvm/Support/TypeSize.h
new file mode 100644
index 000000000..711679cdc
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/TypeSize.h
@@ -0,0 +1,201 @@
+//===- TypeSize.h - Wrapper around type sizes -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a struct that can be used to query the size of IR types
+// which may be scalable vectors. It provides convenience operators so that
+// it can be used in much the same way as a single scalar value.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TYPESIZE_H
+#define LLVM_SUPPORT_TYPESIZE_H
+
+#include <cassert>
+#include <tuple>
+
+namespace llvm {
+
+class ElementCount {
+public:
+ unsigned Min; // Minimum number of vector elements.
+ bool Scalable; // If true, NumElements is a multiple of 'Min' determined
+ // at runtime rather than compile time.
+
+ ElementCount(unsigned Min, bool Scalable)
+ : Min(Min), Scalable(Scalable) {}
+
+ ElementCount operator*(unsigned RHS) {
+ return { Min * RHS, Scalable };
+ }
+ ElementCount operator/(unsigned RHS) {
+ return { Min / RHS, Scalable };
+ }
+
+ bool operator==(const ElementCount& RHS) const {
+ return Min == RHS.Min && Scalable == RHS.Scalable;
+ }
+ bool operator!=(const ElementCount& RHS) const {
+ return !(*this == RHS);
+ }
+};
+
+// This class is used to represent the size of types. If the type is of fixed
+// size, it will represent the exact size. If the type is a scalable vector,
+// it will represent the known minimum size.
+class TypeSize {
+ uint64_t MinSize; // The known minimum size.
+ bool IsScalable; // If true, then the runtime size is an integer multiple
+ // of MinSize.
+
+public:
+ constexpr TypeSize(uint64_t MinSize, bool Scalable)
+ : MinSize(MinSize), IsScalable(Scalable) {}
+
+ static constexpr TypeSize Fixed(uint64_t Size) {
+ return TypeSize(Size, /*IsScalable=*/false);
+ }
+
+ static constexpr TypeSize Scalable(uint64_t MinSize) {
+ return TypeSize(MinSize, /*IsScalable=*/true);
+ }
+
+ // Scalable vector types with the same minimum size as a fixed size type are
+ // not guaranteed to be the same size at runtime, so they are never
+ // considered to be equal.
+ friend bool operator==(const TypeSize &LHS, const TypeSize &RHS) {
+ return std::tie(LHS.MinSize, LHS.IsScalable) ==
+ std::tie(RHS.MinSize, RHS.IsScalable);
+ }
+
+ friend bool operator!=(const TypeSize &LHS, const TypeSize &RHS) {
+ return !(LHS == RHS);
+ }
+
+ // For many cases, size ordering between scalable and fixed size types cannot
+ // be determined at compile time, so such comparisons aren't allowed.
+ //
+ // e.g. <vscale x 2 x i16> could be bigger than <4 x i32> with a runtime
+ // vscale >= 5, equal sized with a vscale of 4, and smaller with
+ // a vscale <= 3.
+ //
+ // If the scalable flags match, just perform the requested comparison
+ // between the minimum sizes.
+ friend bool operator<(const TypeSize &LHS, const TypeSize &RHS) {
+ assert(LHS.IsScalable == RHS.IsScalable &&
+ "Ordering comparison of scalable and fixed types");
+
+ return LHS.MinSize < RHS.MinSize;
+ }
+
+ friend bool operator>(const TypeSize &LHS, const TypeSize &RHS) {
+ return RHS < LHS;
+ }
+
+ friend bool operator<=(const TypeSize &LHS, const TypeSize &RHS) {
+ return !(RHS < LHS);
+ }
+
+ friend bool operator>=(const TypeSize &LHS, const TypeSize& RHS) {
+ return !(LHS < RHS);
+ }
+
+ // Convenience operators to obtain relative sizes independently of
+ // the scalable flag.
+ TypeSize operator*(unsigned RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ friend TypeSize operator*(const unsigned LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ TypeSize operator/(unsigned RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+
+ // Return the minimum size with the assumption that the size is exact.
+ // Use in places where a scalable size doesn't make sense (e.g. non-vector
+ // types, or vectors in backends which don't support scalable vectors).
+ uint64_t getFixedSize() const {
+ assert(!IsScalable && "Request for a fixed size on a scalable object");
+ return MinSize;
+ }
+
+ // Return the known minimum size. Use in places where the scalable property
+ // doesn't matter (e.g. determining alignment) or in conjunction with the
+ // isScalable method below.
+ uint64_t getKnownMinSize() const {
+ return MinSize;
+ }
+
+ // Return whether or not the size is scalable.
+ bool isScalable() const {
+ return IsScalable;
+ }
+
+ // Casts to a uint64_t if this is a fixed-width size.
+ //
+ // NOTE: This interface is obsolete and will be removed in a future version
+ // of LLVM in favour of calling getFixedSize() directly.
+ operator uint64_t() const {
+ return getFixedSize();
+ }
+
+ // Additional convenience operators needed to avoid ambiguous parses.
+ // TODO: Make uint64_t the default operator?
+ TypeSize operator*(uint64_t RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ TypeSize operator*(int RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ TypeSize operator*(int64_t RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ friend TypeSize operator*(const uint64_t LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ friend TypeSize operator*(const int LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ friend TypeSize operator*(const int64_t LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ TypeSize operator/(uint64_t RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+
+ TypeSize operator/(int RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+
+ TypeSize operator/(int64_t RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+};
+
+/// Returns a TypeSize with a known minimum size that is the next integer
+/// (mod 2**64) that is greater than or equal to \p Value and is a multiple
+/// of \p Align. \p Align must be non-zero.
+///
+/// Similar to the alignTo functions in MathExtras.h
+inline TypeSize alignTo(TypeSize Size, uint64_t Align) {
+ assert(Align != 0u && "Align must be non-zero");
+ return {(Size.getKnownMinSize() + Align - 1) / Align * Align,
+ Size.isScalable()};
+}
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_TypeSize_H
diff --git a/third_party/llvm-project/include/llvm/Support/Unicode.h b/third_party/llvm-project/include/llvm/Support/Unicode.h
new file mode 100644
index 000000000..ca17bba2f
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/Unicode.h
@@ -0,0 +1,70 @@
+//===- llvm/Support/Unicode.h - Unicode character properties -*- 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 functions that allow querying certain properties of Unicode
+// characters.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_UNICODE_H
+#define LLVM_SUPPORT_UNICODE_H
+
+namespace llvm {
+class StringRef;
+
+namespace sys {
+namespace unicode {
+
+enum ColumnWidthErrors {
+ ErrorInvalidUTF8 = -2,
+ ErrorNonPrintableCharacter = -1
+};
+
+/// Determines if a character is likely to be displayed correctly on the
+/// terminal. Exact implementation would have to depend on the specific
+/// terminal, so we define the semantic that should be suitable for generic case
+/// of a terminal capable to output Unicode characters.
+///
+/// All characters from the Unicode code point range are considered printable
+/// except for:
+/// * C0 and C1 control character ranges;
+/// * default ignorable code points as per 5.21 of
+/// http://www.unicode.org/versions/Unicode6.2.0/UnicodeStandard-6.2.pdf
+/// except for U+00AD SOFT HYPHEN, as it's actually displayed on most
+/// terminals;
+/// * format characters (category = Cf);
+/// * surrogates (category = Cs);
+/// * unassigned characters (category = Cn).
+/// \return true if the character is considered printable.
+bool isPrintable(int UCS);
+
+/// Gets the number of positions the UTF8-encoded \p Text is likely to occupy
+/// when output on a terminal ("character width"). This depends on the
+/// implementation of the terminal, and there's no standard definition of
+/// character width.
+///
+/// The implementation defines it in a way that is expected to be compatible
+/// with a generic Unicode-capable terminal.
+///
+/// \return Character width:
+/// * ErrorNonPrintableCharacter (-1) if \p Text contains non-printable
+/// characters (as identified by isPrintable);
+/// * 0 for each non-spacing and enclosing combining mark;
+/// * 2 for each CJK character excluding halfwidth forms;
+/// * 1 for each of the remaining characters.
+int columnWidthUTF8(StringRef Text);
+
+/// Fold input unicode character according the Simple unicode case folding
+/// rules.
+int foldCharSimple(int C);
+
+} // namespace unicode
+} // namespace sys
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/UnicodeCharRanges.h b/third_party/llvm-project/include/llvm/Support/UnicodeCharRanges.h
new file mode 100644
index 000000000..73d3603b7
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/UnicodeCharRanges.h
@@ -0,0 +1,103 @@
+//===--- UnicodeCharRanges.h - Types and functions for character ranges ---===//
+//
+// 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_UNICODECHARRANGES_H
+#define LLVM_SUPPORT_UNICODECHARRANGES_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+
+#define DEBUG_TYPE "unicode"
+
+namespace llvm {
+namespace sys {
+
+/// Represents a closed range of Unicode code points [Lower, Upper].
+struct UnicodeCharRange {
+ uint32_t Lower;
+ uint32_t Upper;
+};
+
+inline bool operator<(uint32_t Value, UnicodeCharRange Range) {
+ return Value < Range.Lower;
+}
+inline bool operator<(UnicodeCharRange Range, uint32_t Value) {
+ return Range.Upper < Value;
+}
+
+/// Holds a reference to an ordered array of UnicodeCharRange and allows
+/// to quickly check if a code point is contained in the set represented by this
+/// array.
+class UnicodeCharSet {
+public:
+ typedef ArrayRef<UnicodeCharRange> CharRanges;
+
+ /// Constructs a UnicodeCharSet instance from an array of
+ /// UnicodeCharRanges.
+ ///
+ /// Array pointed by \p Ranges should have the lifetime at least as long as
+ /// the UnicodeCharSet instance, and should not change. Array is validated by
+ /// the constructor, so it makes sense to create as few UnicodeCharSet
+ /// instances per each array of ranges, as possible.
+#ifdef NDEBUG
+
+ // FIXME: This could use constexpr + static_assert. This way we
+ // may get rid of NDEBUG in this header. Unfortunately there are some
+ // problems to get this working with MSVC 2013. Change this when
+ // the support for MSVC 2013 is dropped.
+ constexpr UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) {}
+#else
+ UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) {
+ assert(rangesAreValid());
+ }
+#endif
+
+ /// Returns true if the character set contains the Unicode code point
+ /// \p C.
+ bool contains(uint32_t C) const {
+ return std::binary_search(Ranges.begin(), Ranges.end(), C);
+ }
+
+private:
+ /// Returns true if each of the ranges is a proper closed range
+ /// [min, max], and if the ranges themselves are ordered and non-overlapping.
+ bool rangesAreValid() const {
+ uint32_t Prev = 0;
+ for (CharRanges::const_iterator I = Ranges.begin(), E = Ranges.end();
+ I != E; ++I) {
+ if (I != Ranges.begin() && Prev >= I->Lower) {
+ LLVM_DEBUG(dbgs() << "Upper bound 0x");
+ LLVM_DEBUG(dbgs().write_hex(Prev));
+ LLVM_DEBUG(dbgs() << " should be less than succeeding lower bound 0x");
+ LLVM_DEBUG(dbgs().write_hex(I->Lower) << "\n");
+ return false;
+ }
+ if (I->Upper < I->Lower) {
+ LLVM_DEBUG(dbgs() << "Upper bound 0x");
+ LLVM_DEBUG(dbgs().write_hex(I->Lower));
+ LLVM_DEBUG(dbgs() << " should not be less than lower bound 0x");
+ LLVM_DEBUG(dbgs().write_hex(I->Upper) << "\n");
+ return false;
+ }
+ Prev = I->Upper;
+ }
+
+ return true;
+ }
+
+ const CharRanges Ranges;
+};
+
+} // namespace sys
+} // namespace llvm
+
+#undef DEBUG_TYPE // "unicode"
+
+#endif // LLVM_SUPPORT_UNICODECHARRANGES_H
diff --git a/third_party/llvm-project/include/llvm/Support/WindowsError.h b/third_party/llvm-project/include/llvm/Support/WindowsError.h
new file mode 100644
index 000000000..195405224
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/WindowsError.h
@@ -0,0 +1,18 @@
+//===-- WindowsError.h - Support for mapping windows errors to posix-------===//
+//
+// 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_WINDOWSERROR_H
+#define LLVM_SUPPORT_WINDOWSERROR_H
+
+#include <system_error>
+
+namespace llvm {
+std::error_code mapWindowsError(unsigned EV);
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/WithColor.h b/third_party/llvm-project/include/llvm/Support/WithColor.h
new file mode 100644
index 000000000..2814f7e0e
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/WithColor.h
@@ -0,0 +1,118 @@
+//===- WithColor.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_WITHCOLOR_H
+#define LLVM_SUPPORT_WITHCOLOR_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+#if 0 // XXX BINARYEN
+extern cl::OptionCategory ColorCategory;
+#endif
+
+class raw_ostream;
+
+// Symbolic names for various syntax elements.
+enum class HighlightColor {
+ Address,
+ String,
+ Tag,
+ Attribute,
+ Enumerator,
+ Macro,
+ Error,
+ Warning,
+ Note,
+ Remark
+};
+
+/// An RAII object that temporarily switches an output stream to a specific
+/// color.
+class WithColor {
+ raw_ostream &OS;
+ bool DisableColors;
+
+public:
+ /// To be used like this: WithColor(OS, HighlightColor::String) << "text";
+ /// @param OS The output stream
+ /// @param S Symbolic name for syntax element to color
+ /// @param DisableColors Whether to ignore color changes regardless of -color
+ /// and support in OS
+ WithColor(raw_ostream &OS, HighlightColor S, bool DisableColors = false);
+ /// To be used like this: WithColor(OS, raw_ostream::Black) << "text";
+ /// @param OS The output stream
+ /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to
+ /// change only the bold attribute, and keep colors untouched
+ /// @param Bold Bold/brighter text, default false
+ /// @param BG If true, change the background, default: change foreground
+ /// @param DisableColors Whether to ignore color changes regardless of -color
+ /// and support in OS
+ WithColor(raw_ostream &OS,
+ raw_ostream::Colors Color = raw_ostream::SAVEDCOLOR,
+ bool Bold = false, bool BG = false, bool DisableColors = false)
+ : OS(OS), DisableColors(DisableColors) {
+ changeColor(Color, Bold, BG);
+ }
+ ~WithColor();
+
+ raw_ostream &get() { return OS; }
+ operator raw_ostream &() { return OS; }
+ template <typename T> WithColor &operator<<(T &O) {
+ OS << O;
+ return *this;
+ }
+ template <typename T> WithColor &operator<<(const T &O) {
+ OS << O;
+ return *this;
+ }
+
+ /// Convenience method for printing "error: " to stderr.
+ static raw_ostream &error();
+ /// Convenience method for printing "warning: " to stderr.
+ static raw_ostream &warning();
+ /// Convenience method for printing "note: " to stderr.
+ static raw_ostream &note();
+ /// Convenience method for printing "remark: " to stderr.
+ static raw_ostream &remark();
+
+ /// Convenience method for printing "error: " to the given stream.
+ static raw_ostream &error(raw_ostream &OS, StringRef Prefix = "",
+ bool DisableColors = false);
+ /// Convenience method for printing "warning: " to the given stream.
+ static raw_ostream &warning(raw_ostream &OS, StringRef Prefix = "",
+ bool DisableColors = false);
+ /// Convenience method for printing "note: " to the given stream.
+ static raw_ostream &note(raw_ostream &OS, StringRef Prefix = "",
+ bool DisableColors = false);
+ /// Convenience method for printing "remark: " to the given stream.
+ static raw_ostream &remark(raw_ostream &OS, StringRef Prefix = "",
+ bool DisableColors = false);
+
+ /// Determine whether colors are displayed.
+ bool colorsEnabled();
+
+ /// Change the color of text that will be output from this point forward.
+ /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to
+ /// change only the bold attribute, and keep colors untouched
+ /// @param Bold Bold/brighter text, default false
+ /// @param BG If true, change the background, default: change foreground
+ WithColor &changeColor(raw_ostream::Colors Color, bool Bold = false,
+ bool BG = false);
+
+ /// Reset the colors to terminal defaults. Call this when you are done
+ /// outputting colored text, or before program exit.
+ WithColor &resetColor();
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_DEBUGINFO_WITHCOLOR_H
diff --git a/third_party/llvm-project/include/llvm/Support/X86TargetParser.def b/third_party/llvm-project/include/llvm/Support/X86TargetParser.def
new file mode 100644
index 000000000..4ebf2d79c
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/X86TargetParser.def
@@ -0,0 +1,173 @@
+//===- X86TargetParser.def - X86 target parsing defines ---------*- 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 defines to build up the X86 target parser's logic.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+#ifndef X86_VENDOR
+#define X86_VENDOR(ENUM, STR)
+#endif
+X86_VENDOR(VENDOR_INTEL, "intel")
+X86_VENDOR(VENDOR_AMD, "amd")
+#undef X86_VENDOR
+
+// This macro is used to implement CPU types that have an alias. As of now
+// there is only ever one alias.
+#ifndef X86_CPU_TYPE_COMPAT_WITH_ALIAS
+#define X86_CPU_TYPE_COMPAT_WITH_ALIAS(ARCHNAME, ENUM, STR, ALIAS) X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR)
+#endif
+
+// This macro is used for cpu types present in compiler-rt/libgcc.
+#ifndef X86_CPU_TYPE_COMPAT
+#define X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR) X86_CPU_TYPE(ARCHNAME, ENUM)
+#endif
+
+#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")
+X86_CPU_TYPE_COMPAT_WITH_ALIAS("amdfam10", AMDFAM10H, "amdfam10h", "amdfam10")
+X86_CPU_TYPE_COMPAT_WITH_ALIAS("bdver1", AMDFAM15H, "amdfam15h", "amdfam15")
+X86_CPU_TYPE_COMPAT_WITH_ALIAS("silvermont", INTEL_SILVERMONT, "silvermont", "slm")
+X86_CPU_TYPE_COMPAT ("knl", INTEL_KNL, "knl")
+X86_CPU_TYPE_COMPAT ("btver1", AMD_BTVER1, "btver1")
+X86_CPU_TYPE_COMPAT ("btver2", AMD_BTVER2, "btver2")
+X86_CPU_TYPE_COMPAT ("znver1", AMDFAM17H, "amdfam17h")
+X86_CPU_TYPE_COMPAT ("knm", INTEL_KNM, "knm")
+X86_CPU_TYPE_COMPAT ("goldmont", INTEL_GOLDMONT, "goldmont")
+X86_CPU_TYPE_COMPAT ("goldmont-plus", INTEL_GOLDMONT_PLUS, "goldmont-plus")
+X86_CPU_TYPE_COMPAT ("tremont", INTEL_TREMONT, "tremont")
+// Entries below this are not in libgcc/compiler-rt.
+X86_CPU_TYPE ("i386", INTEL_i386)
+X86_CPU_TYPE ("i486", INTEL_i486)
+X86_CPU_TYPE ("pentium", INTEL_PENTIUM)
+X86_CPU_TYPE ("pentium-mmx", INTEL_PENTIUM_MMX)
+X86_CPU_TYPE ("pentiumpro", INTEL_PENTIUM_PRO)
+X86_CPU_TYPE ("pentium2", INTEL_PENTIUM_II)
+X86_CPU_TYPE ("pentium3", INTEL_PENTIUM_III)
+X86_CPU_TYPE ("pentium4", INTEL_PENTIUM_IV)
+X86_CPU_TYPE ("pentium-m", INTEL_PENTIUM_M)
+X86_CPU_TYPE ("yonah", INTEL_CORE_DUO)
+X86_CPU_TYPE ("nocona", INTEL_NOCONA)
+X86_CPU_TYPE ("prescott", INTEL_PRESCOTT)
+X86_CPU_TYPE ("i486", AMD_i486)
+X86_CPU_TYPE ("pentium", AMDPENTIUM)
+X86_CPU_TYPE ("athlon", AMD_ATHLON)
+X86_CPU_TYPE ("athlon-xp", AMD_ATHLON_XP)
+X86_CPU_TYPE ("k8", AMD_K8)
+X86_CPU_TYPE ("k8-sse3", AMD_K8SSE3)
+#undef X86_CPU_TYPE_COMPAT_WITH_ALIAS
+#undef X86_CPU_TYPE_COMPAT
+#undef X86_CPU_TYPE
+
+// This macro is used for cpu subtypes present in compiler-rt/libgcc.
+#ifndef X86_CPU_SUBTYPE_COMPAT
+#define X86_CPU_SUBTYPE_COMPAT(ARCHNAME, ENUM, STR) X86_CPU_SUBTYPE(ARCHNAME, ENUM)
+#endif
+
+#ifndef X86_CPU_SUBTYPE
+#define X86_CPU_SUBTYPE(ARCHNAME, ENUM)
+#endif
+
+// The first part of this list must match what is implemented in libgcc and
+// compilert-rt. Clang uses this to know how to implement __builtin_cpu_is.
+X86_CPU_SUBTYPE_COMPAT("nehalem", INTEL_COREI7_NEHALEM, "nehalem")
+X86_CPU_SUBTYPE_COMPAT("westmere", INTEL_COREI7_WESTMERE, "westmere")
+X86_CPU_SUBTYPE_COMPAT("sandybridge", INTEL_COREI7_SANDYBRIDGE, "sandybridge")
+X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_BARCELONA, "barcelona")
+X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_SHANGHAI, "shanghai")
+X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_ISTANBUL, "istanbul")
+X86_CPU_SUBTYPE_COMPAT("bdver1", AMDFAM15H_BDVER1, "bdver1")
+X86_CPU_SUBTYPE_COMPAT("bdver2", AMDFAM15H_BDVER2, "bdver2")
+X86_CPU_SUBTYPE_COMPAT("bdver3", AMDFAM15H_BDVER3, "bdver3")
+X86_CPU_SUBTYPE_COMPAT("bdver4", AMDFAM15H_BDVER4, "bdver4")
+X86_CPU_SUBTYPE_COMPAT("znver1", AMDFAM17H_ZNVER1, "znver1")
+X86_CPU_SUBTYPE_COMPAT("ivybridge", INTEL_COREI7_IVYBRIDGE, "ivybridge")
+X86_CPU_SUBTYPE_COMPAT("haswell", INTEL_COREI7_HASWELL, "haswell")
+X86_CPU_SUBTYPE_COMPAT("broadwell", INTEL_COREI7_BROADWELL, "broadwell")
+X86_CPU_SUBTYPE_COMPAT("skylake", INTEL_COREI7_SKYLAKE, "skylake")
+X86_CPU_SUBTYPE_COMPAT("skylake-avx512", INTEL_COREI7_SKYLAKE_AVX512, "skylake-avx512")
+X86_CPU_SUBTYPE_COMPAT("cannonlake", INTEL_COREI7_CANNONLAKE, "cannonlake")
+X86_CPU_SUBTYPE_COMPAT("icelake-client", INTEL_COREI7_ICELAKE_CLIENT, "icelake-client")
+X86_CPU_SUBTYPE_COMPAT("icelake-server", INTEL_COREI7_ICELAKE_SERVER, "icelake-server")
+X86_CPU_SUBTYPE_COMPAT("znver2", AMDFAM17H_ZNVER2, "znver2")
+X86_CPU_SUBTYPE_COMPAT("cascadelake", INTEL_COREI7_CASCADELAKE, "cascadelake")
+// Entries below this are not in libgcc/compiler-rt.
+X86_CPU_SUBTYPE ("core2", INTEL_CORE2_65)
+X86_CPU_SUBTYPE ("penryn", INTEL_CORE2_45)
+X86_CPU_SUBTYPE ("k6", AMDPENTIUM_K6)
+X86_CPU_SUBTYPE ("k6-2", AMDPENTIUM_K62)
+X86_CPU_SUBTYPE ("k6-3", AMDPENTIUM_K63)
+X86_CPU_SUBTYPE ("geode", AMDPENTIUM_GEODE)
+X86_CPU_SUBTYPE ("cooperlake", INTEL_COREI7_COOPERLAKE)
+X86_CPU_SUBTYPE ("tigerlake", INTEL_COREI7_TIGERLAKE)
+#undef X86_CPU_SUBTYPE_COMPAT
+#undef X86_CPU_SUBTYPE
+
+
+// This macro is used for cpu types present in compiler-rt/libgcc.
+#ifndef X86_FEATURE_COMPAT
+#define X86_FEATURE_COMPAT(VAL, ENUM, STR) X86_FEATURE(VAL, ENUM)
+#endif
+
+#ifndef X86_FEATURE
+#define X86_FEATURE(VAL, ENUM)
+#endif
+X86_FEATURE_COMPAT( 0, FEATURE_CMOV, "cmov")
+X86_FEATURE_COMPAT( 1, FEATURE_MMX, "mmx")
+X86_FEATURE_COMPAT( 2, FEATURE_POPCNT, "popcnt")
+X86_FEATURE_COMPAT( 3, FEATURE_SSE, "sse")
+X86_FEATURE_COMPAT( 4, FEATURE_SSE2, "sse2")
+X86_FEATURE_COMPAT( 5, FEATURE_SSE3, "sse3")
+X86_FEATURE_COMPAT( 6, FEATURE_SSSE3, "ssse3")
+X86_FEATURE_COMPAT( 7, FEATURE_SSE4_1, "sse4.1")
+X86_FEATURE_COMPAT( 8, FEATURE_SSE4_2, "sse4.2")
+X86_FEATURE_COMPAT( 9, FEATURE_AVX, "avx")
+X86_FEATURE_COMPAT(10, FEATURE_AVX2, "avx2")
+X86_FEATURE_COMPAT(11, FEATURE_SSE4_A, "sse4a")
+X86_FEATURE_COMPAT(12, FEATURE_FMA4, "fma4")
+X86_FEATURE_COMPAT(13, FEATURE_XOP, "xop")
+X86_FEATURE_COMPAT(14, FEATURE_FMA, "fma")
+X86_FEATURE_COMPAT(15, FEATURE_AVX512F, "avx512f")
+X86_FEATURE_COMPAT(16, FEATURE_BMI, "bmi")
+X86_FEATURE_COMPAT(17, FEATURE_BMI2, "bmi2")
+X86_FEATURE_COMPAT(18, FEATURE_AES, "aes")
+X86_FEATURE_COMPAT(19, FEATURE_PCLMUL, "pclmul")
+X86_FEATURE_COMPAT(20, FEATURE_AVX512VL, "avx512vl")
+X86_FEATURE_COMPAT(21, FEATURE_AVX512BW, "avx512bw")
+X86_FEATURE_COMPAT(22, FEATURE_AVX512DQ, "avx512dq")
+X86_FEATURE_COMPAT(23, FEATURE_AVX512CD, "avx512cd")
+X86_FEATURE_COMPAT(24, FEATURE_AVX512ER, "avx512er")
+X86_FEATURE_COMPAT(25, FEATURE_AVX512PF, "avx512pf")
+X86_FEATURE_COMPAT(26, FEATURE_AVX512VBMI, "avx512vbmi")
+X86_FEATURE_COMPAT(27, FEATURE_AVX512IFMA, "avx512ifma")
+X86_FEATURE_COMPAT(28, FEATURE_AVX5124VNNIW, "avx5124vnniw")
+X86_FEATURE_COMPAT(29, FEATURE_AVX5124FMAPS, "avx5124fmaps")
+X86_FEATURE_COMPAT(30, FEATURE_AVX512VPOPCNTDQ, "avx512vpopcntdq")
+X86_FEATURE_COMPAT(31, FEATURE_AVX512VBMI2, "avx512vbmi2")
+X86_FEATURE_COMPAT(32, FEATURE_GFNI, "gfni")
+X86_FEATURE_COMPAT(33, FEATURE_VPCLMULQDQ, "vpclmulqdq")
+X86_FEATURE_COMPAT(34, FEATURE_AVX512VNNI, "avx512vnni")
+X86_FEATURE_COMPAT(35, FEATURE_AVX512BITALG, "avx512bitalg")
+X86_FEATURE_COMPAT(36, FEATURE_AVX512BF16, "avx512bf16")
+// Features below here are not in libgcc/compiler-rt.
+X86_FEATURE (64, FEATURE_MOVBE)
+X86_FEATURE (65, FEATURE_ADX)
+X86_FEATURE (66, FEATURE_EM64T)
+X86_FEATURE (67, FEATURE_CLFLUSHOPT)
+X86_FEATURE (68, FEATURE_SHA)
+X86_FEATURE (69, FEATURE_AVX512VP2INTERSECT)
+#undef X86_FEATURE_COMPAT
+#undef X86_FEATURE
diff --git a/third_party/llvm-project/include/llvm/Support/YAMLParser.h b/third_party/llvm-project/include/llvm/Support/YAMLParser.h
new file mode 100644
index 000000000..3570119a3
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/YAMLParser.h
@@ -0,0 +1,619 @@
+//===- YAMLParser.h - Simple YAML parser ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a YAML 1.2 parser.
+//
+// See http://www.yaml.org/spec/1.2/spec.html for the full standard.
+//
+// This currently does not implement the following:
+// * Multi-line literal folding.
+// * Tag resolution.
+// * UTF-16.
+// * BOMs anywhere other than the first Unicode scalar value in the file.
+//
+// The most important class here is Stream. This represents a YAML stream with
+// 0, 1, or many documents.
+//
+// SourceMgr sm;
+// StringRef input = getInput();
+// yaml::Stream stream(input, sm);
+//
+// for (yaml::document_iterator di = stream.begin(), de = stream.end();
+// di != de; ++di) {
+// yaml::Node *n = di->getRoot();
+// if (n) {
+// // Do something with n...
+// } else
+// break;
+// }
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_YAMLPARSER_H
+#define LLVM_SUPPORT_YAMLPARSER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/SMLoc.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <map>
+#include <memory>
+#include <string>
+#include <system_error>
+
+namespace llvm {
+
+class MemoryBufferRef;
+class SourceMgr;
+class raw_ostream;
+class Twine;
+
+namespace yaml {
+
+class Document;
+class document_iterator;
+class Node;
+class Scanner;
+struct Token;
+
+/// Dump all the tokens in this stream to OS.
+/// \returns true if there was an error, false otherwise.
+bool dumpTokens(StringRef Input, raw_ostream &);
+
+/// Scans all tokens in input without outputting anything. This is used
+/// for benchmarking the tokenizer.
+/// \returns true if there was an error, false otherwise.
+bool scanTokens(StringRef Input);
+
+/// Escape \a Input for a double quoted scalar; if \p EscapePrintable
+/// is true, all UTF8 sequences will be escaped, if \p EscapePrintable is
+/// false, those UTF8 sequences encoding printable unicode scalars will not be
+/// escaped, but emitted verbatim.
+std::string escape(StringRef Input, bool EscapePrintable = true);
+
+/// This class represents a YAML stream potentially containing multiple
+/// documents.
+class Stream {
+public:
+ /// This keeps a reference to the string referenced by \p Input.
+ Stream(StringRef Input, SourceMgr &, bool ShowColors = true,
+ std::error_code *EC = nullptr);
+
+ Stream(MemoryBufferRef InputBuffer, SourceMgr &, bool ShowColors = true,
+ std::error_code *EC = nullptr);
+ ~Stream();
+
+ document_iterator begin();
+ document_iterator end();
+ void skip();
+ bool failed();
+
+ bool validate() {
+ skip();
+ return !failed();
+ }
+
+ void printError(Node *N, const Twine &Msg);
+
+private:
+ friend class Document;
+
+ std::unique_ptr<Scanner> scanner;
+ std::unique_ptr<Document> CurrentDoc;
+};
+
+/// Abstract base class for all Nodes.
+class Node {
+ virtual void anchor();
+
+public:
+ enum NodeKind {
+ NK_Null,
+ NK_Scalar,
+ NK_BlockScalar,
+ NK_KeyValue,
+ NK_Mapping,
+ NK_Sequence,
+ NK_Alias
+ };
+
+ Node(unsigned int Type, std::unique_ptr<Document> &, StringRef Anchor,
+ StringRef Tag);
+
+ // It's not safe to copy YAML nodes; the document is streamed and the position
+ // is part of the state.
+ Node(const Node &) = delete;
+ void operator=(const Node &) = delete;
+
+ void *operator new(size_t Size, BumpPtrAllocator &Alloc,
+ size_t Alignment = 16) noexcept {
+ return Alloc.Allocate(Size, Alignment);
+ }
+
+ void operator delete(void *Ptr, BumpPtrAllocator &Alloc,
+ size_t Size) noexcept {
+ Alloc.Deallocate(Ptr, Size);
+ }
+
+ void operator delete(void *) noexcept = delete;
+
+ /// Get the value of the anchor attached to this node. If it does not
+ /// have one, getAnchor().size() will be 0.
+ StringRef getAnchor() const { return Anchor; }
+
+ /// Get the tag as it was written in the document. This does not
+ /// perform tag resolution.
+ StringRef getRawTag() const { return Tag; }
+
+ /// Get the verbatium tag for a given Node. This performs tag resoluton
+ /// and substitution.
+ std::string getVerbatimTag() const;
+
+ SMRange getSourceRange() const { return SourceRange; }
+ void setSourceRange(SMRange SR) { SourceRange = SR; }
+
+ // These functions forward to Document and Scanner.
+ Token &peekNext();
+ Token getNext();
+ Node *parseBlockNode();
+ BumpPtrAllocator &getAllocator();
+ void setError(const Twine &Message, Token &Location) const;
+ bool failed() const;
+
+ virtual void skip() {}
+
+ unsigned int getType() const { return TypeID; }
+
+protected:
+ std::unique_ptr<Document> &Doc;
+ SMRange SourceRange;
+
+ ~Node() = default;
+
+private:
+ unsigned int TypeID;
+ StringRef Anchor;
+ /// The tag as typed in the document.
+ StringRef Tag;
+};
+
+/// A null value.
+///
+/// Example:
+/// !!null null
+class NullNode final : public Node {
+ void anchor() override;
+
+public:
+ NullNode(std::unique_ptr<Document> &D)
+ : Node(NK_Null, D, StringRef(), StringRef()) {}
+
+ static bool classof(const Node *N) { return N->getType() == NK_Null; }
+};
+
+/// A scalar node is an opaque datum that can be presented as a
+/// series of zero or more Unicode scalar values.
+///
+/// Example:
+/// Adena
+class ScalarNode final : public Node {
+ void anchor() override;
+
+public:
+ ScalarNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag,
+ StringRef Val)
+ : Node(NK_Scalar, D, Anchor, Tag), Value(Val) {
+ SMLoc Start = SMLoc::getFromPointer(Val.begin());
+ SMLoc End = SMLoc::getFromPointer(Val.end());
+ SourceRange = SMRange(Start, End);
+ }
+
+ // Return Value without any escaping or folding or other fun YAML stuff. This
+ // is the exact bytes that are contained in the file (after conversion to
+ // utf8).
+ StringRef getRawValue() const { return Value; }
+
+ /// Gets the value of this node as a StringRef.
+ ///
+ /// \param Storage is used to store the content of the returned StringRef iff
+ /// it requires any modification from how it appeared in the source.
+ /// This happens with escaped characters and multi-line literals.
+ StringRef getValue(SmallVectorImpl<char> &Storage) const;
+
+ static bool classof(const Node *N) {
+ return N->getType() == NK_Scalar;
+ }
+
+private:
+ StringRef Value;
+
+ StringRef unescapeDoubleQuoted(StringRef UnquotedValue,
+ StringRef::size_type Start,
+ SmallVectorImpl<char> &Storage) const;
+};
+
+/// A block scalar node is an opaque datum that can be presented as a
+/// series of zero or more Unicode scalar values.
+///
+/// Example:
+/// |
+/// Hello
+/// World
+class BlockScalarNode final : public Node {
+ void anchor() override;
+
+public:
+ BlockScalarNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag,
+ StringRef Value, StringRef RawVal)
+ : Node(NK_BlockScalar, D, Anchor, Tag), Value(Value) {
+ SMLoc Start = SMLoc::getFromPointer(RawVal.begin());
+ SMLoc End = SMLoc::getFromPointer(RawVal.end());
+ SourceRange = SMRange(Start, End);
+ }
+
+ /// Gets the value of this node as a StringRef.
+ StringRef getValue() const { return Value; }
+
+ static bool classof(const Node *N) {
+ return N->getType() == NK_BlockScalar;
+ }
+
+private:
+ StringRef Value;
+};
+
+/// A key and value pair. While not technically a Node under the YAML
+/// representation graph, it is easier to treat them this way.
+///
+/// TODO: Consider making this not a child of Node.
+///
+/// Example:
+/// Section: .text
+class KeyValueNode final : public Node {
+ void anchor() override;
+
+public:
+ KeyValueNode(std::unique_ptr<Document> &D)
+ : Node(NK_KeyValue, D, StringRef(), StringRef()) {}
+
+ /// Parse and return the key.
+ ///
+ /// This may be called multiple times.
+ ///
+ /// \returns The key, or nullptr if failed() == true.
+ Node *getKey();
+
+ /// Parse and return the value.
+ ///
+ /// This may be called multiple times.
+ ///
+ /// \returns The value, or nullptr if failed() == true.
+ Node *getValue();
+
+ void skip() override {
+ if (Node *Key = getKey()) {
+ Key->skip();
+ if (Node *Val = getValue())
+ Val->skip();
+ }
+ }
+
+ static bool classof(const Node *N) {
+ return N->getType() == NK_KeyValue;
+ }
+
+private:
+ Node *Key = nullptr;
+ Node *Value = nullptr;
+};
+
+/// This is an iterator abstraction over YAML collections shared by both
+/// sequences and maps.
+///
+/// BaseT must have a ValueT* member named CurrentEntry and a member function
+/// increment() which must set CurrentEntry to 0 to create an end iterator.
+template <class BaseT, class ValueT>
+class basic_collection_iterator
+ : public std::iterator<std::input_iterator_tag, ValueT> {
+public:
+ basic_collection_iterator() = default;
+ basic_collection_iterator(BaseT *B) : Base(B) {}
+
+ ValueT *operator->() const {
+ assert(Base && Base->CurrentEntry && "Attempted to access end iterator!");
+ return Base->CurrentEntry;
+ }
+
+ ValueT &operator*() const {
+ assert(Base && Base->CurrentEntry &&
+ "Attempted to dereference end iterator!");
+ return *Base->CurrentEntry;
+ }
+
+ operator ValueT *() const {
+ assert(Base && Base->CurrentEntry && "Attempted to access end iterator!");
+ return Base->CurrentEntry;
+ }
+
+ /// Note on EqualityComparable:
+ ///
+ /// The iterator is not re-entrant,
+ /// it is meant to be used for parsing YAML on-demand
+ /// Once iteration started - it can point only to one entry at a time
+ /// hence Base.CurrentEntry and Other.Base.CurrentEntry are equal
+ /// iff Base and Other.Base are equal.
+ bool operator==(const basic_collection_iterator &Other) const {
+ if (Base && (Base == Other.Base)) {
+ assert((Base->CurrentEntry == Other.Base->CurrentEntry)
+ && "Equal Bases expected to point to equal Entries");
+ }
+
+ return Base == Other.Base;
+ }
+
+ bool operator!=(const basic_collection_iterator &Other) const {
+ return !(Base == Other.Base);
+ }
+
+ basic_collection_iterator &operator++() {
+ assert(Base && "Attempted to advance iterator past end!");
+ Base->increment();
+ // Create an end iterator.
+ if (!Base->CurrentEntry)
+ Base = nullptr;
+ return *this;
+ }
+
+private:
+ BaseT *Base = nullptr;
+};
+
+// The following two templates are used for both MappingNode and Sequence Node.
+template <class CollectionType>
+typename CollectionType::iterator begin(CollectionType &C) {
+ assert(C.IsAtBeginning && "You may only iterate over a collection once!");
+ C.IsAtBeginning = false;
+ typename CollectionType::iterator ret(&C);
+ ++ret;
+ return ret;
+}
+
+template <class CollectionType> void skip(CollectionType &C) {
+ // TODO: support skipping from the middle of a parsed collection ;/
+ assert((C.IsAtBeginning || C.IsAtEnd) && "Cannot skip mid parse!");
+ if (C.IsAtBeginning)
+ for (typename CollectionType::iterator i = begin(C), e = C.end(); i != e;
+ ++i)
+ i->skip();
+}
+
+/// Represents a YAML map created from either a block map for a flow map.
+///
+/// This parses the YAML stream as increment() is called.
+///
+/// Example:
+/// Name: _main
+/// Scope: Global
+class MappingNode final : public Node {
+ void anchor() override;
+
+public:
+ enum MappingType {
+ MT_Block,
+ MT_Flow,
+ MT_Inline ///< An inline mapping node is used for "[key: value]".
+ };
+
+ MappingNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag,
+ MappingType MT)
+ : Node(NK_Mapping, D, Anchor, Tag), Type(MT) {}
+
+ friend class basic_collection_iterator<MappingNode, KeyValueNode>;
+
+ using iterator = basic_collection_iterator<MappingNode, KeyValueNode>;
+
+ template <class T> friend typename T::iterator yaml::begin(T &);
+ template <class T> friend void yaml::skip(T &);
+
+ iterator begin() { return yaml::begin(*this); }
+
+ iterator end() { return iterator(); }
+
+ void skip() override { yaml::skip(*this); }
+
+ static bool classof(const Node *N) {
+ return N->getType() == NK_Mapping;
+ }
+
+private:
+ MappingType Type;
+ bool IsAtBeginning = true;
+ bool IsAtEnd = false;
+ KeyValueNode *CurrentEntry = nullptr;
+
+ void increment();
+};
+
+/// Represents a YAML sequence created from either a block sequence for a
+/// flow sequence.
+///
+/// This parses the YAML stream as increment() is called.
+///
+/// Example:
+/// - Hello
+/// - World
+class SequenceNode final : public Node {
+ void anchor() override;
+
+public:
+ enum SequenceType {
+ ST_Block,
+ ST_Flow,
+ // Use for:
+ //
+ // key:
+ // - val1
+ // - val2
+ //
+ // As a BlockMappingEntry and BlockEnd are not created in this case.
+ ST_Indentless
+ };
+
+ SequenceNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag,
+ SequenceType ST)
+ : Node(NK_Sequence, D, Anchor, Tag), SeqType(ST) {}
+
+ friend class basic_collection_iterator<SequenceNode, Node>;
+
+ using iterator = basic_collection_iterator<SequenceNode, Node>;
+
+ template <class T> friend typename T::iterator yaml::begin(T &);
+ template <class T> friend void yaml::skip(T &);
+
+ void increment();
+
+ iterator begin() { return yaml::begin(*this); }
+
+ iterator end() { return iterator(); }
+
+ void skip() override { yaml::skip(*this); }
+
+ static bool classof(const Node *N) {
+ return N->getType() == NK_Sequence;
+ }
+
+private:
+ SequenceType SeqType;
+ bool IsAtBeginning = true;
+ bool IsAtEnd = false;
+ bool WasPreviousTokenFlowEntry = true; // Start with an imaginary ','.
+ Node *CurrentEntry = nullptr;
+};
+
+/// Represents an alias to a Node with an anchor.
+///
+/// Example:
+/// *AnchorName
+class AliasNode final : public Node {
+ void anchor() override;
+
+public:
+ AliasNode(std::unique_ptr<Document> &D, StringRef Val)
+ : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {}
+
+ StringRef getName() const { return Name; }
+ Node *getTarget();
+
+ static bool classof(const Node *N) { return N->getType() == NK_Alias; }
+
+private:
+ StringRef Name;
+};
+
+/// A YAML Stream is a sequence of Documents. A document contains a root
+/// node.
+class Document {
+public:
+ Document(Stream &ParentStream);
+
+ /// Root for parsing a node. Returns a single node.
+ Node *parseBlockNode();
+
+ /// Finish parsing the current document and return true if there are
+ /// more. Return false otherwise.
+ bool skip();
+
+ /// Parse and return the root level node.
+ Node *getRoot() {
+ if (Root)
+ return Root;
+ return Root = parseBlockNode();
+ }
+
+ const std::map<StringRef, StringRef> &getTagMap() const { return TagMap; }
+
+private:
+ friend class Node;
+ friend class document_iterator;
+
+ /// Stream to read tokens from.
+ Stream &stream;
+
+ /// Used to allocate nodes to. All are destroyed without calling their
+ /// destructor when the document is destroyed.
+ BumpPtrAllocator NodeAllocator;
+
+ /// The root node. Used to support skipping a partially parsed
+ /// document.
+ Node *Root;
+
+ /// Maps tag prefixes to their expansion.
+ std::map<StringRef, StringRef> TagMap;
+
+ Token &peekNext();
+ Token getNext();
+ void setError(const Twine &Message, Token &Location) const;
+ bool failed() const;
+
+ /// Parse %BLAH directives and return true if any were encountered.
+ bool parseDirectives();
+
+ /// Parse %YAML
+ void parseYAMLDirective();
+
+ /// Parse %TAG
+ void parseTAGDirective();
+
+ /// Consume the next token and error if it is not \a TK.
+ bool expectToken(int TK);
+};
+
+/// Iterator abstraction for Documents over a Stream.
+class document_iterator {
+public:
+ document_iterator() = default;
+ document_iterator(std::unique_ptr<Document> &D) : Doc(&D) {}
+
+ bool operator==(const document_iterator &Other) const {
+ if (isAtEnd() || Other.isAtEnd())
+ return isAtEnd() && Other.isAtEnd();
+
+ return Doc == Other.Doc;
+ }
+ bool operator!=(const document_iterator &Other) const {
+ return !(*this == Other);
+ }
+
+ document_iterator operator++() {
+ assert(Doc && "incrementing iterator past the end.");
+ if (!(*Doc)->skip()) {
+ Doc->reset(nullptr);
+ } else {
+ Stream &S = (*Doc)->stream;
+ Doc->reset(new Document(S));
+ }
+ return *this;
+ }
+
+ Document &operator*() { return *Doc->get(); }
+
+ std::unique_ptr<Document> &operator->() { return *Doc; }
+
+private:
+ bool isAtEnd() const { return !Doc || !*Doc; }
+
+ std::unique_ptr<Document> *Doc = nullptr;
+};
+
+} // end namespace yaml
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_YAMLPARSER_H
diff --git a/third_party/llvm-project/include/llvm/Support/YAMLTraits.h b/third_party/llvm-project/include/llvm/Support/YAMLTraits.h
new file mode 100644
index 000000000..8642069ad
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/YAMLTraits.h
@@ -0,0 +1,2043 @@
+//===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_YAMLTRAITS_H
+#define LLVM_SUPPORT_YAMLTRAITS_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cctype>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <map>
+#include <memory>
+#include <new>
+#include <string>
+#include <system_error>
+#include <type_traits>
+#include <vector>
+
+namespace llvm {
+namespace yaml {
+
+enum class NodeKind : uint8_t {
+ Scalar,
+ Map,
+ Sequence,
+};
+
+struct EmptyContext {};
+
+/// This class should be specialized by any type that needs to be converted
+/// to/from a YAML mapping. For example:
+///
+/// struct MappingTraits<MyStruct> {
+/// static void mapping(IO &io, MyStruct &s) {
+/// io.mapRequired("name", s.name);
+/// io.mapRequired("size", s.size);
+/// io.mapOptional("age", s.age);
+/// }
+/// };
+template<class T>
+struct MappingTraits {
+ // Must provide:
+ // static void mapping(IO &io, T &fields);
+ // Optionally may provide:
+ // static StringRef validate(IO &io, T &fields);
+ //
+ // The optional flow flag will cause generated YAML to use a flow mapping
+ // (e.g. { a: 0, b: 1 }):
+ // static const bool flow = true;
+};
+
+/// This class is similar to MappingTraits<T> but allows you to pass in
+/// additional context for each map operation. For example:
+///
+/// struct MappingContextTraits<MyStruct, MyContext> {
+/// static void mapping(IO &io, MyStruct &s, MyContext &c) {
+/// io.mapRequired("name", s.name);
+/// io.mapRequired("size", s.size);
+/// io.mapOptional("age", s.age);
+/// ++c.TimesMapped;
+/// }
+/// };
+template <class T, class Context> struct MappingContextTraits {
+ // Must provide:
+ // static void mapping(IO &io, T &fields, Context &Ctx);
+ // Optionally may provide:
+ // static StringRef validate(IO &io, T &fields, Context &Ctx);
+ //
+ // The optional flow flag will cause generated YAML to use a flow mapping
+ // (e.g. { a: 0, b: 1 }):
+ // static const bool flow = true;
+};
+
+/// This class should be specialized by any integral type that converts
+/// to/from a YAML scalar where there is a one-to-one mapping between
+/// in-memory values and a string in YAML. For example:
+///
+/// struct ScalarEnumerationTraits<Colors> {
+/// static void enumeration(IO &io, Colors &value) {
+/// io.enumCase(value, "red", cRed);
+/// io.enumCase(value, "blue", cBlue);
+/// io.enumCase(value, "green", cGreen);
+/// }
+/// };
+template <typename T, typename Enable = void> struct ScalarEnumerationTraits {
+ // Must provide:
+ // static void enumeration(IO &io, T &value);
+};
+
+/// This class should be specialized by any integer type that is a union
+/// of bit values and the YAML representation is a flow sequence of
+/// strings. For example:
+///
+/// struct ScalarBitSetTraits<MyFlags> {
+/// static void bitset(IO &io, MyFlags &value) {
+/// io.bitSetCase(value, "big", flagBig);
+/// io.bitSetCase(value, "flat", flagFlat);
+/// io.bitSetCase(value, "round", flagRound);
+/// }
+/// };
+template <typename T, typename Enable = void> struct ScalarBitSetTraits {
+ // Must provide:
+ // static void bitset(IO &io, T &value);
+};
+
+/// Describe which type of quotes should be used when quoting is necessary.
+/// Some non-printable characters need to be double-quoted, while some others
+/// are fine with simple-quoting, and some don't need any quoting.
+enum class QuotingType { None, Single, Double };
+
+/// This class should be specialized by type that requires custom conversion
+/// to/from a yaml scalar. For example:
+///
+/// template<>
+/// struct ScalarTraits<MyType> {
+/// static void output(const MyType &val, void*, llvm::raw_ostream &out) {
+/// // stream out custom formatting
+/// out << llvm::format("%x", val);
+/// }
+/// static StringRef input(StringRef scalar, void*, MyType &value) {
+/// // parse scalar and set `value`
+/// // return empty string on success, or error string
+/// return StringRef();
+/// }
+/// static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
+/// };
+template <typename T, typename Enable = void> struct ScalarTraits {
+ // Must provide:
+ //
+ // Function to write the value as a string:
+ // static void output(const T &value, void *ctxt, llvm::raw_ostream &out);
+ //
+ // Function to convert a string to a value. Returns the empty
+ // StringRef on success or an error string if string is malformed:
+ // static StringRef input(StringRef scalar, void *ctxt, T &value);
+ //
+ // Function to determine if the value should be quoted.
+ // static QuotingType mustQuote(StringRef);
+};
+
+/// This class should be specialized by type that requires custom conversion
+/// to/from a YAML literal block scalar. For example:
+///
+/// template <>
+/// struct BlockScalarTraits<MyType> {
+/// static void output(const MyType &Value, void*, llvm::raw_ostream &Out)
+/// {
+/// // stream out custom formatting
+/// Out << Value;
+/// }
+/// static StringRef input(StringRef Scalar, void*, MyType &Value) {
+/// // parse scalar and set `value`
+/// // return empty string on success, or error string
+/// return StringRef();
+/// }
+/// };
+template <typename T>
+struct BlockScalarTraits {
+ // Must provide:
+ //
+ // Function to write the value as a string:
+ // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out);
+ //
+ // Function to convert a string to a value. Returns the empty
+ // StringRef on success or an error string if string is malformed:
+ // static StringRef input(StringRef Scalar, void *ctxt, T &Value);
+ //
+ // Optional:
+ // static StringRef inputTag(T &Val, std::string Tag)
+ // static void outputTag(const T &Val, raw_ostream &Out)
+};
+
+/// This class should be specialized by type that requires custom conversion
+/// to/from a YAML scalar with optional tags. For example:
+///
+/// template <>
+/// struct TaggedScalarTraits<MyType> {
+/// static void output(const MyType &Value, void*, llvm::raw_ostream
+/// &ScalarOut, llvm::raw_ostream &TagOut)
+/// {
+/// // stream out custom formatting including optional Tag
+/// Out << Value;
+/// }
+/// static StringRef input(StringRef Scalar, StringRef Tag, void*, MyType
+/// &Value) {
+/// // parse scalar and set `value`
+/// // return empty string on success, or error string
+/// return StringRef();
+/// }
+/// static QuotingType mustQuote(const MyType &Value, StringRef) {
+/// return QuotingType::Single;
+/// }
+/// };
+template <typename T> struct TaggedScalarTraits {
+ // Must provide:
+ //
+ // Function to write the value and tag as strings:
+ // static void output(const T &Value, void *ctx, llvm::raw_ostream &ScalarOut,
+ // llvm::raw_ostream &TagOut);
+ //
+ // Function to convert a string to a value. Returns the empty
+ // StringRef on success or an error string if string is malformed:
+ // static StringRef input(StringRef Scalar, StringRef Tag, void *ctxt, T
+ // &Value);
+ //
+ // Function to determine if the value should be quoted.
+ // static QuotingType mustQuote(const T &Value, StringRef Scalar);
+};
+
+/// This class should be specialized by any type that needs to be converted
+/// to/from a YAML sequence. For example:
+///
+/// template<>
+/// struct SequenceTraits<MyContainer> {
+/// static size_t size(IO &io, MyContainer &seq) {
+/// return seq.size();
+/// }
+/// static MyType& element(IO &, MyContainer &seq, size_t index) {
+/// if ( index >= seq.size() )
+/// seq.resize(index+1);
+/// return seq[index];
+/// }
+/// };
+template<typename T, typename EnableIf = void>
+struct SequenceTraits {
+ // Must provide:
+ // static size_t size(IO &io, T &seq);
+ // static T::value_type& element(IO &io, T &seq, size_t index);
+ //
+ // The following is option and will cause generated YAML to use
+ // a flow sequence (e.g. [a,b,c]).
+ // static const bool flow = true;
+};
+
+/// This class should be specialized by any type for which vectors of that
+/// type need to be converted to/from a YAML sequence.
+template<typename T, typename EnableIf = void>
+struct SequenceElementTraits {
+ // Must provide:
+ // static const bool flow;
+};
+
+/// This class should be specialized by any type that needs to be converted
+/// to/from a list of YAML documents.
+template<typename T>
+struct DocumentListTraits {
+ // Must provide:
+ // static size_t size(IO &io, T &seq);
+ // static T::value_type& element(IO &io, T &seq, size_t index);
+};
+
+/// This class should be specialized by any type that needs to be converted
+/// to/from a YAML mapping in the case where the names of the keys are not known
+/// in advance, e.g. a string map.
+template <typename T>
+struct CustomMappingTraits {
+ // static void inputOne(IO &io, StringRef key, T &elem);
+ // static void output(IO &io, T &elem);
+};
+
+/// This class should be specialized by any type that can be represented as
+/// a scalar, map, or sequence, decided dynamically. For example:
+///
+/// typedef std::unique_ptr<MyBase> MyPoly;
+///
+/// template<>
+/// struct PolymorphicTraits<MyPoly> {
+/// static NodeKind getKind(const MyPoly &poly) {
+/// return poly->getKind();
+/// }
+/// static MyScalar& getAsScalar(MyPoly &poly) {
+/// if (!poly || !isa<MyScalar>(poly))
+/// poly.reset(new MyScalar());
+/// return *cast<MyScalar>(poly.get());
+/// }
+/// // ...
+/// };
+template <typename T> struct PolymorphicTraits {
+ // Must provide:
+ // static NodeKind getKind(const T &poly);
+ // static scalar_type &getAsScalar(T &poly);
+ // static map_type &getAsMap(T &poly);
+ // static sequence_type &getAsSequence(T &poly);
+};
+
+// Only used for better diagnostics of missing traits
+template <typename T>
+struct MissingTrait;
+
+// Test if ScalarEnumerationTraits<T> is defined on type T.
+template <class T>
+struct has_ScalarEnumerationTraits
+{
+ using Signature_enumeration = void (*)(class IO&, T&);
+
+ template <typename U>
+ static char test(SameType<Signature_enumeration, &U::enumeration>*);
+
+ template <typename U>
+ static double test(...);
+
+ static bool const value =
+ (sizeof(test<ScalarEnumerationTraits<T>>(nullptr)) == 1);
+};
+
+// Test if ScalarBitSetTraits<T> is defined on type T.
+template <class T>
+struct has_ScalarBitSetTraits
+{
+ using Signature_bitset = void (*)(class IO&, T&);
+
+ template <typename U>
+ static char test(SameType<Signature_bitset, &U::bitset>*);
+
+ template <typename U>
+ static double test(...);
+
+ static bool const value = (sizeof(test<ScalarBitSetTraits<T>>(nullptr)) == 1);
+};
+
+// Test if ScalarTraits<T> is defined on type T.
+template <class T>
+struct has_ScalarTraits
+{
+ using Signature_input = StringRef (*)(StringRef, void*, T&);
+ using Signature_output = void (*)(const T&, void*, raw_ostream&);
+ using Signature_mustQuote = QuotingType (*)(StringRef);
+
+ template <typename U>
+ static char test(SameType<Signature_input, &U::input> *,
+ SameType<Signature_output, &U::output> *,
+ SameType<Signature_mustQuote, &U::mustQuote> *);
+
+ template <typename U>
+ static double test(...);
+
+ static bool const value =
+ (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
+};
+
+// Test if BlockScalarTraits<T> is defined on type T.
+template <class T>
+struct has_BlockScalarTraits
+{
+ using Signature_input = StringRef (*)(StringRef, void *, T &);
+ using Signature_output = void (*)(const T &, void *, raw_ostream &);
+
+ template <typename U>
+ static char test(SameType<Signature_input, &U::input> *,
+ SameType<Signature_output, &U::output> *);
+
+ template <typename U>
+ static double test(...);
+
+ static bool const value =
+ (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1);
+};
+
+// Test if TaggedScalarTraits<T> is defined on type T.
+template <class T> struct has_TaggedScalarTraits {
+ using Signature_input = StringRef (*)(StringRef, StringRef, void *, T &);
+ using Signature_output = void (*)(const T &, void *, raw_ostream &,
+ raw_ostream &);
+ using Signature_mustQuote = QuotingType (*)(const T &, StringRef);
+
+ template <typename U>
+ static char test(SameType<Signature_input, &U::input> *,
+ SameType<Signature_output, &U::output> *,
+ SameType<Signature_mustQuote, &U::mustQuote> *);
+
+ template <typename U> static double test(...);
+
+ static bool const value =
+ (sizeof(test<TaggedScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1);
+};
+
+// Test if MappingContextTraits<T> is defined on type T.
+template <class T, class Context> struct has_MappingTraits {
+ using Signature_mapping = void (*)(class IO &, T &, Context &);
+
+ template <typename U>
+ static char test(SameType<Signature_mapping, &U::mapping>*);
+
+ template <typename U>
+ static double test(...);
+
+ static bool const value =
+ (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
+};
+
+// Test if MappingTraits<T> is defined on type T.
+template <class T> struct has_MappingTraits<T, EmptyContext> {
+ using Signature_mapping = void (*)(class IO &, T &);
+
+ template <typename U>
+ static char test(SameType<Signature_mapping, &U::mapping> *);
+
+ template <typename U> static double test(...);
+
+ static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
+};
+
+// Test if MappingContextTraits<T>::validate() is defined on type T.
+template <class T, class Context> struct has_MappingValidateTraits {
+ using Signature_validate = StringRef (*)(class IO &, T &, Context &);
+
+ template <typename U>
+ static char test(SameType<Signature_validate, &U::validate>*);
+
+ template <typename U>
+ static double test(...);
+
+ static bool const value =
+ (sizeof(test<MappingContextTraits<T, Context>>(nullptr)) == 1);
+};
+
+// Test if MappingTraits<T>::validate() is defined on type T.
+template <class T> struct has_MappingValidateTraits<T, EmptyContext> {
+ using Signature_validate = StringRef (*)(class IO &, T &);
+
+ template <typename U>
+ static char test(SameType<Signature_validate, &U::validate> *);
+
+ template <typename U> static double test(...);
+
+ static bool const value = (sizeof(test<MappingTraits<T>>(nullptr)) == 1);
+};
+
+// Test if SequenceTraits<T> is defined on type T.
+template <class T>
+struct has_SequenceMethodTraits
+{
+ using Signature_size = size_t (*)(class IO&, T&);
+
+ template <typename U>
+ static char test(SameType<Signature_size, &U::size>*);
+
+ template <typename U>
+ static double test(...);
+
+ static bool const value = (sizeof(test<SequenceTraits<T>>(nullptr)) == 1);
+};
+
+// Test if CustomMappingTraits<T> is defined on type T.
+template <class T>
+struct has_CustomMappingTraits
+{
+ using Signature_input = void (*)(IO &io, StringRef key, T &v);
+
+ template <typename U>
+ static char test(SameType<Signature_input, &U::inputOne>*);
+
+ template <typename U>
+ static double test(...);
+
+ static bool const value =
+ (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1);
+};
+
+// has_FlowTraits<int> will cause an error with some compilers because
+// it subclasses int. Using this wrapper only instantiates the
+// real has_FlowTraits only if the template type is a class.
+template <typename T, bool Enabled = std::is_class<T>::value>
+class has_FlowTraits
+{
+public:
+ static const bool value = false;
+};
+
+// Some older gcc compilers don't support straight forward tests
+// for members, so test for ambiguity cause by the base and derived
+// classes both defining the member.
+template <class T>
+struct has_FlowTraits<T, true>
+{
+ struct Fallback { bool flow; };
+ struct Derived : T, Fallback { };
+
+ template<typename C>
+ static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
+
+ template<typename C>
+ static char (&f(...))[2];
+
+ static bool const value = sizeof(f<Derived>(nullptr)) == 2;
+};
+
+// Test if SequenceTraits<T> is defined on type T
+template<typename T>
+struct has_SequenceTraits : public std::integral_constant<bool,
+ has_SequenceMethodTraits<T>::value > { };
+
+// Test if DocumentListTraits<T> is defined on type T
+template <class T>
+struct has_DocumentListTraits
+{
+ using Signature_size = size_t (*)(class IO &, T &);
+
+ template <typename U>
+ static char test(SameType<Signature_size, &U::size>*);
+
+ template <typename U>
+ static double test(...);
+
+ static bool const value = (sizeof(test<DocumentListTraits<T>>(nullptr))==1);
+};
+
+template <class T> struct has_PolymorphicTraits {
+ using Signature_getKind = NodeKind (*)(const T &);
+
+ template <typename U>
+ static char test(SameType<Signature_getKind, &U::getKind> *);
+
+ template <typename U> static double test(...);
+
+ static bool const value = (sizeof(test<PolymorphicTraits<T>>(nullptr)) == 1);
+};
+
+inline bool isNumeric(StringRef S) {
+ const static auto skipDigits = [](StringRef Input) {
+ return Input.drop_front(
+ std::min(Input.find_first_not_of("0123456789"), Input.size()));
+ };
+
+ // Make S.front() and S.drop_front().front() (if S.front() is [+-]) calls
+ // safe.
+ if (S.empty() || S.equals("+") || S.equals("-"))
+ return false;
+
+ if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN"))
+ return true;
+
+ // Infinity and decimal numbers can be prefixed with sign.
+ StringRef Tail = (S.front() == '-' || S.front() == '+') ? S.drop_front() : S;
+
+ // Check for infinity first, because checking for hex and oct numbers is more
+ // expensive.
+ if (Tail.equals(".inf") || Tail.equals(".Inf") || Tail.equals(".INF"))
+ return true;
+
+ // Section 10.3.2 Tag Resolution
+ // YAML 1.2 Specification prohibits Base 8 and Base 16 numbers prefixed with
+ // [-+], so S should be used instead of Tail.
+ if (S.startswith("0o"))
+ return S.size() > 2 &&
+ S.drop_front(2).find_first_not_of("01234567") == StringRef::npos;
+
+ if (S.startswith("0x"))
+ return S.size() > 2 && S.drop_front(2).find_first_not_of(
+ "0123456789abcdefABCDEF") == StringRef::npos;
+
+ // Parse float: [-+]? (\. [0-9]+ | [0-9]+ (\. [0-9]* )?) ([eE] [-+]? [0-9]+)?
+ S = Tail;
+
+ // Handle cases when the number starts with '.' and hence needs at least one
+ // digit after dot (as opposed by number which has digits before the dot), but
+ // doesn't have one.
+ if (S.startswith(".") &&
+ (S.equals(".") ||
+ (S.size() > 1 && std::strchr("0123456789", S[1]) == nullptr)))
+ return false;
+
+ if (S.startswith("E") || S.startswith("e"))
+ return false;
+
+ enum ParseState {
+ Default,
+ FoundDot,
+ FoundExponent,
+ };
+ ParseState State = Default;
+
+ S = skipDigits(S);
+
+ // Accept decimal integer.
+ if (S.empty())
+ return true;
+
+ if (S.front() == '.') {
+ State = FoundDot;
+ S = S.drop_front();
+ } else if (S.front() == 'e' || S.front() == 'E') {
+ State = FoundExponent;
+ S = S.drop_front();
+ } else {
+ return false;
+ }
+
+ if (State == FoundDot) {
+ S = skipDigits(S);
+ if (S.empty())
+ return true;
+
+ if (S.front() == 'e' || S.front() == 'E') {
+ State = FoundExponent;
+ S = S.drop_front();
+ } else {
+ return false;
+ }
+ }
+
+ assert(State == FoundExponent && "Should have found exponent at this point.");
+ if (S.empty())
+ return false;
+
+ if (S.front() == '+' || S.front() == '-') {
+ S = S.drop_front();
+ if (S.empty())
+ return false;
+ }
+
+ return skipDigits(S).empty();
+}
+
+inline bool isNull(StringRef S) {
+ return S.equals("null") || S.equals("Null") || S.equals("NULL") ||
+ S.equals("~");
+}
+
+inline bool isBool(StringRef S) {
+ return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
+ S.equals("false") || S.equals("False") || S.equals("FALSE");
+}
+
+// 5.1. Character Set
+// The allowed character range explicitly excludes the C0 control block #x0-#x1F
+// (except for TAB #x9, LF #xA, and CR #xD which are allowed), DEL #x7F, the C1
+// control block #x80-#x9F (except for NEL #x85 which is allowed), the surrogate
+// block #xD800-#xDFFF, #xFFFE, and #xFFFF.
+inline QuotingType needsQuotes(StringRef S) {
+ if (S.empty())
+ return QuotingType::Single;
+ if (isspace(static_cast<unsigned char>(S.front())) ||
+ isspace(static_cast<unsigned char>(S.back())))
+ return QuotingType::Single;
+ if (isNull(S))
+ return QuotingType::Single;
+ if (isBool(S))
+ return QuotingType::Single;
+ if (isNumeric(S))
+ return QuotingType::Single;
+
+ // 7.3.3 Plain Style
+ // Plain scalars must not begin with most indicators, as this would cause
+ // ambiguity with other YAML constructs.
+ static constexpr char Indicators[] = R"(-?:\,[]{}#&*!|>'"%@`)";
+ if (S.find_first_of(Indicators) == 0)
+ return QuotingType::Single;
+
+ QuotingType MaxQuotingNeeded = QuotingType::None;
+ for (unsigned char C : S) {
+ // Alphanum is safe.
+ if (isAlnum(C))
+ continue;
+
+ switch (C) {
+ // Safe scalar characters.
+ case '_':
+ case '-':
+ case '^':
+ case '.':
+ case ',':
+ case ' ':
+ // TAB (0x9) is allowed in unquoted strings.
+ case 0x9:
+ continue;
+ // LF(0xA) and CR(0xD) may delimit values and so require at least single
+ // quotes.
+ case 0xA:
+ case 0xD:
+ MaxQuotingNeeded = QuotingType::Single;
+ continue;
+ // DEL (0x7F) are excluded from the allowed character range.
+ case 0x7F:
+ return QuotingType::Double;
+ // Forward slash is allowed to be unquoted, but we quote it anyway. We have
+ // many tests that use FileCheck against YAML output, and this output often
+ // contains paths. If we quote backslashes but not forward slashes then
+ // paths will come out either quoted or unquoted depending on which platform
+ // the test is run on, making FileCheck comparisons difficult.
+ case '/':
+ default: {
+ // C0 control block (0x0 - 0x1F) is excluded from the allowed character
+ // range.
+ if (C <= 0x1F)
+ return QuotingType::Double;
+
+ // Always double quote UTF-8.
+ if ((C & 0x80) != 0)
+ return QuotingType::Double;
+
+ // The character is not safe, at least simple quoting needed.
+ MaxQuotingNeeded = QuotingType::Single;
+ }
+ }
+ }
+
+ return MaxQuotingNeeded;
+}
+
+template <typename T, typename Context>
+struct missingTraits
+ : public std::integral_constant<bool,
+ !has_ScalarEnumerationTraits<T>::value &&
+ !has_ScalarBitSetTraits<T>::value &&
+ !has_ScalarTraits<T>::value &&
+ !has_BlockScalarTraits<T>::value &&
+ !has_TaggedScalarTraits<T>::value &&
+ !has_MappingTraits<T, Context>::value &&
+ !has_SequenceTraits<T>::value &&
+ !has_CustomMappingTraits<T>::value &&
+ !has_DocumentListTraits<T>::value &&
+ !has_PolymorphicTraits<T>::value> {};
+
+template <typename T, typename Context>
+struct validatedMappingTraits
+ : public std::integral_constant<
+ bool, has_MappingTraits<T, Context>::value &&
+ has_MappingValidateTraits<T, Context>::value> {};
+
+template <typename T, typename Context>
+struct unvalidatedMappingTraits
+ : public std::integral_constant<
+ bool, has_MappingTraits<T, Context>::value &&
+ !has_MappingValidateTraits<T, Context>::value> {};
+
+// Base class for Input and Output.
+class IO {
+public:
+ IO(void *Ctxt = nullptr);
+ virtual ~IO();
+
+ virtual bool outputting() const = 0;
+
+ virtual unsigned beginSequence() = 0;
+ virtual bool preflightElement(unsigned, void *&) = 0;
+ virtual void postflightElement(void*) = 0;
+ virtual void endSequence() = 0;
+ virtual bool canElideEmptySequence() = 0;
+
+ virtual unsigned beginFlowSequence() = 0;
+ virtual bool preflightFlowElement(unsigned, void *&) = 0;
+ virtual void postflightFlowElement(void*) = 0;
+ virtual void endFlowSequence() = 0;
+
+ virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
+ virtual void beginMapping() = 0;
+ virtual void endMapping() = 0;
+ virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
+ virtual void postflightKey(void*) = 0;
+ virtual std::vector<StringRef> keys() = 0;
+
+ virtual void beginFlowMapping() = 0;
+ virtual void endFlowMapping() = 0;
+
+ virtual void beginEnumScalar() = 0;
+ virtual bool matchEnumScalar(const char*, bool) = 0;
+ virtual bool matchEnumFallback() = 0;
+ virtual void endEnumScalar() = 0;
+
+ virtual bool beginBitSetScalar(bool &) = 0;
+ virtual bool bitSetMatch(const char*, bool) = 0;
+ virtual void endBitSetScalar() = 0;
+
+ virtual void scalarString(StringRef &, QuotingType) = 0;
+ virtual void blockScalarString(StringRef &) = 0;
+ virtual void scalarTag(std::string &) = 0;
+
+ virtual NodeKind getNodeKind() = 0;
+
+ virtual void setError(const Twine &) = 0;
+
+ template <typename T>
+ void enumCase(T &Val, const char* Str, const T ConstVal) {
+ if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) {
+ Val = ConstVal;
+ }
+ }
+
+ // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
+ template <typename T>
+ void enumCase(T &Val, const char* Str, const uint32_t ConstVal) {
+ if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) {
+ Val = ConstVal;
+ }
+ }
+
+ template <typename FBT, typename T>
+ void enumFallback(T &Val) {
+ if (matchEnumFallback()) {
+ EmptyContext Context;
+ // FIXME: Force integral conversion to allow strong typedefs to convert.
+ FBT Res = static_cast<typename FBT::BaseType>(Val);
+ yamlize(*this, Res, true, Context);
+ Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res));
+ }
+ }
+
+ template <typename T>
+ void bitSetCase(T &Val, const char* Str, const T ConstVal) {
+ if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
+ Val = static_cast<T>(Val | ConstVal);
+ }
+ }
+
+ // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF
+ template <typename T>
+ void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
+ if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
+ Val = static_cast<T>(Val | ConstVal);
+ }
+ }
+
+ template <typename T>
+ void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
+ if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
+ Val = Val | ConstVal;
+ }
+
+ template <typename T>
+ void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
+ uint32_t Mask) {
+ if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
+ Val = Val | ConstVal;
+ }
+
+ void *getContext() const;
+ void setContext(void *);
+
+ template <typename T> void mapRequired(const char *Key, T &Val) {
+ EmptyContext Ctx;
+ this->processKey(Key, Val, true, Ctx);
+ }
+
+ template <typename T, typename Context>
+ void mapRequired(const char *Key, T &Val, Context &Ctx) {
+ this->processKey(Key, Val, true, Ctx);
+ }
+
+ template <typename T> void mapOptional(const char *Key, T &Val) {
+ EmptyContext Ctx;
+ mapOptionalWithContext(Key, Val, Ctx);
+ }
+
+ template <typename T, typename DefaultT>
+ void mapOptional(const char *Key, T &Val, const DefaultT &Default) {
+ EmptyContext Ctx;
+ mapOptionalWithContext(Key, Val, Default, Ctx);
+ }
+
+ template <typename T, typename Context>
+ typename std::enable_if<has_SequenceTraits<T>::value, void>::type
+ mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
+ // omit key/value instead of outputting empty sequence
+ if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
+ return;
+ this->processKey(Key, Val, false, Ctx);
+ }
+
+ template <typename T, typename Context>
+ void mapOptionalWithContext(const char *Key, Optional<T> &Val, Context &Ctx) {
+ this->processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false,
+ Ctx);
+ }
+
+ template <typename T, typename Context>
+ typename std::enable_if<!has_SequenceTraits<T>::value, void>::type
+ mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
+ this->processKey(Key, Val, false, Ctx);
+ }
+
+ template <typename T, typename Context, typename DefaultT>
+ void mapOptionalWithContext(const char *Key, T &Val, const DefaultT &Default,
+ Context &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:
+ template <typename T, typename Context>
+ void processKeyWithDefault(const char *Key, Optional<T> &Val,
+ const Optional<T> &DefaultValue, bool Required,
+ Context &Ctx) {
+ assert(DefaultValue.hasValue() == false &&
+ "Optional<T> shouldn't have a value!");
+ void *SaveInfo;
+ bool UseDefault = true;
+ const bool sameAsDefault = outputting() && !Val.hasValue();
+ if (!outputting() && !Val.hasValue())
+ Val = T();
+ if (Val.hasValue() &&
+ this->preflightKey(Key, Required, sameAsDefault, UseDefault,
+ SaveInfo)) {
+ yamlize(*this, Val.getValue(), Required, Ctx);
+ this->postflightKey(SaveInfo);
+ } else {
+ if (UseDefault)
+ Val = DefaultValue;
+ }
+ }
+
+ template <typename T, typename Context>
+ void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
+ bool Required, Context &Ctx) {
+ void *SaveInfo;
+ bool UseDefault;
+ const bool sameAsDefault = outputting() && Val == DefaultValue;
+ if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault,
+ SaveInfo) ) {
+ yamlize(*this, Val, Required, Ctx);
+ this->postflightKey(SaveInfo);
+ }
+ else {
+ if ( UseDefault )
+ Val = DefaultValue;
+ }
+ }
+
+ template <typename T, typename Context>
+ void processKey(const char *Key, T &Val, bool Required, Context &Ctx) {
+ void *SaveInfo;
+ bool UseDefault;
+ if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) {
+ yamlize(*this, Val, Required, Ctx);
+ this->postflightKey(SaveInfo);
+ }
+ }
+
+private:
+ void *Ctxt;
+};
+
+namespace detail {
+
+template <typename T, typename Context>
+void doMapping(IO &io, T &Val, Context &Ctx) {
+ MappingContextTraits<T, Context>::mapping(io, Val, Ctx);
+}
+
+template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
+ MappingTraits<T>::mapping(io, Val);
+}
+
+} // end namespace detail
+
+template <typename T>
+typename std::enable_if<has_ScalarEnumerationTraits<T>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
+ io.beginEnumScalar();
+ ScalarEnumerationTraits<T>::enumeration(io, Val);
+ io.endEnumScalar();
+}
+
+template <typename T>
+typename std::enable_if<has_ScalarBitSetTraits<T>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
+ bool DoClear;
+ if ( io.beginBitSetScalar(DoClear) ) {
+ if ( DoClear )
+ Val = T();
+ ScalarBitSetTraits<T>::bitset(io, Val);
+ io.endBitSetScalar();
+ }
+}
+
+template <typename T>
+typename std::enable_if<has_ScalarTraits<T>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
+ if ( io.outputting() ) {
+ std::string Storage;
+ raw_string_ostream Buffer(Storage);
+ ScalarTraits<T>::output(Val, io.getContext(), Buffer);
+ StringRef Str = Buffer.str();
+ io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
+ }
+ else {
+ StringRef Str;
+ io.scalarString(Str, ScalarTraits<T>::mustQuote(Str));
+ StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val);
+ if ( !Result.empty() ) {
+ io.setError(Twine(Result));
+ }
+ }
+}
+
+template <typename T>
+typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type
+yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
+ if (YamlIO.outputting()) {
+ std::string Storage;
+ raw_string_ostream Buffer(Storage);
+ BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer);
+ StringRef Str = Buffer.str();
+ YamlIO.blockScalarString(Str);
+ } else {
+ StringRef Str;
+ YamlIO.blockScalarString(Str);
+ StringRef Result =
+ BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val);
+ if (!Result.empty())
+ YamlIO.setError(Twine(Result));
+ }
+}
+
+template <typename T>
+typename std::enable_if<has_TaggedScalarTraits<T>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
+ if (io.outputting()) {
+ std::string ScalarStorage, TagStorage;
+ raw_string_ostream ScalarBuffer(ScalarStorage), TagBuffer(TagStorage);
+ TaggedScalarTraits<T>::output(Val, io.getContext(), ScalarBuffer,
+ TagBuffer);
+ io.scalarTag(TagBuffer.str());
+ StringRef ScalarStr = ScalarBuffer.str();
+ io.scalarString(ScalarStr,
+ TaggedScalarTraits<T>::mustQuote(Val, ScalarStr));
+ } else {
+ std::string Tag;
+ io.scalarTag(Tag);
+ StringRef Str;
+ io.scalarString(Str, QuotingType::None);
+ StringRef Result =
+ TaggedScalarTraits<T>::input(Str, Tag, io.getContext(), Val);
+ if (!Result.empty()) {
+ io.setError(Twine(Result));
+ }
+ }
+}
+
+template <typename T, typename Context>
+typename std::enable_if<validatedMappingTraits<T, Context>::value, void>::type
+yamlize(IO &io, T &Val, bool, Context &Ctx) {
+ if (has_FlowTraits<MappingTraits<T>>::value)
+ io.beginFlowMapping();
+ else
+ io.beginMapping();
+ if (io.outputting()) {
+ StringRef Err = MappingTraits<T>::validate(io, Val);
+ if (!Err.empty()) {
+ errs() << Err << "\n";
+ assert(Err.empty() && "invalid struct trying to be written as yaml");
+ }
+ }
+ detail::doMapping(io, Val, Ctx);
+ if (!io.outputting()) {
+ StringRef Err = MappingTraits<T>::validate(io, Val);
+ if (!Err.empty())
+ io.setError(Err);
+ }
+ if (has_FlowTraits<MappingTraits<T>>::value)
+ io.endFlowMapping();
+ else
+ io.endMapping();
+}
+
+template <typename T, typename Context>
+typename std::enable_if<unvalidatedMappingTraits<T, Context>::value, void>::type
+yamlize(IO &io, T &Val, bool, Context &Ctx) {
+ if (has_FlowTraits<MappingTraits<T>>::value) {
+ io.beginFlowMapping();
+ detail::doMapping(io, Val, Ctx);
+ io.endFlowMapping();
+ } else {
+ io.beginMapping();
+ detail::doMapping(io, Val, Ctx);
+ io.endMapping();
+ }
+}
+
+template <typename T>
+typename std::enable_if<has_CustomMappingTraits<T>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
+ if ( io.outputting() ) {
+ io.beginMapping();
+ CustomMappingTraits<T>::output(io, Val);
+ io.endMapping();
+ } else {
+ io.beginMapping();
+ for (StringRef key : io.keys())
+ CustomMappingTraits<T>::inputOne(io, key, Val);
+ io.endMapping();
+ }
+}
+
+template <typename T>
+typename std::enable_if<has_PolymorphicTraits<T>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
+ switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val)
+ : io.getNodeKind()) {
+ case NodeKind::Scalar:
+ return yamlize(io, PolymorphicTraits<T>::getAsScalar(Val), true, Ctx);
+ case NodeKind::Map:
+ return yamlize(io, PolymorphicTraits<T>::getAsMap(Val), true, Ctx);
+ case NodeKind::Sequence:
+ return yamlize(io, PolymorphicTraits<T>::getAsSequence(Val), true, Ctx);
+ }
+}
+
+template <typename T>
+typename std::enable_if<missingTraits<T, EmptyContext>::value, void>::type
+yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
+ char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
+}
+
+template <typename T, typename Context>
+typename std::enable_if<has_SequenceTraits<T>::value, void>::type
+yamlize(IO &io, T &Seq, bool, Context &Ctx) {
+ if ( has_FlowTraits< SequenceTraits<T>>::value ) {
+ unsigned incnt = io.beginFlowSequence();
+ unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
+ for(unsigned i=0; i < count; ++i) {
+ void *SaveInfo;
+ if ( io.preflightFlowElement(i, SaveInfo) ) {
+ yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
+ io.postflightFlowElement(SaveInfo);
+ }
+ }
+ io.endFlowSequence();
+ }
+ else {
+ unsigned incnt = io.beginSequence();
+ unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt;
+ for(unsigned i=0; i < count; ++i) {
+ void *SaveInfo;
+ if ( io.preflightElement(i, SaveInfo) ) {
+ yamlize(io, SequenceTraits<T>::element(io, Seq, i), true, Ctx);
+ io.postflightElement(SaveInfo);
+ }
+ }
+ io.endSequence();
+ }
+}
+
+template<>
+struct ScalarTraits<bool> {
+ static void output(const bool &, void* , raw_ostream &);
+ static StringRef input(StringRef, void *, bool &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<StringRef> {
+ static void output(const StringRef &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, StringRef &);
+ static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
+};
+
+template<>
+struct ScalarTraits<std::string> {
+ static void output(const std::string &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, std::string &);
+ static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
+};
+
+template<>
+struct ScalarTraits<uint8_t> {
+ static void output(const uint8_t &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, uint8_t &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<uint16_t> {
+ static void output(const uint16_t &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, uint16_t &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<uint32_t> {
+ static void output(const uint32_t &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, uint32_t &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<uint64_t> {
+ static void output(const uint64_t &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, uint64_t &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<int8_t> {
+ static void output(const int8_t &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, int8_t &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<int16_t> {
+ static void output(const int16_t &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, int16_t &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<int32_t> {
+ static void output(const int32_t &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, int32_t &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<int64_t> {
+ static void output(const int64_t &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, int64_t &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<float> {
+ static void output(const float &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, float &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<double> {
+ static void output(const double &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, double &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+// 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>,
+ typename std::enable_if<has_ScalarTraits<value_type>::value>::type> {
+ using endian_type =
+ support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>;
+
+ static void output(const endian_type &E, void *Ctx, raw_ostream &Stream) {
+ ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
+ }
+
+ static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
+ value_type V;
+ auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
+ E = static_cast<endian_type>(V);
+ return R;
+ }
+
+ static QuotingType mustQuote(StringRef Str) {
+ return ScalarTraits<value_type>::mustQuote(Str);
+ }
+};
+
+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>
+struct MappingNormalization {
+ MappingNormalization(IO &i_o, TFinal &Obj)
+ : io(i_o), BufPtr(nullptr), Result(Obj) {
+ if ( io.outputting() ) {
+ BufPtr = new (&Buffer) TNorm(io, Obj);
+ }
+ else {
+ BufPtr = new (&Buffer) TNorm(io);
+ }
+ }
+
+ ~MappingNormalization() {
+ if ( ! io.outputting() ) {
+ Result = BufPtr->denormalize(io);
+ }
+ BufPtr->~TNorm();
+ }
+
+ TNorm* operator->() { return BufPtr; }
+
+private:
+ using Storage = AlignedCharArrayUnion<TNorm>;
+
+ Storage Buffer;
+ IO &io;
+ TNorm *BufPtr;
+ TFinal &Result;
+};
+
+// Utility for use within MappingTraits<>::mapping() method
+// to [de]normalize an object for use with YAML conversion.
+template <typename TNorm, typename TFinal>
+struct MappingNormalizationHeap {
+ MappingNormalizationHeap(IO &i_o, TFinal &Obj, BumpPtrAllocator *allocator)
+ : io(i_o), Result(Obj) {
+ if ( io.outputting() ) {
+ BufPtr = new (&Buffer) TNorm(io, Obj);
+ }
+ else if (allocator) {
+ BufPtr = allocator->Allocate<TNorm>();
+ new (BufPtr) TNorm(io);
+ } else {
+ BufPtr = new TNorm(io);
+ }
+ }
+
+ ~MappingNormalizationHeap() {
+ if ( io.outputting() ) {
+ BufPtr->~TNorm();
+ }
+ else {
+ Result = BufPtr->denormalize(io);
+ }
+ }
+
+ TNorm* operator->() { return BufPtr; }
+
+private:
+ using Storage = AlignedCharArrayUnion<TNorm>;
+
+ Storage Buffer;
+ IO &io;
+ TNorm *BufPtr = nullptr;
+ TFinal &Result;
+};
+
+///
+/// The Input class is used to parse a yaml document into in-memory structs
+/// and vectors.
+///
+/// It works by using YAMLParser to do a syntax parse of the entire yaml
+/// document, then the Input class builds a graph of HNodes which wraps
+/// each yaml Node. The extra layer is buffering. The low level yaml
+/// parser only lets you look at each node once. The buffering layer lets
+/// you search and interate multiple times. This is necessary because
+/// the mapRequired() method calls may not be in the same order
+/// as the keys in the document.
+///
+class Input : public IO {
+public:
+ // Construct a yaml Input object from a StringRef and optional
+ // user-data. The DiagHandler can be specified to provide
+ // alternative error reporting.
+ Input(StringRef InputContent,
+ void *Ctxt = nullptr,
+ SourceMgr::DiagHandlerTy DiagHandler = nullptr,
+ void *DiagHandlerCtxt = nullptr);
+ Input(MemoryBufferRef Input,
+ void *Ctxt = nullptr,
+ SourceMgr::DiagHandlerTy DiagHandler = nullptr,
+ void *DiagHandlerCtxt = nullptr);
+ ~Input() override;
+
+ // Check if there was an syntax or semantic error during parsing.
+ std::error_code error();
+
+private:
+ bool outputting() const override;
+ bool mapTag(StringRef, bool) override;
+ void beginMapping() override;
+ void endMapping() override;
+ bool preflightKey(const char *, bool, bool, bool &, void *&) override;
+ void postflightKey(void *) override;
+ std::vector<StringRef> keys() override;
+ void beginFlowMapping() override;
+ void endFlowMapping() override;
+ unsigned beginSequence() override;
+ void endSequence() override;
+ bool preflightElement(unsigned index, void *&) override;
+ void postflightElement(void *) override;
+ unsigned beginFlowSequence() override;
+ bool preflightFlowElement(unsigned , void *&) override;
+ void postflightFlowElement(void *) override;
+ void endFlowSequence() override;
+ void beginEnumScalar() override;
+ bool matchEnumScalar(const char*, bool) override;
+ bool matchEnumFallback() override;
+ void endEnumScalar() override;
+ bool beginBitSetScalar(bool &) override;
+ bool bitSetMatch(const char *, bool ) override;
+ void endBitSetScalar() override;
+ void scalarString(StringRef &, QuotingType) override;
+ void blockScalarString(StringRef &) override;
+ void scalarTag(std::string &) override;
+ NodeKind getNodeKind() override;
+ void setError(const Twine &message) override;
+ bool canElideEmptySequence() override;
+
+ class HNode {
+ virtual void anchor();
+
+ public:
+ HNode(Node *n) : _node(n) { }
+ virtual ~HNode() = default;
+
+ static bool classof(const HNode *) { return true; }
+
+ Node *_node;
+ };
+
+ class EmptyHNode : public HNode {
+ void anchor() override;
+
+ public:
+ EmptyHNode(Node *n) : HNode(n) { }
+
+ static bool classof(const HNode *n) { return NullNode::classof(n->_node); }
+
+ static bool classof(const EmptyHNode *) { return true; }
+ };
+
+ class ScalarHNode : public HNode {
+ void anchor() override;
+
+ public:
+ ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { }
+
+ StringRef value() const { return _value; }
+
+ static bool classof(const HNode *n) {
+ return ScalarNode::classof(n->_node) ||
+ BlockScalarNode::classof(n->_node);
+ }
+
+ static bool classof(const ScalarHNode *) { return true; }
+
+ protected:
+ StringRef _value;
+ };
+
+ class MapHNode : public HNode {
+ void anchor() override;
+
+ public:
+ MapHNode(Node *n) : HNode(n) { }
+
+ static bool classof(const HNode *n) {
+ return MappingNode::classof(n->_node);
+ }
+
+ static bool classof(const MapHNode *) { return true; }
+
+ using NameToNode = StringMap<std::unique_ptr<HNode>>;
+
+ NameToNode Mapping;
+ SmallVector<std::string, 6> ValidKeys;
+ };
+
+ class SequenceHNode : public HNode {
+ void anchor() override;
+
+ public:
+ SequenceHNode(Node *n) : HNode(n) { }
+
+ static bool classof(const HNode *n) {
+ return SequenceNode::classof(n->_node);
+ }
+
+ static bool classof(const SequenceHNode *) { return true; }
+
+ std::vector<std::unique_ptr<HNode>> Entries;
+ };
+
+ std::unique_ptr<Input::HNode> createHNodes(Node *node);
+ void setError(HNode *hnode, const Twine &message);
+ void setError(Node *node, const Twine &message);
+
+public:
+ // These are only used by operator>>. They could be private
+ // if those templated things could be made friends.
+ bool setCurrentDocument();
+ bool nextDocument();
+
+ /// Returns the current node that's being parsed by the YAML Parser.
+ const Node *getCurrentNode() const;
+
+private:
+ SourceMgr SrcMgr; // must be before Strm
+ std::unique_ptr<llvm::yaml::Stream> Strm;
+ std::unique_ptr<HNode> TopNode;
+ std::error_code EC;
+ BumpPtrAllocator StringAllocator;
+ document_iterator DocIterator;
+ std::vector<bool> BitValuesUsed;
+ HNode *CurrentNode = nullptr;
+ bool ScalarMatchFound = false;
+};
+
+///
+/// The Output class is used to generate a yaml document from in-memory structs
+/// and vectors.
+///
+class Output : public IO {
+public:
+ Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
+ ~Output() override;
+
+ /// Set whether or not to output optional values which are equal
+ /// to the default value. By default, when outputting if you attempt
+ /// to write a value that is equal to the default, the value gets ignored.
+ /// Sometimes, it is useful to be able to see these in the resulting YAML
+ /// anyway.
+ void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
+
+ bool outputting() const override;
+ bool mapTag(StringRef, bool) override;
+ void beginMapping() override;
+ void endMapping() override;
+ bool preflightKey(const char *key, bool, bool, bool &, void *&) override;
+ void postflightKey(void *) override;
+ std::vector<StringRef> keys() override;
+ void beginFlowMapping() override;
+ void endFlowMapping() override;
+ unsigned beginSequence() override;
+ void endSequence() override;
+ bool preflightElement(unsigned, void *&) override;
+ void postflightElement(void *) override;
+ unsigned beginFlowSequence() override;
+ bool preflightFlowElement(unsigned, void *&) override;
+ void postflightFlowElement(void *) override;
+ void endFlowSequence() override;
+ void beginEnumScalar() override;
+ bool matchEnumScalar(const char*, bool) override;
+ bool matchEnumFallback() override;
+ void endEnumScalar() override;
+ bool beginBitSetScalar(bool &) override;
+ bool bitSetMatch(const char *, bool ) override;
+ void endBitSetScalar() override;
+ void scalarString(StringRef &, QuotingType) override;
+ void blockScalarString(StringRef &) override;
+ void scalarTag(std::string &) override;
+ NodeKind getNodeKind() override;
+ void setError(const Twine &message) override;
+ bool canElideEmptySequence() override;
+
+ // These are only used by operator<<. They could be private
+ // if that templated operator could be made a friend.
+ void beginDocuments();
+ bool preflightDocument(unsigned);
+ void postflightDocument();
+ void endDocuments();
+
+private:
+ void output(StringRef s);
+ void outputUpToEndOfLine(StringRef s);
+ void newLineCheck();
+ void outputNewLine();
+ void paddedKey(StringRef key);
+ void flowKey(StringRef Key);
+
+ enum InState {
+ inSeqFirstElement,
+ inSeqOtherElement,
+ inFlowSeqFirstElement,
+ inFlowSeqOtherElement,
+ inMapFirstKey,
+ inMapOtherKey,
+ inFlowMapFirstKey,
+ inFlowMapOtherKey
+ };
+
+ static bool inSeqAnyElement(InState State);
+ static bool inFlowSeqAnyElement(InState State);
+ static bool inMapAnyKey(InState State);
+ static bool inFlowMapAnyKey(InState State);
+
+ raw_ostream &Out;
+ int WrapColumn;
+ SmallVector<InState, 8> StateStack;
+ int Column = 0;
+ int ColumnAtFlowStart = 0;
+ int ColumnAtMapFlowStart = 0;
+ bool NeedBitValueComma = false;
+ bool NeedFlowSequenceComma = false;
+ bool EnumerationMatchFound = false;
+ bool WriteDefaultValues = false;
+ StringRef Padding;
+ StringRef PaddingBeforeContainer;
+};
+
+/// YAML I/O does conversion based on types. But often native data types
+/// are just a typedef of built in intergral types (e.g. int). But the C++
+/// type matching system sees through the typedef and all the typedefed types
+/// look like a built in type. This will cause the generic YAML I/O conversion
+/// to be used. To provide better control over the YAML conversion, you can
+/// use this macro instead of typedef. It will create a class with one field
+/// and automatic conversion operators to and from the base type.
+/// Based on BOOST_STRONG_TYPEDEF
+#define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \
+ struct _type { \
+ _type() = default; \
+ _type(const _base v) : value(v) {} \
+ _type(const _type &v) = default; \
+ _type &operator=(const _type &rhs) = default; \
+ _type &operator=(const _base &rhs) { value = rhs; return *this; } \
+ operator const _base & () const { return value; } \
+ bool operator==(const _type &rhs) const { return value == rhs.value; } \
+ bool operator==(const _base &rhs) const { return value == rhs; } \
+ bool operator<(const _type &rhs) const { return value < rhs.value; } \
+ _base value; \
+ using BaseType = _base; \
+ };
+
+///
+/// Use these types instead of uintXX_t in any mapping to have
+/// its yaml output formatted as hexadecimal.
+///
+LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8)
+LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32)
+LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64)
+
+template<>
+struct ScalarTraits<Hex8> {
+ static void output(const Hex8 &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, Hex8 &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<Hex16> {
+ static void output(const Hex16 &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, Hex16 &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<Hex32> {
+ static void output(const Hex32 &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, Hex32 &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+template<>
+struct ScalarTraits<Hex64> {
+ static void output(const Hex64 &, void *, raw_ostream &);
+ static StringRef input(StringRef, void *, Hex64 &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
+// Define non-member operator>> so that Input can stream in a document list.
+template <typename T>
+inline
+typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type
+operator>>(Input &yin, T &docList) {
+ int i = 0;
+ EmptyContext Ctx;
+ while ( yin.setCurrentDocument() ) {
+ yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true, Ctx);
+ if ( yin.error() )
+ return yin;
+ yin.nextDocument();
+ ++i;
+ }
+ return yin;
+}
+
+// Define non-member operator>> so that Input can stream in a map as a document.
+template <typename T>
+inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
+ Input &>::type
+operator>>(Input &yin, T &docMap) {
+ EmptyContext Ctx;
+ yin.setCurrentDocument();
+ yamlize(yin, docMap, true, Ctx);
+ return yin;
+}
+
+// Define non-member operator>> so that Input can stream in a sequence as
+// a document.
+template <typename T>
+inline
+typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type
+operator>>(Input &yin, T &docSeq) {
+ EmptyContext Ctx;
+ if (yin.setCurrentDocument())
+ yamlize(yin, docSeq, true, Ctx);
+ return yin;
+}
+
+// Define non-member operator>> so that Input can stream in a block scalar.
+template <typename T>
+inline
+typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type
+operator>>(Input &In, T &Val) {
+ EmptyContext Ctx;
+ if (In.setCurrentDocument())
+ yamlize(In, Val, true, Ctx);
+ return In;
+}
+
+// Define non-member operator>> so that Input can stream in a string map.
+template <typename T>
+inline
+typename std::enable_if<has_CustomMappingTraits<T>::value, Input &>::type
+operator>>(Input &In, T &Val) {
+ EmptyContext Ctx;
+ if (In.setCurrentDocument())
+ yamlize(In, Val, true, Ctx);
+ return In;
+}
+
+// Define non-member operator>> so that Input can stream in a polymorphic type.
+template <typename T>
+inline typename std::enable_if<has_PolymorphicTraits<T>::value, Input &>::type
+operator>>(Input &In, T &Val) {
+ EmptyContext Ctx;
+ if (In.setCurrentDocument())
+ yamlize(In, Val, true, Ctx);
+ return In;
+}
+
+// Provide better error message about types missing a trait specialization
+template <typename T>
+inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
+ Input &>::type
+operator>>(Input &yin, T &docSeq) {
+ char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
+ return yin;
+}
+
+// Define non-member operator<< so that Output can stream out document list.
+template <typename T>
+inline
+typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type
+operator<<(Output &yout, T &docList) {
+ EmptyContext Ctx;
+ yout.beginDocuments();
+ const size_t count = DocumentListTraits<T>::size(yout, docList);
+ for(size_t i=0; i < count; ++i) {
+ if ( yout.preflightDocument(i) ) {
+ yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true,
+ Ctx);
+ yout.postflightDocument();
+ }
+ }
+ yout.endDocuments();
+ return yout;
+}
+
+// Define non-member operator<< so that Output can stream out a map.
+template <typename T>
+inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
+ Output &>::type
+operator<<(Output &yout, T &map) {
+ EmptyContext Ctx;
+ yout.beginDocuments();
+ if ( yout.preflightDocument(0) ) {
+ yamlize(yout, map, true, Ctx);
+ yout.postflightDocument();
+ }
+ yout.endDocuments();
+ return yout;
+}
+
+// Define non-member operator<< so that Output can stream out a sequence.
+template <typename T>
+inline
+typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type
+operator<<(Output &yout, T &seq) {
+ EmptyContext Ctx;
+ yout.beginDocuments();
+ if ( yout.preflightDocument(0) ) {
+ yamlize(yout, seq, true, Ctx);
+ yout.postflightDocument();
+ }
+ yout.endDocuments();
+ return yout;
+}
+
+// Define non-member operator<< so that Output can stream out a block scalar.
+template <typename T>
+inline
+typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type
+operator<<(Output &Out, T &Val) {
+ EmptyContext Ctx;
+ Out.beginDocuments();
+ if (Out.preflightDocument(0)) {
+ yamlize(Out, Val, true, Ctx);
+ Out.postflightDocument();
+ }
+ Out.endDocuments();
+ return Out;
+}
+
+// Define non-member operator<< so that Output can stream out a string map.
+template <typename T>
+inline
+typename std::enable_if<has_CustomMappingTraits<T>::value, Output &>::type
+operator<<(Output &Out, T &Val) {
+ EmptyContext Ctx;
+ Out.beginDocuments();
+ if (Out.preflightDocument(0)) {
+ yamlize(Out, Val, true, Ctx);
+ Out.postflightDocument();
+ }
+ Out.endDocuments();
+ return Out;
+}
+
+// Define non-member operator<< so that Output can stream out a polymorphic
+// type.
+template <typename T>
+inline typename std::enable_if<has_PolymorphicTraits<T>::value, Output &>::type
+operator<<(Output &Out, T &Val) {
+ EmptyContext Ctx;
+ Out.beginDocuments();
+ if (Out.preflightDocument(0)) {
+ // FIXME: The parser does not support explicit documents terminated with a
+ // plain scalar; the end-marker is included as part of the scalar token.
+ assert(PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar && "plain scalar documents are not supported");
+ yamlize(Out, Val, true, Ctx);
+ Out.postflightDocument();
+ }
+ Out.endDocuments();
+ return Out;
+}
+
+// Provide better error message about types missing a trait specialization
+template <typename T>
+inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
+ Output &>::type
+operator<<(Output &yout, T &seq) {
+ char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
+ return yout;
+}
+
+template <bool B> struct IsFlowSequenceBase {};
+template <> struct IsFlowSequenceBase<true> { static const bool flow = true; };
+
+template <typename T, bool Flow>
+struct SequenceTraitsImpl : IsFlowSequenceBase<Flow> {
+private:
+ using type = typename T::value_type;
+
+public:
+ static size_t size(IO &io, T &seq) { return seq.size(); }
+
+ static type &element(IO &io, T &seq, size_t index) {
+ if (index >= seq.size())
+ seq.resize(index + 1);
+ return seq[index];
+ }
+};
+
+// Simple helper to check an expression can be used as a bool-valued template
+// argument.
+template <bool> struct CheckIsBool { static const bool value = true; };
+
+// If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
+// SequenceTraits that do the obvious thing.
+template <typename T>
+struct SequenceTraits<std::vector<T>,
+ typename std::enable_if<CheckIsBool<
+ SequenceElementTraits<T>::flow>::value>::type>
+ : SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
+template <typename T, unsigned N>
+struct SequenceTraits<SmallVector<T, N>,
+ typename std::enable_if<CheckIsBool<
+ SequenceElementTraits<T>::flow>::value>::type>
+ : 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>
+struct SequenceElementTraits<
+ T, typename std::enable_if<std::is_fundamental<T>::value>::type> {
+ static const bool flow = true;
+};
+
+// Sequences of strings use block formatting.
+template<> struct SequenceElementTraits<std::string> {
+ static const bool flow = false;
+};
+template<> struct SequenceElementTraits<StringRef> {
+ static const bool flow = false;
+};
+template<> struct SequenceElementTraits<std::pair<std::string, std::string>> {
+ static const bool flow = false;
+};
+
+/// Implementation of CustomMappingTraits for std::map<std::string, T>.
+template <typename T> struct StdMapStringCustomMappingTraitsImpl {
+ using map_type = std::map<std::string, T>;
+
+ static void inputOne(IO &io, StringRef key, map_type &v) {
+ io.mapRequired(key.str().c_str(), v[key]);
+ }
+
+ static void output(IO &io, map_type &v) {
+ for (auto &p : v)
+ io.mapRequired(p.first.c_str(), p.second);
+ }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+#define LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(TYPE, FLOW) \
+ namespace llvm { \
+ namespace yaml { \
+ static_assert( \
+ !std::is_fundamental<TYPE>::value && \
+ !std::is_same<TYPE, std::string>::value && \
+ !std::is_same<TYPE, llvm::StringRef>::value, \
+ "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control"); \
+ template <> struct SequenceElementTraits<TYPE> { \
+ static const bool flow = FLOW; \
+ }; \
+ } \
+ }
+
+/// Utility for declaring that a std::vector of a particular type
+/// should be considered a YAML sequence.
+#define LLVM_YAML_IS_SEQUENCE_VECTOR(type) \
+ LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, false)
+
+/// Utility for declaring that a std::vector of a particular type
+/// should be considered a YAML flow sequence.
+#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(type) \
+ LLVM_YAML_IS_SEQUENCE_VECTOR_IMPL(type, true)
+
+#define LLVM_YAML_DECLARE_MAPPING_TRAITS(Type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <> struct MappingTraits<Type> { \
+ static void mapping(IO &IO, Type &Obj); \
+ }; \
+ } \
+ }
+
+#define LLVM_YAML_DECLARE_ENUM_TRAITS(Type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <> struct ScalarEnumerationTraits<Type> { \
+ static void enumeration(IO &io, Type &Value); \
+ }; \
+ } \
+ }
+
+#define LLVM_YAML_DECLARE_BITSET_TRAITS(Type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <> struct ScalarBitSetTraits<Type> { \
+ static void bitset(IO &IO, Type &Options); \
+ }; \
+ } \
+ }
+
+#define LLVM_YAML_DECLARE_SCALAR_TRAITS(Type, MustQuote) \
+ namespace llvm { \
+ namespace yaml { \
+ template <> struct ScalarTraits<Type> { \
+ static void output(const Type &Value, void *ctx, raw_ostream &Out); \
+ static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \
+ static QuotingType mustQuote(StringRef) { return MustQuote; } \
+ }; \
+ } \
+ }
+
+/// Utility for declaring that a std::vector of a particular type
+/// should be considered a YAML document list.
+#define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <unsigned N> \
+ struct DocumentListTraits<SmallVector<_type, N>> \
+ : public SequenceTraitsImpl<SmallVector<_type, N>, false> {}; \
+ template <> \
+ struct DocumentListTraits<std::vector<_type>> \
+ : public SequenceTraitsImpl<std::vector<_type>, false> {}; \
+ } \
+ }
+
+/// Utility for declaring that std::map<std::string, _type> should be considered
+/// a YAML map.
+#define LLVM_YAML_IS_STRING_MAP(_type) \
+ namespace llvm { \
+ namespace yaml { \
+ template <> \
+ struct CustomMappingTraits<std::map<std::string, _type>> \
+ : public StdMapStringCustomMappingTraitsImpl<_type> {}; \
+ } \
+ }
+
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex32)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex16)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex8)
+
+#endif // LLVM_SUPPORT_YAMLTRAITS_H
diff --git a/third_party/llvm-project/include/llvm/Support/circular_raw_ostream.h b/third_party/llvm-project/include/llvm/Support/circular_raw_ostream.h
new file mode 100644
index 000000000..a72acd4fe
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/circular_raw_ostream.h
@@ -0,0 +1,159 @@
+//===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- 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 raw_ostream implementations for streams to do circular
+// buffering of their output.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H
+#define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+ /// circular_raw_ostream - A raw_ostream which *can* save its data
+ /// to a circular buffer, or can pass it through directly to an
+ /// underlying stream if specified with a buffer of zero.
+ ///
+ class circular_raw_ostream : public raw_ostream {
+ public:
+ /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying
+ /// stream and is responsible for cleanup, memory management
+ /// issues, etc.
+ ///
+ static const bool TAKE_OWNERSHIP = true;
+
+ /// REFERENCE_ONLY - Tell this stream it should not manage the
+ /// held stream.
+ ///
+ static const bool REFERENCE_ONLY = false;
+
+ private:
+ /// TheStream - The real stream we output to. We set it to be
+ /// unbuffered, since we're already doing our own buffering.
+ ///
+ raw_ostream *TheStream;
+
+ /// OwnsStream - Are we responsible for managing the underlying
+ /// stream?
+ ///
+ bool OwnsStream;
+
+ /// BufferSize - The size of the buffer in bytes.
+ ///
+ size_t BufferSize;
+
+ /// BufferArray - The actual buffer storage.
+ ///
+ char *BufferArray;
+
+ /// Cur - Pointer to the current output point in BufferArray.
+ ///
+ char *Cur;
+
+ /// Filled - Indicate whether the buffer has been completely
+ /// filled. This helps avoid garbage output.
+ ///
+ bool Filled;
+
+ /// Banner - A pointer to a banner to print before dumping the
+ /// log.
+ ///
+ const char *Banner;
+
+ /// flushBuffer - Dump the contents of the buffer to Stream.
+ ///
+ void flushBuffer() {
+ if (Filled)
+ // Write the older portion of the buffer.
+ TheStream->write(Cur, BufferArray + BufferSize - Cur);
+ // Write the newer portion of the buffer.
+ TheStream->write(BufferArray, Cur - BufferArray);
+ Cur = BufferArray;
+ Filled = false;
+ }
+
+ void write_impl(const char *Ptr, size_t Size) override;
+
+ /// current_pos - Return the current position within the stream,
+ /// not counting the bytes currently in the buffer.
+ ///
+ uint64_t current_pos() const override {
+ // This has the same effect as calling TheStream.current_pos(),
+ // but that interface is private.
+ return TheStream->tell() - TheStream->GetNumBytesInBuffer();
+ }
+
+ public:
+ /// circular_raw_ostream - Construct an optionally
+ /// circular-buffered stream, handing it an underlying stream to
+ /// do the "real" output.
+ ///
+ /// As a side effect, if BuffSize is nonzero, the given Stream is
+ /// set to be Unbuffered. This is because circular_raw_ostream
+ /// does its own buffering, so it doesn't want another layer of
+ /// buffering to be happening underneath it.
+ ///
+ /// "Owns" tells the circular_raw_ostream whether it is
+ /// responsible for managing the held stream, doing memory
+ /// management of it, etc.
+ ///
+ circular_raw_ostream(raw_ostream &Stream, const char *Header,
+ size_t BuffSize = 0, bool Owns = REFERENCE_ONLY)
+ : raw_ostream(/*unbuffered*/ true), TheStream(nullptr),
+ OwnsStream(Owns), BufferSize(BuffSize), BufferArray(nullptr),
+ Filled(false), Banner(Header) {
+ if (BufferSize != 0)
+ BufferArray = new char[BufferSize];
+ Cur = BufferArray;
+ setStream(Stream, Owns);
+ }
+
+ ~circular_raw_ostream() override {
+ flush();
+ flushBufferWithBanner();
+ releaseStream();
+ delete[] BufferArray;
+ }
+
+ bool is_displayed() const override {
+ return TheStream->is_displayed();
+ }
+
+ /// setStream - Tell the circular_raw_ostream to output a
+ /// different stream. "Owns" tells circular_raw_ostream whether
+ /// it should take responsibility for managing the underlying
+ /// stream.
+ ///
+ void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) {
+ releaseStream();
+ TheStream = &Stream;
+ OwnsStream = Owns;
+ }
+
+ /// flushBufferWithBanner - Force output of the buffer along with
+ /// a small header.
+ ///
+ void flushBufferWithBanner();
+
+ private:
+ /// releaseStream - Delete the held stream if needed. Otherwise,
+ /// transfer the buffer settings from this circular_raw_ostream
+ /// back to the underlying stream.
+ ///
+ void releaseStream() {
+ if (!TheStream)
+ return;
+ if (OwnsStream)
+ delete TheStream;
+ }
+ };
+} // end llvm namespace
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/Support/raw_ostream.h b/third_party/llvm-project/include/llvm/Support/raw_ostream.h
new file mode 100644
index 000000000..705f1790b
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/raw_ostream.h
@@ -0,0 +1,587 @@
+//===--- raw_ostream.h - Raw output stream ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the raw_ostream class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_RAW_OSTREAM_H
+#define LLVM_SUPPORT_RAW_OSTREAM_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <string>
+#include <system_error>
+
+namespace llvm {
+
+class formatv_object_base;
+class format_object_base;
+class FormattedString;
+class FormattedNumber;
+class FormattedBytes;
+
+namespace sys {
+namespace fs {
+enum FileAccess : unsigned;
+enum OpenFlags : unsigned;
+enum CreationDisposition : unsigned;
+} // end namespace fs
+} // end namespace sys
+
+/// This class implements an extremely fast bulk output stream that can *only*
+/// output to a stream. It does not support seeking, reopening, rewinding, line
+/// buffered disciplines etc. It is a simple buffer that outputs
+/// a chunk at a time.
+class raw_ostream {
+private:
+ /// The buffer is handled in such a way that the buffer is
+ /// uninitialized, unbuffered, or out of space when OutBufCur >=
+ /// OutBufEnd. Thus a single comparison suffices to determine if we
+ /// need to take the slow path to write a single character.
+ ///
+ /// The buffer is in one of three states:
+ /// 1. Unbuffered (BufferMode == Unbuffered)
+ /// 1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0).
+ /// 2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 &&
+ /// OutBufEnd - OutBufStart >= 1).
+ ///
+ /// If buffered, then the raw_ostream owns the buffer if (BufferMode ==
+ /// InternalBuffer); otherwise the buffer has been set via SetBuffer and is
+ /// managed by the subclass.
+ ///
+ /// If a subclass installs an external buffer using SetBuffer then it can wait
+ /// for a \see write_impl() call to handle the data which has been put into
+ /// this buffer.
+ char *OutBufStart, *OutBufEnd, *OutBufCur;
+
+ enum class BufferKind {
+ Unbuffered = 0,
+ InternalBuffer,
+ ExternalBuffer
+ } BufferMode;
+
+public:
+ // color order matches ANSI escape sequence, don't change
+ enum class Colors {
+ BLACK = 0,
+ RED,
+ GREEN,
+ YELLOW,
+ BLUE,
+ MAGENTA,
+ CYAN,
+ WHITE,
+ SAVEDCOLOR,
+ RESET,
+ };
+
+ static const Colors BLACK = Colors::BLACK;
+ static const Colors RED = Colors::RED;
+ static const Colors GREEN = Colors::GREEN;
+ static const Colors YELLOW = Colors::YELLOW;
+ static const Colors BLUE = Colors::BLUE;
+ static const Colors MAGENTA = Colors::MAGENTA;
+ static const Colors CYAN = Colors::CYAN;
+ static const Colors WHITE = Colors::WHITE;
+ static const Colors SAVEDCOLOR = Colors::SAVEDCOLOR;
+ static const Colors RESET = Colors::RESET;
+
+ explicit raw_ostream(bool unbuffered = false)
+ : BufferMode(unbuffered ? BufferKind::Unbuffered
+ : BufferKind::InternalBuffer) {
+ // Start out ready to flush.
+ OutBufStart = OutBufEnd = OutBufCur = nullptr;
+ }
+
+ raw_ostream(const raw_ostream &) = delete;
+ void operator=(const raw_ostream &) = delete;
+
+ virtual ~raw_ostream();
+
+ /// tell - Return the current offset with the file.
+ uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); }
+
+ //===--------------------------------------------------------------------===//
+ // Configuration Interface
+ //===--------------------------------------------------------------------===//
+
+ /// Set the stream to be buffered, with an automatically determined buffer
+ /// size.
+ void SetBuffered();
+
+ /// Set the stream to be buffered, using the specified buffer size.
+ void SetBufferSize(size_t Size) {
+ flush();
+ SetBufferAndMode(new char[Size], Size, BufferKind::InternalBuffer);
+ }
+
+ size_t GetBufferSize() const {
+ // If we're supposed to be buffered but haven't actually gotten around
+ // to allocating the buffer yet, return the value that would be used.
+ if (BufferMode != BufferKind::Unbuffered && OutBufStart == nullptr)
+ return preferred_buffer_size();
+
+ // Otherwise just return the size of the allocated buffer.
+ return OutBufEnd - OutBufStart;
+ }
+
+ /// Set the stream to be unbuffered. When unbuffered, the stream will flush
+ /// after every write. This routine will also flush the buffer immediately
+ /// when the stream is being set to unbuffered.
+ void SetUnbuffered() {
+ flush();
+ SetBufferAndMode(nullptr, 0, BufferKind::Unbuffered);
+ }
+
+ size_t GetNumBytesInBuffer() const {
+ return OutBufCur - OutBufStart;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Data Output Interface
+ //===--------------------------------------------------------------------===//
+
+ void flush() {
+ if (OutBufCur != OutBufStart)
+ flush_nonempty();
+ }
+
+ raw_ostream &operator<<(char C) {
+ if (OutBufCur >= OutBufEnd)
+ return write(C);
+ *OutBufCur++ = C;
+ return *this;
+ }
+
+ raw_ostream &operator<<(unsigned char C) {
+ if (OutBufCur >= OutBufEnd)
+ return write(C);
+ *OutBufCur++ = C;
+ return *this;
+ }
+
+ raw_ostream &operator<<(signed char C) {
+ if (OutBufCur >= OutBufEnd)
+ return write(C);
+ *OutBufCur++ = C;
+ return *this;
+ }
+
+ raw_ostream &operator<<(StringRef Str) {
+ // Inline fast path, particularly for strings with a known length.
+ size_t Size = Str.size();
+
+ // Make sure we can use the fast path.
+ if (Size > (size_t)(OutBufEnd - OutBufCur))
+ return write(Str.data(), Size);
+
+ if (Size) {
+ memcpy(OutBufCur, Str.data(), Size);
+ OutBufCur += Size;
+ }
+ return *this;
+ }
+
+ raw_ostream &operator<<(const char *Str) {
+ // Inline fast path, particularly for constant strings where a sufficiently
+ // smart compiler will simplify strlen.
+
+ return this->operator<<(StringRef(Str));
+ }
+
+ raw_ostream &operator<<(const std::string &Str) {
+ // Avoid the fast path, it would only increase code size for a marginal win.
+ return write(Str.data(), Str.length());
+ }
+
+ raw_ostream &operator<<(const SmallVectorImpl<char> &Str) {
+ return write(Str.data(), Str.size());
+ }
+
+ raw_ostream &operator<<(unsigned long N);
+ raw_ostream &operator<<(long N);
+ raw_ostream &operator<<(unsigned long long N);
+ raw_ostream &operator<<(long long N);
+ raw_ostream &operator<<(const void *P);
+
+ raw_ostream &operator<<(unsigned int N) {
+ return this->operator<<(static_cast<unsigned long>(N));
+ }
+
+ raw_ostream &operator<<(int N) {
+ return this->operator<<(static_cast<long>(N));
+ }
+
+ raw_ostream &operator<<(double N);
+
+ /// Output \p N in hexadecimal, without any prefix or padding.
+ raw_ostream &write_hex(unsigned long long N);
+
+ // Change the foreground color of text.
+ raw_ostream &operator<<(Colors C);
+
+ /// Output a formatted UUID with dash separators.
+ using uuid_t = uint8_t[16];
+ raw_ostream &write_uuid(const uuid_t UUID);
+
+ /// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't
+ /// satisfy llvm::isPrint into an escape sequence.
+ raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false);
+
+ raw_ostream &write(unsigned char C);
+ raw_ostream &write(const char *Ptr, size_t Size);
+
+ // Formatted output, see the format() function in Support/Format.h.
+ raw_ostream &operator<<(const format_object_base &Fmt);
+
+ // Formatted output, see the leftJustify() function in Support/Format.h.
+ raw_ostream &operator<<(const FormattedString &);
+
+ // Formatted output, see the formatHex() function in Support/Format.h.
+ raw_ostream &operator<<(const FormattedNumber &);
+
+ // Formatted output, see the formatv() function in Support/FormatVariadic.h.
+ raw_ostream &operator<<(const formatv_object_base &);
+
+ // Formatted output, see the format_bytes() function in Support/Format.h.
+ raw_ostream &operator<<(const FormattedBytes &);
+
+ /// indent - Insert 'NumSpaces' spaces.
+ raw_ostream &indent(unsigned NumSpaces);
+
+ /// write_zeros - Insert 'NumZeros' nulls.
+ raw_ostream &write_zeros(unsigned NumZeros);
+
+ /// Changes the foreground color of text that will be output from this point
+ /// forward.
+ /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to
+ /// change only the bold attribute, and keep colors untouched
+ /// @param Bold bold/brighter text, default false
+ /// @param BG if true change the background, default: change foreground
+ /// @returns itself so it can be used within << invocations
+ virtual raw_ostream &changeColor(enum Colors Color,
+ bool Bold = false,
+ bool BG = false) {
+ (void)Color;
+ (void)Bold;
+ (void)BG;
+ return *this;
+ }
+
+ /// Resets the colors to terminal defaults. Call this when you are done
+ /// outputting colored text, or before program exit.
+ virtual raw_ostream &resetColor() { return *this; }
+
+ /// Reverses the foreground and background colors.
+ virtual raw_ostream &reverseColor() { return *this; }
+
+ /// This function determines if this stream is connected to a "tty" or
+ /// "console" window. That is, the output would be displayed to the user
+ /// rather than being put on a pipe or stored in a file.
+ virtual bool is_displayed() const { return false; }
+
+ /// This function determines if this stream is displayed and supports colors.
+ virtual bool has_colors() const { return is_displayed(); }
+
+ // Enable or disable colors. Once disable_colors() is called,
+ // changeColor() has no effect until enable_colors() is called.
+ virtual void enable_colors(bool /*enable*/) {}
+
+ //===--------------------------------------------------------------------===//
+ // Subclass Interface
+ //===--------------------------------------------------------------------===//
+
+private:
+ /// The is the piece of the class that is implemented by subclasses. This
+ /// writes the \p Size bytes starting at
+ /// \p Ptr to the underlying stream.
+ ///
+ /// This function is guaranteed to only be called at a point at which it is
+ /// safe for the subclass to install a new buffer via SetBuffer.
+ ///
+ /// \param Ptr The start of the data to be written. For buffered streams this
+ /// is guaranteed to be the start of the buffer.
+ ///
+ /// \param Size The number of bytes to be written.
+ ///
+ /// \invariant { Size > 0 }
+ virtual void write_impl(const char *Ptr, size_t Size) = 0;
+
+ /// Return the current position within the stream, not counting the bytes
+ /// currently in the buffer.
+ virtual uint64_t current_pos() const = 0;
+
+protected:
+ /// Use the provided buffer as the raw_ostream buffer. This is intended for
+ /// use only by subclasses which can arrange for the output to go directly
+ /// into the desired output buffer, instead of being copied on each flush.
+ void SetBuffer(char *BufferStart, size_t Size) {
+ SetBufferAndMode(BufferStart, Size, BufferKind::ExternalBuffer);
+ }
+
+ /// Return an efficient buffer size for the underlying output mechanism.
+ virtual size_t preferred_buffer_size() const;
+
+ /// Return the beginning of the current stream buffer, or 0 if the stream is
+ /// unbuffered.
+ const char *getBufferStart() const { return OutBufStart; }
+
+ //===--------------------------------------------------------------------===//
+ // Private Interface
+ //===--------------------------------------------------------------------===//
+private:
+ /// Install the given buffer and mode.
+ void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode);
+
+ /// Flush the current buffer, which is known to be non-empty. This outputs the
+ /// currently buffered data and resets the buffer to empty.
+ void flush_nonempty();
+
+ /// Copy data into the buffer. Size must not be greater than the number of
+ /// unused bytes in the buffer.
+ void copy_to_buffer(const char *Ptr, size_t Size);
+
+ virtual void anchor();
+};
+
+/// An abstract base class for streams implementations that also support a
+/// pwrite operation. This is useful for code that can mostly stream out data,
+/// but needs to patch in a header that needs to know the output size.
+class raw_pwrite_stream : public raw_ostream {
+ virtual void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) = 0;
+ void anchor() override;
+
+public:
+ explicit raw_pwrite_stream(bool Unbuffered = false)
+ : raw_ostream(Unbuffered) {}
+ void pwrite(const char *Ptr, size_t Size, uint64_t Offset) {
+#ifndef NDEBUG
+ uint64_t Pos = tell();
+ // /dev/null always reports a pos of 0, so we cannot perform this check
+ // in that case.
+ if (Pos)
+ assert(Size + Offset <= Pos && "We don't support extending the stream");
+#endif
+ pwrite_impl(Ptr, Size, Offset);
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// File Output Streams
+//===----------------------------------------------------------------------===//
+
+/// A raw_ostream that writes to a file descriptor.
+///
+class raw_fd_ostream : public raw_pwrite_stream {
+ int FD;
+ bool ShouldClose;
+ bool SupportsSeeking = false;
+ bool ColorEnabled = true;
+
+#ifdef _WIN32
+ /// True if this fd refers to a Windows console device. Mintty and other
+ /// terminal emulators are TTYs, but they are not consoles.
+ bool IsWindowsConsole = false;
+#endif
+
+ std::error_code EC;
+
+ uint64_t pos = 0;
+
+ /// See raw_ostream::write_impl.
+ void write_impl(const char *Ptr, size_t Size) override;
+
+ void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override;
+
+ /// Return the current position within the stream, not counting the bytes
+ /// currently in the buffer.
+ uint64_t current_pos() const override { return pos; }
+
+ /// Determine an efficient buffer size.
+ size_t preferred_buffer_size() const override;
+
+ /// Set the flag indicating that an output error has been encountered.
+ void error_detected(std::error_code EC) { this->EC = EC; }
+
+ void anchor() override;
+
+public:
+ /// Open the specified file for writing. If an error occurs, information
+ /// about the error is put into EC, and the stream should be immediately
+ /// destroyed;
+ /// \p Flags allows optional flags to control how the file will be opened.
+ ///
+ /// As a special case, if Filename is "-", then the stream will use
+ /// STDOUT_FILENO instead of opening a file. This will not close the stdout
+ /// descriptor.
+ raw_fd_ostream(StringRef Filename, std::error_code &EC);
+ raw_fd_ostream(StringRef Filename, std::error_code &EC,
+ sys::fs::CreationDisposition Disp);
+ raw_fd_ostream(StringRef Filename, std::error_code &EC,
+ sys::fs::FileAccess Access);
+ raw_fd_ostream(StringRef Filename, std::error_code &EC,
+ sys::fs::OpenFlags Flags);
+ raw_fd_ostream(StringRef Filename, std::error_code &EC,
+ sys::fs::CreationDisposition Disp, sys::fs::FileAccess Access,
+ sys::fs::OpenFlags Flags);
+
+ /// FD is the file descriptor that this writes to. If ShouldClose is true,
+ /// this closes the file when the stream is destroyed. If FD is for stdout or
+ /// stderr, it will not be closed.
+ raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false);
+
+ ~raw_fd_ostream() override;
+
+ /// Manually flush the stream and close the file. Note that this does not call
+ /// fsync.
+ void close();
+
+ bool supportsSeeking() { return SupportsSeeking; }
+
+ /// Flushes the stream and repositions the underlying file descriptor position
+ /// to the offset specified from the beginning of the file.
+ uint64_t seek(uint64_t off);
+
+ raw_ostream &changeColor(enum Colors colors, bool bold=false,
+ bool bg=false) override;
+ raw_ostream &resetColor() override;
+
+ raw_ostream &reverseColor() override;
+
+ bool is_displayed() const override;
+
+ bool has_colors() const override;
+
+ void enable_colors(bool enable) override { ColorEnabled = enable; }
+
+ std::error_code error() const { return EC; }
+
+ /// Return the value of the flag in this raw_fd_ostream indicating whether an
+ /// output error has been encountered.
+ /// This doesn't implicitly flush any pending output. Also, it doesn't
+ /// guarantee to detect all errors unless the stream has been closed.
+ bool has_error() const { return bool(EC); }
+
+ /// Set the flag read by has_error() to false. If the error flag is set at the
+ /// time when this raw_ostream's destructor is called, report_fatal_error is
+ /// called to report the error. Use clear_error() after handling the error to
+ /// avoid this behavior.
+ ///
+ /// "Errors should never pass silently.
+ /// Unless explicitly silenced."
+ /// - from The Zen of Python, by Tim Peters
+ ///
+ void clear_error() { EC = std::error_code(); }
+};
+
+/// This returns a reference to a raw_ostream for standard output. Use it like:
+/// outs() << "foo" << "bar";
+raw_ostream &outs();
+
+/// This returns a reference to a raw_ostream for standard error. Use it like:
+/// errs() << "foo" << "bar";
+raw_ostream &errs();
+
+/// This returns a reference to a raw_ostream which simply discards output.
+raw_ostream &nulls();
+
+//===----------------------------------------------------------------------===//
+// Output Stream Adaptors
+//===----------------------------------------------------------------------===//
+
+/// A raw_ostream that writes to an std::string. This is a simple adaptor
+/// class. This class does not encounter output errors.
+class raw_string_ostream : public raw_ostream {
+ std::string &OS;
+
+ /// See raw_ostream::write_impl.
+ void write_impl(const char *Ptr, size_t Size) override;
+
+ /// Return the current position within the stream, not counting the bytes
+ /// currently in the buffer.
+ uint64_t current_pos() const override { return OS.size(); }
+
+public:
+ explicit raw_string_ostream(std::string &O) : OS(O) {}
+ ~raw_string_ostream() override;
+
+ /// Flushes the stream contents to the target string and returns the string's
+ /// reference.
+ std::string& str() {
+ flush();
+ return OS;
+ }
+};
+
+/// A raw_ostream that writes to an SmallVector or SmallString. This is a
+/// simple adaptor class. This class does not encounter output errors.
+/// raw_svector_ostream operates without a buffer, delegating all memory
+/// management to the SmallString. Thus the SmallString is always up-to-date,
+/// may be used directly and there is no need to call flush().
+class raw_svector_ostream : public raw_pwrite_stream {
+ SmallVectorImpl<char> &OS;
+
+ /// See raw_ostream::write_impl.
+ void write_impl(const char *Ptr, size_t Size) override;
+
+ void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override;
+
+ /// Return the current position within the stream.
+ uint64_t current_pos() const override;
+
+public:
+ /// Construct a new raw_svector_ostream.
+ ///
+ /// \param O The vector to write to; this should generally have at least 128
+ /// bytes free to avoid any extraneous memory overhead.
+ explicit raw_svector_ostream(SmallVectorImpl<char> &O) : OS(O) {
+ SetUnbuffered();
+ }
+
+ ~raw_svector_ostream() override = default;
+
+ void flush() = delete;
+
+ /// Return a StringRef for the vector contents.
+ StringRef str() { return StringRef(OS.data(), OS.size()); }
+};
+
+/// A raw_ostream that discards all output.
+class raw_null_ostream : public raw_pwrite_stream {
+ /// See raw_ostream::write_impl.
+ void write_impl(const char *Ptr, size_t size) override;
+ void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override;
+
+ /// Return the current position within the stream, not counting the bytes
+ /// currently in the buffer.
+ uint64_t current_pos() const override;
+
+public:
+ explicit raw_null_ostream() = default;
+ ~raw_null_ostream() override;
+};
+
+class buffer_ostream : public raw_svector_ostream {
+ raw_ostream &OS;
+ SmallVector<char, 0> Buffer;
+
+ virtual void anchor() override;
+
+public:
+ buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer), OS(OS) {}
+ ~buffer_ostream() override { OS << str(); }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_RAW_OSTREAM_H
diff --git a/third_party/llvm-project/include/llvm/Support/type_traits.h b/third_party/llvm-project/include/llvm/Support/type_traits.h
new file mode 100644
index 000000000..b7d48e8e1
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/Support/type_traits.h
@@ -0,0 +1,192 @@
+//===- llvm/Support/type_traits.h - Simplfied type traits -------*- 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 useful additions to the standard type_traits library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TYPE_TRAITS_H
+#define LLVM_SUPPORT_TYPE_TRAITS_H
+
+#include "llvm/Support/Compiler.h"
+#include <type_traits>
+#include <utility>
+
+namespace llvm {
+
+
+/// Metafunction that determines whether the given type is either an
+/// integral type or an enumeration type, including enum classes.
+///
+/// Note that this accepts potentially more integral types than is_integral
+/// because it is based on being implicitly convertible to an integral type.
+/// Also note that enum classes aren't implicitly convertible to integral types,
+/// the value may therefore need to be explicitly converted before being used.
+template <typename T> class is_integral_or_enum {
+ using UnderlyingT = typename std::remove_reference<T>::type;
+
+public:
+ static const bool value =
+ !std::is_class<UnderlyingT>::value && // Filter conversion operators.
+ !std::is_pointer<UnderlyingT>::value &&
+ !std::is_floating_point<UnderlyingT>::value &&
+ (std::is_enum<UnderlyingT>::value ||
+ std::is_convertible<UnderlyingT, unsigned long long>::value);
+};
+
+/// If T is a pointer, just return it. If it is not, return T&.
+template<typename T, typename Enable = void>
+struct add_lvalue_reference_if_not_pointer { using type = T &; };
+
+template <typename T>
+struct add_lvalue_reference_if_not_pointer<
+ T, typename std::enable_if<std::is_pointer<T>::value>::type> {
+ using type = T;
+};
+
+/// If T is a pointer to X, return a pointer to const X. If it is not,
+/// return const T.
+template<typename T, typename Enable = void>
+struct add_const_past_pointer { using type = const T; };
+
+template <typename T>
+struct add_const_past_pointer<
+ T, typename std::enable_if<std::is_pointer<T>::value>::type> {
+ using type = const typename std::remove_pointer<T>::type *;
+};
+
+template <typename T, typename Enable = void>
+struct const_pointer_or_const_ref {
+ using type = const T &;
+};
+template <typename T>
+struct const_pointer_or_const_ref<
+ T, typename std::enable_if<std::is_pointer<T>::value>::type> {
+ using type = typename add_const_past_pointer<T>::type;
+};
+
+namespace detail {
+/// Internal utility to detect trivial copy construction.
+template<typename T> union copy_construction_triviality_helper {
+ T t;
+ copy_construction_triviality_helper() = default;
+ copy_construction_triviality_helper(const copy_construction_triviality_helper&) = default;
+ ~copy_construction_triviality_helper() = default;
+};
+/// Internal utility to detect trivial move construction.
+template<typename T> union move_construction_triviality_helper {
+ T t;
+ move_construction_triviality_helper() = default;
+ move_construction_triviality_helper(move_construction_triviality_helper&&) = default;
+ ~move_construction_triviality_helper() = default;
+};
+
+template<class T>
+union trivial_helper {
+ T t;
+};
+
+} // end namespace detail
+
+/// An implementation of `std::is_trivially_copy_constructible` since we have
+/// users with STLs that don't yet include it.
+template <typename T>
+struct is_trivially_copy_constructible
+ : std::is_copy_constructible<
+ ::llvm::detail::copy_construction_triviality_helper<T>> {};
+template <typename T>
+struct is_trivially_copy_constructible<T &> : std::true_type {};
+template <typename T>
+struct is_trivially_copy_constructible<T &&> : std::false_type {};
+
+/// An implementation of `std::is_trivially_move_constructible` since we have
+/// users with STLs that don't yet include it.
+template <typename T>
+struct is_trivially_move_constructible
+ : std::is_move_constructible<
+ ::llvm::detail::move_construction_triviality_helper<T>> {};
+template <typename T>
+struct is_trivially_move_constructible<T &> : std::true_type {};
+template <typename T>
+struct is_trivially_move_constructible<T &&> : std::true_type {};
+
+
+template <typename T>
+struct is_copy_assignable {
+ template<class F>
+ static auto get(F*) -> decltype(std::declval<F &>() = std::declval<const F &>(), std::true_type{});
+ static std::false_type get(...);
+ static constexpr bool value = decltype(get((T*)nullptr))::value;
+};
+
+template <typename T>
+struct is_move_assignable {
+ template<class F>
+ static auto get(F*) -> decltype(std::declval<F &>() = std::declval<F &&>(), std::true_type{});
+ static std::false_type get(...);
+ static constexpr bool value = decltype(get((T*)nullptr))::value;
+};
+
+
+// An implementation of `std::is_trivially_copyable` since STL version
+// is not equally supported by all compilers, especially GCC 4.9.
+// Uniform implementation of this trait is important for ABI compatibility
+// as it has an impact on SmallVector's ABI (among others).
+template <typename T>
+class is_trivially_copyable {
+
+ // copy constructors
+ static constexpr bool has_trivial_copy_constructor =
+ std::is_copy_constructible<detail::trivial_helper<T>>::value;
+ static constexpr bool has_deleted_copy_constructor =
+ !std::is_copy_constructible<T>::value;
+
+ // move constructors
+ static constexpr bool has_trivial_move_constructor =
+ std::is_move_constructible<detail::trivial_helper<T>>::value;
+ static constexpr bool has_deleted_move_constructor =
+ !std::is_move_constructible<T>::value;
+
+ // copy assign
+ static constexpr bool has_trivial_copy_assign =
+ is_copy_assignable<detail::trivial_helper<T>>::value;
+ static constexpr bool has_deleted_copy_assign =
+ !is_copy_assignable<T>::value;
+
+ // move assign
+ static constexpr bool has_trivial_move_assign =
+ is_move_assignable<detail::trivial_helper<T>>::value;
+ static constexpr bool has_deleted_move_assign =
+ !is_move_assignable<T>::value;
+
+ // destructor
+ static constexpr bool has_trivial_destructor =
+ std::is_destructible<detail::trivial_helper<T>>::value;
+
+ public:
+
+ static constexpr bool value =
+ has_trivial_destructor &&
+ (has_deleted_move_assign || has_trivial_move_assign) &&
+ (has_deleted_move_constructor || has_trivial_move_constructor) &&
+ (has_deleted_copy_assign || has_trivial_copy_assign) &&
+ (has_deleted_copy_constructor || has_trivial_copy_constructor);
+
+#ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE
+ static_assert(value == std::is_trivially_copyable<T>::value,
+ "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
+#endif
+};
+template <typename T>
+class is_trivially_copyable<T*> : public std::true_type {
+};
+
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_TYPE_TRAITS_H