summaryrefslogtreecommitdiff
path: root/llvm/include/llvm/Support
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/include/llvm/Support')
-rw-r--r--llvm/include/llvm/Support/AArch64TargetParser.def30
-rw-r--r--llvm/include/llvm/Support/AArch64TargetParser.h11
-rw-r--r--llvm/include/llvm/Support/AMDGPUMetadata.h7
-rw-r--r--llvm/include/llvm/Support/ARMAttributeParser.h173
-rw-r--r--llvm/include/llvm/Support/ARMBuildAttributes.h109
-rw-r--r--llvm/include/llvm/Support/ARMTargetParser.def24
-rw-r--r--llvm/include/llvm/Support/ARMTargetParser.h50
-rw-r--r--llvm/include/llvm/Support/Alignment.h166
-rw-r--r--llvm/include/llvm/Support/Allocator.h150
-rw-r--r--llvm/include/llvm/Support/AllocatorBase.h103
-rw-r--r--llvm/include/llvm/Support/AtomicOrdering.h5
-rw-r--r--llvm/include/llvm/Support/Base64.h56
-rw-r--r--llvm/include/llvm/Support/BinaryStreamArray.h1
-rw-r--r--llvm/include/llvm/Support/BinaryStreamReader.h3
-rw-r--r--llvm/include/llvm/Support/BinaryStreamWriter.h2
-rw-r--r--llvm/include/llvm/Support/BranchProbability.h4
-rw-r--r--llvm/include/llvm/Support/CFGDiff.h250
-rw-r--r--llvm/include/llvm/Support/CFGUpdate.h12
-rw-r--r--llvm/include/llvm/Support/CachePruning.h3
-rw-r--r--llvm/include/llvm/Support/Casting.h64
-rw-r--r--llvm/include/llvm/Support/CheckedArithmetic.h18
-rw-r--r--llvm/include/llvm/Support/Chrono.h4
-rw-r--r--llvm/include/llvm/Support/CommandLine.h29
-rw-r--r--llvm/include/llvm/Support/Compiler.h64
-rw-r--r--llvm/include/llvm/Support/CrashRecoveryContext.h3
-rw-r--r--llvm/include/llvm/Support/DataExtractor.h146
-rw-r--r--llvm/include/llvm/Support/DebugCounter.h7
-rw-r--r--llvm/include/llvm/Support/ELFAttributeParser.h72
-rw-r--r--llvm/include/llvm/Support/ELFAttributes.h37
-rw-r--r--llvm/include/llvm/Support/Endian.h4
-rw-r--r--llvm/include/llvm/Support/Errno.h4
-rw-r--r--llvm/include/llvm/Support/Error.h35
-rw-r--r--llvm/include/llvm/Support/ErrorHandling.h11
-rw-r--r--llvm/include/llvm/Support/ErrorOr.h48
-rw-r--r--llvm/include/llvm/Support/ExtensibleRTTI.h135
-rw-r--r--llvm/include/llvm/Support/FileCheck.h19
-rw-r--r--llvm/include/llvm/Support/FileCollector.h58
-rw-r--r--llvm/include/llvm/Support/FileOutputBuffer.h2
-rw-r--r--llvm/include/llvm/Support/FormatAdapters.h11
-rw-r--r--llvm/include/llvm/Support/FormatProviders.h14
-rw-r--r--llvm/include/llvm/Support/FormatVariadic.h63
-rw-r--r--llvm/include/llvm/Support/FormatVariadicDetails.h34
-rw-r--r--llvm/include/llvm/Support/FormattedStream.h40
-rw-r--r--llvm/include/llvm/Support/GenericDomTree.h66
-rw-r--r--llvm/include/llvm/Support/GenericDomTreeConstruction.h77
-rw-r--r--llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h20
-rw-r--r--llvm/include/llvm/Support/GlobPattern.h4
-rw-r--r--llvm/include/llvm/Support/GraphWriter.h20
-rw-r--r--llvm/include/llvm/Support/Host.h8
-rw-r--r--llvm/include/llvm/Support/ItaniumManglingCanonicalizer.h6
-rw-r--r--llvm/include/llvm/Support/JSON.h29
-rw-r--r--llvm/include/llvm/Support/KnownBits.h93
-rw-r--r--llvm/include/llvm/Support/LEB128.h4
-rw-r--r--llvm/include/llvm/Support/LockFileManager.h4
-rw-r--r--llvm/include/llvm/Support/LowLevelTypeImpl.h28
-rw-r--r--llvm/include/llvm/Support/MD5.h2
-rw-r--r--llvm/include/llvm/Support/MSVCErrorWorkarounds.h9
-rw-r--r--llvm/include/llvm/Support/MachineValueType.h489
-rw-r--r--llvm/include/llvm/Support/ManagedStatic.h10
-rw-r--r--llvm/include/llvm/Support/MathExtras.h77
-rw-r--r--llvm/include/llvm/Support/MemAlloc.h23
-rw-r--r--llvm/include/llvm/Support/MemoryBuffer.h22
-rw-r--r--llvm/include/llvm/Support/NativeFormatting.h3
-rw-r--r--llvm/include/llvm/Support/OptimizedStructLayout.h142
-rw-r--r--llvm/include/llvm/Support/Parallel.h92
-rw-r--r--llvm/include/llvm/Support/Path.h42
-rw-r--r--llvm/include/llvm/Support/PointerLikeTypeTraits.h21
-rw-r--r--llvm/include/llvm/Support/PrettyStackTrace.h7
-rw-r--r--llvm/include/llvm/Support/Process.h13
-rw-r--r--llvm/include/llvm/Support/Program.h28
-rw-r--r--llvm/include/llvm/Support/RISCVAttributeParser.h37
-rw-r--r--llvm/include/llvm/Support/RISCVAttributes.h44
-rw-r--r--llvm/include/llvm/Support/Regex.h16
-rw-r--r--llvm/include/llvm/Support/SHA1.h9
-rw-r--r--llvm/include/llvm/Support/ScaledNumber.h4
-rw-r--r--llvm/include/llvm/Support/SmallVectorMemoryBuffer.h2
-rw-r--r--llvm/include/llvm/Support/SourceMgr.h98
-rw-r--r--llvm/include/llvm/Support/SpecialCaseList.h20
-rw-r--r--llvm/include/llvm/Support/StringPool.h139
-rw-r--r--llvm/include/llvm/Support/SuffixTree.h350
-rw-r--r--llvm/include/llvm/Support/SwapByteOrder.h81
-rw-r--r--llvm/include/llvm/Support/SystemUtils.h7
-rw-r--r--llvm/include/llvm/Support/TargetOpcodes.def41
-rw-r--r--llvm/include/llvm/Support/TargetParser.h53
-rw-r--r--llvm/include/llvm/Support/TaskQueue.h6
-rw-r--r--llvm/include/llvm/Support/ThreadPool.h25
-rw-r--r--llvm/include/llvm/Support/Threading.h98
-rw-r--r--llvm/include/llvm/Support/TimeProfiler.h26
-rw-r--r--llvm/include/llvm/Support/Timer.h5
-rw-r--r--llvm/include/llvm/Support/ToolOutputFile.h11
-rw-r--r--llvm/include/llvm/Support/TrailingObjects.h8
-rw-r--r--llvm/include/llvm/Support/TrigramIndex.h1
-rw-r--r--llvm/include/llvm/Support/TypeSize.h70
-rw-r--r--llvm/include/llvm/Support/VersionTuple.h9
-rw-r--r--llvm/include/llvm/Support/VirtualFileSystem.h23
-rw-r--r--llvm/include/llvm/Support/Windows/WindowsSupport.h249
-rw-r--r--llvm/include/llvm/Support/WithColor.h48
-rw-r--r--llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h5
-rw-r--r--llvm/include/llvm/Support/X86TargetParser.def281
-rw-r--r--llvm/include/llvm/Support/X86TargetParser.h148
-rw-r--r--llvm/include/llvm/Support/YAMLParser.h2
-rw-r--r--llvm/include/llvm/Support/YAMLTraits.h127
-rw-r--r--llvm/include/llvm/Support/circular_raw_ostream.h4
-rw-r--r--llvm/include/llvm/Support/raw_ostream.h93
-rw-r--r--llvm/include/llvm/Support/type_traits.h13
105 files changed, 3806 insertions, 1767 deletions
diff --git a/llvm/include/llvm/Support/AArch64TargetParser.def b/llvm/include/llvm/Support/AArch64TargetParser.def
index 6b25ef2ca435f..13b7cfc4b5cd9 100644
--- a/llvm/include/llvm/Support/AArch64TargetParser.def
+++ b/llvm/include/llvm/Support/AArch64TargetParser.def
@@ -44,6 +44,13 @@ AARCH64_ARCH("armv8.5-a", ARMV8_5A, "8.5-A", "v8.5a",
(AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD))
+AARCH64_ARCH("armv8.6-a", ARMV8_6A, "8.6-A", "v8.6a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
+ AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
+ AArch64::AEK_SM4 | AArch64::AEK_SHA3 | AArch64::AEK_BF16 |
+ AArch64::AEK_SHA2 | AArch64::AEK_AES | AArch64::AEK_I8MM))
#undef AARCH64_ARCH
#ifndef AARCH64_ARCH_EXT_NAME
@@ -79,12 +86,18 @@ AARCH64_ARCH_EXT_NAME("memtag", AArch64::AEK_MTE, "+mte", "-mte"
AARCH64_ARCH_EXT_NAME("ssbs", AArch64::AEK_SSBS, "+ssbs", "-ssbs")
AARCH64_ARCH_EXT_NAME("sb", AArch64::AEK_SB, "+sb", "-sb")
AARCH64_ARCH_EXT_NAME("predres", AArch64::AEK_PREDRES, "+predres", "-predres")
+AARCH64_ARCH_EXT_NAME("bf16", AArch64::AEK_BF16, "+bf16", "-bf16")
+AARCH64_ARCH_EXT_NAME("i8mm", AArch64::AEK_I8MM, "+i8mm", "-i8mm")
+AARCH64_ARCH_EXT_NAME("f32mm", AArch64::AEK_F32MM, "+f32mm", "-f32mm")
+AARCH64_ARCH_EXT_NAME("f64mm", AArch64::AEK_F64MM, "+f64mm", "-f64mm")
AARCH64_ARCH_EXT_NAME("tme", AArch64::AEK_TME, "+tme", "-tme")
#undef AARCH64_ARCH_EXT_NAME
#ifndef AARCH64_CPU_NAME
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)
#endif
+AARCH64_CPU_NAME("cortex-a34", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("cortex-a35", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_CRC))
AARCH64_CPU_NAME("cortex-a53", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true,
@@ -111,6 +124,15 @@ AARCH64_CPU_NAME("cortex-a76", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
AARCH64_CPU_NAME("cortex-a76ae", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("cortex-a77", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16 | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
+ AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("cortex-a78", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
+ AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("cortex-x1", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
+ AArch64::AEK_SSBS))
AARCH64_CPU_NAME("neoverse-e1", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_RAS |
AArch64::AEK_RCPC | AArch64::AEK_SSBS))
@@ -152,6 +174,10 @@ 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("thunderx3t110", ARMV8_3A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC | AEK_CRYPTO | AEK_FP | AEK_SIMD |
+ AEK_LSE | AEK_RAND | AArch64::AEK_PROFILE |
+ AArch64::AEK_RAS))
AARCH64_CPU_NAME("thunderx", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_CRC | AArch64::AEK_PROFILE))
AARCH64_CPU_NAME("thunderxt88", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
@@ -164,6 +190,10 @@ AARCH64_CPU_NAME("tsv110", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_DOTPROD |
AArch64::AEK_FP16 | AArch64::AEK_FP16FML |
AArch64::AEK_PROFILE))
+AARCH64_CPU_NAME("a64fx", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16 | AArch64::AEK_SVE))
+AARCH64_CPU_NAME("carmel", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ AArch64::AEK_FP16)
// Invalid CPU
AARCH64_CPU_NAME("invalid", INVALID, FK_INVALID, true, AArch64::AEK_INVALID)
#undef AARCH64_CPU_NAME
diff --git a/llvm/include/llvm/Support/AArch64TargetParser.h b/llvm/include/llvm/Support/AArch64TargetParser.h
index fbe08945a038e..b045e31bc92aa 100644
--- a/llvm/include/llvm/Support/AArch64TargetParser.h
+++ b/llvm/include/llvm/Support/AArch64TargetParser.h
@@ -14,17 +14,20 @@
#ifndef LLVM_SUPPORT_AARCH64TARGETPARSERCOMMON_H
#define LLVM_SUPPORT_AARCH64TARGETPARSERCOMMON_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Support/ARMTargetParser.h"
#include <vector>
// FIXME:This should be made into class design,to avoid dupplication.
namespace llvm {
+
+class Triple;
+
namespace AArch64 {
// Arch extension modifiers for CPUs.
-enum ArchExtKind : unsigned {
+enum ArchExtKind : uint64_t {
AEK_INVALID = 0,
AEK_NONE = 1,
AEK_CRC = 1 << 1,
@@ -55,6 +58,10 @@ enum ArchExtKind : unsigned {
AEK_SVE2SHA3 = 1 << 26,
AEK_SVE2BITPERM = 1 << 27,
AEK_TME = 1 << 28,
+ AEK_BF16 = 1 << 29,
+ AEK_I8MM = 1 << 30,
+ AEK_F32MM = 1ULL << 31,
+ AEK_F64MM = 1ULL << 32,
};
enum class ArchKind {
diff --git a/llvm/include/llvm/Support/AMDGPUMetadata.h b/llvm/include/llvm/Support/AMDGPUMetadata.h
index eeef4e699c3e0..920c97f7e112c 100644
--- a/llvm/include/llvm/Support/AMDGPUMetadata.h
+++ b/llvm/include/llvm/Support/AMDGPUMetadata.h
@@ -79,7 +79,8 @@ enum class ValueKind : uint8_t {
Unknown = 0xff
};
-/// Value types.
+/// Value types. This is deprecated and only remains for compatibility parsing
+/// of old metadata.
enum class ValueType : uint8_t {
Struct = 0,
I8 = 1,
@@ -164,7 +165,7 @@ constexpr char Offset[] = "Offset";
constexpr char Align[] = "Align";
/// Key for Kernel::Arg::Metadata::mValueKind.
constexpr char ValueKind[] = "ValueKind";
-/// Key for Kernel::Arg::Metadata::mValueType.
+/// Key for Kernel::Arg::Metadata::mValueType. (deprecated)
constexpr char ValueType[] = "ValueType";
/// Key for Kernel::Arg::Metadata::mPointeeAlign.
constexpr char PointeeAlign[] = "PointeeAlign";
@@ -198,8 +199,6 @@ struct Metadata final {
uint32_t mAlign = 0;
/// Value kind. Required.
ValueKind mValueKind = ValueKind::Unknown;
- /// Value type. Required.
- ValueType mValueType = ValueType::Unknown;
/// Pointee alignment in bytes. Optional.
uint32_t mPointeeAlign = 0;
/// Address space qualifier. Optional.
diff --git a/llvm/include/llvm/Support/ARMAttributeParser.h b/llvm/include/llvm/Support/ARMAttributeParser.h
index f6c39abb4f211..bf85ea14cfe33 100644
--- a/llvm/include/llvm/Support/ARMAttributeParser.h
+++ b/llvm/include/llvm/Support/ARMAttributeParser.h
@@ -1,4 +1,4 @@
-//===--- ARMAttributeParser.h - ARM Attribute Information Printer ---------===//
+//===- ARMAttributeParser.h - ARM Attribute Information Printer -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -10,132 +10,71 @@
#define LLVM_SUPPORT_ARMATTRIBUTEPARSER_H
#include "ARMBuildAttributes.h"
+#include "ELFAttributeParser.h"
#include "ScopedPrinter.h"
-
-#include <map>
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
namespace llvm {
class StringRef;
-class ARMAttributeParser {
- ScopedPrinter *SW;
-
- std::map<unsigned, unsigned> Attributes;
-
+class ARMAttributeParser : public ELFAttributeParser {
struct DisplayHandler {
- ARMBuildAttrs::AttrType Attribute;
- void (ARMAttributeParser::*Routine)(ARMBuildAttrs::AttrType,
- const uint8_t *, uint32_t &);
+ ARMBuildAttrs::AttrType attribute;
+ Error (ARMAttributeParser::*routine)(ARMBuildAttrs::AttrType);
};
- static const DisplayHandler DisplayRoutines[];
-
- 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);
+ static const DisplayHandler displayRoutines[];
+
+ Error handler(uint64_t tag, bool &handled) override;
+
+ Error stringAttribute(ARMBuildAttrs::AttrType tag);
+
+ Error CPU_arch(ARMBuildAttrs::AttrType tag);
+ Error CPU_arch_profile(ARMBuildAttrs::AttrType tag);
+ Error ARM_ISA_use(ARMBuildAttrs::AttrType tag);
+ Error THUMB_ISA_use(ARMBuildAttrs::AttrType tag);
+ Error FP_arch(ARMBuildAttrs::AttrType tag);
+ Error WMMX_arch(ARMBuildAttrs::AttrType tag);
+ Error Advanced_SIMD_arch(ARMBuildAttrs::AttrType tag);
+ Error MVE_arch(ARMBuildAttrs::AttrType tag);
+ Error PCS_config(ARMBuildAttrs::AttrType tag);
+ Error ABI_PCS_R9_use(ARMBuildAttrs::AttrType tag);
+ Error ABI_PCS_RW_data(ARMBuildAttrs::AttrType tag);
+ Error ABI_PCS_RO_data(ARMBuildAttrs::AttrType tag);
+ Error ABI_PCS_GOT_use(ARMBuildAttrs::AttrType tag);
+ Error ABI_PCS_wchar_t(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_rounding(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_denormal(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_exceptions(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_user_exceptions(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_number_model(ARMBuildAttrs::AttrType tag);
+ Error ABI_align_needed(ARMBuildAttrs::AttrType tag);
+ Error ABI_align_preserved(ARMBuildAttrs::AttrType tag);
+ Error ABI_enum_size(ARMBuildAttrs::AttrType tag);
+ Error ABI_HardFP_use(ARMBuildAttrs::AttrType tag);
+ Error ABI_VFP_args(ARMBuildAttrs::AttrType tag);
+ Error ABI_WMMX_args(ARMBuildAttrs::AttrType tag);
+ Error ABI_optimization_goals(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_optimization_goals(ARMBuildAttrs::AttrType tag);
+ Error compatibility(ARMBuildAttrs::AttrType tag);
+ Error CPU_unaligned_access(ARMBuildAttrs::AttrType tag);
+ Error FP_HP_extension(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_16bit_format(ARMBuildAttrs::AttrType tag);
+ Error MPextension_use(ARMBuildAttrs::AttrType tag);
+ Error DIV_use(ARMBuildAttrs::AttrType tag);
+ Error DSP_extension(ARMBuildAttrs::AttrType tag);
+ Error T2EE_use(ARMBuildAttrs::AttrType tag);
+ Error Virtualization_use(ARMBuildAttrs::AttrType tag);
+ Error nodefaults(ARMBuildAttrs::AttrType tag);
- void ParseAttributeList(const uint8_t *Data, uint32_t &Offset,
- uint32_t Length);
- void ParseIndexList(const uint8_t *Data, uint32_t &Offset,
- SmallVectorImpl<uint8_t> &IndexList);
- void ParseSubsection(const uint8_t *Data, uint32_t Length);
public:
- ARMAttributeParser(ScopedPrinter *SW) : SW(SW) {}
-
- ARMAttributeParser() : SW(nullptr) { }
-
- void Parse(ArrayRef<uint8_t> Section, bool isLittle);
-
- bool hasAttribute(unsigned Tag) const {
- return Attributes.count(Tag);
- }
-
- unsigned getAttributeValue(unsigned Tag) const {
- return Attributes.find(Tag)->second;
- }
+ ARMAttributeParser(ScopedPrinter *sw)
+ : ELFAttributeParser(sw, ARMBuildAttrs::ARMAttributeTags, "aeabi") {}
+ ARMAttributeParser()
+ : ELFAttributeParser(ARMBuildAttrs::ARMAttributeTags, "aeabi") {}
};
-
}
#endif
-
diff --git a/llvm/include/llvm/Support/ARMBuildAttributes.h b/llvm/include/llvm/Support/ARMBuildAttributes.h
index 90481eaa1677c..5a06fd6ca7be7 100644
--- a/llvm/include/llvm/Support/ARMBuildAttributes.h
+++ b/llvm/include/llvm/Support/ARMBuildAttributes.h
@@ -18,77 +18,70 @@
#ifndef LLVM_SUPPORT_ARMBUILDATTRIBUTES_H
#define LLVM_SUPPORT_ARMBUILDATTRIBUTES_H
-namespace llvm {
-class StringRef;
+#include "llvm/Support/ELFAttributes.h"
+namespace llvm {
namespace ARMBuildAttrs {
+extern const TagNameMap ARMAttributeTags;
+
enum SpecialAttr {
// This is for the .cpu asm attr. It translates into one or more
// AttrType (below) entries in the .ARM.attributes section in the ELF.
SEL_CPU
};
-enum AttrType {
+enum AttrType : unsigned {
// Rest correspond to ELF/.ARM.attributes
- File = 1,
- CPU_raw_name = 4,
- CPU_name = 5,
- CPU_arch = 6,
- CPU_arch_profile = 7,
- ARM_ISA_use = 8,
- THUMB_ISA_use = 9,
- FP_arch = 10,
- WMMX_arch = 11,
- Advanced_SIMD_arch = 12,
- PCS_config = 13,
- ABI_PCS_R9_use = 14,
- ABI_PCS_RW_data = 15,
- ABI_PCS_RO_data = 16,
- ABI_PCS_GOT_use = 17,
- ABI_PCS_wchar_t = 18,
- ABI_FP_rounding = 19,
- ABI_FP_denormal = 20,
- ABI_FP_exceptions = 21,
- ABI_FP_user_exceptions = 22,
- ABI_FP_number_model = 23,
- ABI_align_needed = 24,
- ABI_align_preserved = 25,
- ABI_enum_size = 26,
- ABI_HardFP_use = 27,
- ABI_VFP_args = 28,
- ABI_WMMX_args = 29,
- ABI_optimization_goals = 30,
+ File = 1,
+ CPU_raw_name = 4,
+ CPU_name = 5,
+ CPU_arch = 6,
+ CPU_arch_profile = 7,
+ ARM_ISA_use = 8,
+ THUMB_ISA_use = 9,
+ FP_arch = 10,
+ WMMX_arch = 11,
+ Advanced_SIMD_arch = 12,
+ PCS_config = 13,
+ ABI_PCS_R9_use = 14,
+ ABI_PCS_RW_data = 15,
+ ABI_PCS_RO_data = 16,
+ ABI_PCS_GOT_use = 17,
+ ABI_PCS_wchar_t = 18,
+ ABI_FP_rounding = 19,
+ ABI_FP_denormal = 20,
+ ABI_FP_exceptions = 21,
+ ABI_FP_user_exceptions = 22,
+ ABI_FP_number_model = 23,
+ ABI_align_needed = 24,
+ ABI_align_preserved = 25,
+ ABI_enum_size = 26,
+ ABI_HardFP_use = 27,
+ ABI_VFP_args = 28,
+ ABI_WMMX_args = 29,
+ ABI_optimization_goals = 30,
ABI_FP_optimization_goals = 31,
- compatibility = 32,
- CPU_unaligned_access = 34,
- FP_HP_extension = 36,
- ABI_FP_16bit_format = 38,
- MPextension_use = 42, // recoded from 70 (ABI r2.08)
- DIV_use = 44,
- DSP_extension = 46,
- MVE_arch = 48,
- also_compatible_with = 65,
- conformance = 67,
- Virtualization_use = 68,
+ compatibility = 32,
+ CPU_unaligned_access = 34,
+ FP_HP_extension = 36,
+ ABI_FP_16bit_format = 38,
+ MPextension_use = 42, // recoded from 70 (ABI r2.08)
+ DIV_use = 44,
+ DSP_extension = 46,
+ MVE_arch = 48,
+ also_compatible_with = 65,
+ conformance = 67,
+ Virtualization_use = 68,
/// Legacy Tags
- Section = 2, // deprecated (ABI r2.09)
- Symbol = 3, // deprecated (ABI r2.09)
- ABI_align8_needed = 24, // renamed to ABI_align_needed (ABI r2.09)
- ABI_align8_preserved = 25, // renamed to ABI_align_preserved (ABI r2.09)
- nodefaults = 64, // deprecated (ABI r2.09)
- T2EE_use = 66, // deprecated (ABI r2.09)
- MPextension_use_old = 70 // recoded to MPextension_use (ABI r2.08)
-};
-
-StringRef AttrTypeAsString(unsigned Attr, bool HasTagPrefix = true);
-StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix = true);
-int AttrTypeFromString(StringRef Tag);
-
-// Magic numbers for .ARM.attributes
-enum AttrMagic {
- Format_Version = 0x41
+ Section = 2, // deprecated (ABI r2.09)
+ Symbol = 3, // deprecated (ABI r2.09)
+ ABI_align8_needed = 24, // renamed to ABI_align_needed (ABI r2.09)
+ ABI_align8_preserved = 25, // renamed to ABI_align_preserved (ABI r2.09)
+ nodefaults = 64, // deprecated (ABI r2.09)
+ T2EE_use = 66, // deprecated (ABI r2.09)
+ MPextension_use_old = 70 // recoded to MPextension_use (ABI r2.08)
};
// Legal Values for CPU_arch, (=6), uleb128
diff --git a/llvm/include/llvm/Support/ARMTargetParser.def b/llvm/include/llvm/Support/ARMTargetParser.def
index 7f03d9a1320af..9f51c841e4296 100644
--- a/llvm/include/llvm/Support/ARMTargetParser.def
+++ b/llvm/include/llvm/Support/ARMTargetParser.def
@@ -112,6 +112,12 @@ ARM_ARCH("armv8.5-a", ARMV8_5A, "8.5-A", "v8.5a",
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS |
ARM::AEK_DOTPROD))
+ARM_ARCH("armv8.6-a", ARMV8_6A, "8.6-A", "v8.6a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS |
+ ARM::AEK_DOTPROD | ARM::AEK_BF16 | ARM::AEK_SHA2 | ARM::AEK_AES |
+ ARM::AEK_I8MM))
ARM_ARCH("armv8-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 |
@@ -164,8 +170,18 @@ 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("bf16", ARM::AEK_BF16, "+bf16", "-bf16")
ARM_ARCH_EXT_NAME("sb", ARM::AEK_SB, "+sb", "-sb")
+ARM_ARCH_EXT_NAME("i8mm", ARM::AEK_I8MM, "+i8mm", "-i8mm")
ARM_ARCH_EXT_NAME("lob", ARM::AEK_LOB, "+lob", "-lob")
+ARM_ARCH_EXT_NAME("cdecp0", ARM::AEK_CDECP0, "+cdecp0", "-cdecp0")
+ARM_ARCH_EXT_NAME("cdecp1", ARM::AEK_CDECP1, "+cdecp1", "-cdecp1")
+ARM_ARCH_EXT_NAME("cdecp2", ARM::AEK_CDECP2, "+cdecp2", "-cdecp2")
+ARM_ARCH_EXT_NAME("cdecp3", ARM::AEK_CDECP3, "+cdecp3", "-cdecp3")
+ARM_ARCH_EXT_NAME("cdecp4", ARM::AEK_CDECP4, "+cdecp4", "-cdecp4")
+ARM_ARCH_EXT_NAME("cdecp5", ARM::AEK_CDECP5, "+cdecp5", "-cdecp5")
+ARM_ARCH_EXT_NAME("cdecp6", ARM::AEK_CDECP6, "+cdecp6", "-cdecp6")
+ARM_ARCH_EXT_NAME("cdecp7", ARM::AEK_CDECP7, "+cdecp7", "-cdecp7")
#undef ARM_ARCH_EXT_NAME
#ifndef ARM_HW_DIV_NAME
@@ -260,6 +276,8 @@ 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-m55", ARMV8_1MMainline, FK_FP_ARMV8_FULLFP16_D16, false,
+ (ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP | ARM::AEK_FP16))
ARM_CPU_NAME("cortex-a32", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a35", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a53", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
@@ -274,6 +292,12 @@ 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("cortex-a77", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_FP16 | ARM::AEK_DOTPROD))
+ARM_CPU_NAME("cortex-a78",ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_FP16 | ARM::AEK_DOTPROD))
+ARM_CPU_NAME("cortex-x1", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_FP16 | ARM::AEK_DOTPROD))
ARM_CPU_NAME("neoverse-n1", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(ARM::AEK_FP16 | ARM::AEK_DOTPROD))
ARM_CPU_NAME("cyclone", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
diff --git a/llvm/include/llvm/Support/ARMTargetParser.h b/llvm/include/llvm/Support/ARMTargetParser.h
index 02d4c975129fb..4e76b3c4b83e0 100644
--- a/llvm/include/llvm/Support/ARMTargetParser.h
+++ b/llvm/include/llvm/Support/ARMTargetParser.h
@@ -14,17 +14,20 @@
#ifndef LLVM_SUPPORT_ARMTARGETPARSER_H
#define LLVM_SUPPORT_ARMTARGETPARSER_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include <vector>
namespace llvm {
+
+class Triple;
+
namespace ARM {
// Arch extension modifiers for CPUs.
// Note that this is not the same as the AArch64 list
-enum ArchExtKind : unsigned {
+enum ArchExtKind : uint64_t {
AEK_INVALID = 0,
AEK_NONE = 1,
AEK_CRC = 1 << 1,
@@ -46,12 +49,23 @@ enum ArchExtKind : unsigned {
AEK_SB = 1 << 17,
AEK_FP_DP = 1 << 18,
AEK_LOB = 1 << 19,
+ AEK_BF16 = 1 << 20,
+ AEK_I8MM = 1 << 21,
+ AEK_CDECP0 = 1 << 22,
+ AEK_CDECP1 = 1 << 23,
+ AEK_CDECP2 = 1 << 24,
+ AEK_CDECP3 = 1 << 25,
+ AEK_CDECP4 = 1 << 26,
+ AEK_CDECP5 = 1 << 27,
+ AEK_CDECP6 = 1 << 28,
+ AEK_CDECP7 = 1 << 29,
+
// Unsupported extensions.
- AEK_OS = 0x8000000,
- AEK_IWMMXT = 0x10000000,
- AEK_IWMMXT2 = 0x20000000,
- AEK_MAVERICK = 0x40000000,
- AEK_XSCALE = 0x80000000,
+ AEK_OS = 1ULL << 59,
+ AEK_IWMMXT = 1ULL << 60,
+ AEK_IWMMXT2 = 1ULL << 61,
+ AEK_MAVERICK = 1ULL << 62,
+ AEK_XSCALE = 1ULL << 63,
};
// List of Arch Extension names.
@@ -59,7 +73,7 @@ enum ArchExtKind : unsigned {
struct ExtName {
const char *NameCStr;
size_t NameLength;
- unsigned ID;
+ uint64_t ID;
const char *Feature;
const char *NegFeature;
@@ -78,7 +92,7 @@ const ExtName ARCHExtNames[] = {
const struct {
const char *NameCStr;
size_t NameLength;
- unsigned ID;
+ uint64_t ID;
StringRef getName() const { return StringRef(NameCStr, NameLength); }
} HWDivNames[] = {
@@ -102,7 +116,7 @@ template <typename T> struct CpuNames {
size_t NameLength;
T ArchID;
bool Default; // is $Name the default CPU for $ArchID ?
- unsigned DefaultExtensions;
+ uint64_t DefaultExtensions;
StringRef getName() const { return StringRef(NameCStr, NameLength); }
};
@@ -193,7 +207,7 @@ template <typename T> struct ArchNames {
const char *SubArchCStr;
size_t SubArchLength;
unsigned DefaultFPU;
- unsigned ArchBaseExtensions;
+ uint64_t ArchBaseExtensions;
T ID;
ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
@@ -225,33 +239,33 @@ 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,
+bool getHWDivFeatures(uint64_t HWDivKind, std::vector<StringRef> &Features);
+bool getExtensionFeatures(uint64_t Extensions,
std::vector<StringRef> &Features);
StringRef getArchName(ArchKind AK);
unsigned getArchAttr(ArchKind AK);
StringRef getCPUAttr(ArchKind AK);
StringRef getSubArch(ArchKind AK);
-StringRef getArchExtName(unsigned ArchExtKind);
+StringRef getArchExtName(uint64_t ArchExtKind);
StringRef getArchExtFeature(StringRef ArchExt);
bool appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK, StringRef ArchExt,
std::vector<StringRef> &Features);
-StringRef getHWDivName(unsigned HWDivKind);
+StringRef getHWDivName(uint64_t HWDivKind);
// Information by Name
unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
-unsigned getDefaultExtensions(StringRef CPU, ArchKind AK);
+uint64_t getDefaultExtensions(StringRef CPU, ArchKind AK);
StringRef getDefaultCPU(StringRef Arch);
StringRef getCanonicalArchName(StringRef Arch);
StringRef getFPUSynonym(StringRef FPU);
StringRef getArchSynonym(StringRef Arch);
// Parser
-unsigned parseHWDiv(StringRef HWDiv);
+uint64_t parseHWDiv(StringRef HWDiv);
unsigned parseFPU(StringRef FPU);
ArchKind parseArch(StringRef Arch);
-unsigned parseArchExt(StringRef ArchExt);
+uint64_t parseArchExt(StringRef ArchExt);
ArchKind parseCPUArch(StringRef CPU);
ISAKind parseArchISA(StringRef Arch);
EndianKind parseArchEndian(StringRef Arch);
diff --git a/llvm/include/llvm/Support/Alignment.h b/llvm/include/llvm/Support/Alignment.h
index 72fad87dd0d4d..667434e8a407f 100644
--- a/llvm/include/llvm/Support/Alignment.h
+++ b/llvm/include/llvm/Support/Alignment.h
@@ -22,17 +22,16 @@
#define LLVM_SUPPORT_ALIGNMENT_H_
#include "llvm/ADT/Optional.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
-#include <limits>
+#ifndef NDEBUG
+#include <string>
+#endif // NDEBUG
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.
@@ -86,11 +85,14 @@ public:
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(); }
+ /// It was decided to deprecate Align::None because it's too close to
+ /// llvm::None which can be used to initialize `MaybeAlign`.
+ /// MaybeAlign = llvm::None means unspecified alignment,
+ /// Align = Align::None() means alignment of one byte.
+ LLVM_ATTRIBUTE_DEPRECATED(constexpr static const Align None(),
+ "Use Align() or Align(1) instead") {
+ return Align();
+ }
/// Allow constructions of constexpr Align.
template <size_t kValue> constexpr static LogValue Constant() {
@@ -147,13 +149,6 @@ 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));
@@ -161,17 +156,34 @@ inline bool isAddrAligned(Align Lhs, const void *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`.
+ 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
+ // 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);
+ return (Size + Value - 1) & ~(Value - 1U);
+}
+
+/// If non-zero \p Skew is specified, the return value will be a minimal integer
+/// that is greater than or equal to \p Size and equal to \p A * N + \p Skew for
+/// some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p
+/// Skew mod \p A'.
+///
+/// Examples:
+/// \code
+/// alignTo(5, Align(8), 7) = 7
+/// alignTo(17, Align(8), 1) = 17
+/// alignTo(~0LL, Align(8), 3) = 3
+/// \endcode
+inline uint64_t alignTo(uint64_t Size, Align A, uint64_t Skew) {
+ const uint64_t Value = A.value();
+ Skew %= Value;
+ return ((Size + Value - 1 - Skew) & ~(Value - 1U)) + Skew;
}
/// Returns a multiple of A needed to store `Size` bytes.
@@ -184,7 +196,8 @@ inline uint64_t alignTo(uint64_t Size, MaybeAlign A) {
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");
+ ArithAddr &&
+ "Overflow");
return alignTo(ArithAddr, Alignment);
}
@@ -203,13 +216,6 @@ inline uint64_t offsetToAlignedAddr(const void *Addr, Align 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); }
@@ -281,26 +287,6 @@ inline bool operator==(MaybeAlign Lhs, uint64_t Rhs) {
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) {
@@ -322,56 +308,30 @@ 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();
-}
+// Don't allow relational comparisons with MaybeAlign.
+bool operator<=(Align Lhs, MaybeAlign Rhs) = delete;
+bool operator>=(Align Lhs, MaybeAlign Rhs) = delete;
+bool operator<(Align Lhs, MaybeAlign Rhs) = delete;
+bool operator>(Align Lhs, MaybeAlign Rhs) = delete;
-/// 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();
+bool operator<=(MaybeAlign Lhs, Align Rhs) = delete;
+bool operator>=(MaybeAlign Lhs, Align Rhs) = delete;
+bool operator<(MaybeAlign Lhs, Align Rhs) = delete;
+bool operator>(MaybeAlign Lhs, Align Rhs) = delete;
+
+bool operator<=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
+bool operator>=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
+bool operator<(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
+bool operator>(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
+
+inline Align operator*(Align Lhs, uint64_t Rhs) {
+ assert(Rhs > 0 && "Rhs must be positive");
+ return Align(Lhs.value() * Rhs);
}
-inline bool operator>(MaybeAlign Lhs, Align Rhs) {
- ALIGN_CHECK_ISSET(Lhs);
- return Lhs && (*Lhs).value() > Rhs.value();
+
+inline MaybeAlign operator*(MaybeAlign Lhs, uint64_t Rhs) {
+ assert(Rhs > 0 && "Rhs must be positive");
+ return Lhs ? Lhs.getValue() * Rhs : MaybeAlign();
}
inline Align operator/(Align Lhs, uint64_t Divisor) {
@@ -395,8 +355,20 @@ inline Align max(Align Lhs, MaybeAlign Rhs) {
return Rhs && *Rhs > Lhs ? *Rhs : Lhs;
}
+#ifndef NDEBUG
+// For usage in LLVM_DEBUG macros.
+inline std::string DebugStr(const Align &A) {
+ return std::to_string(A.value());
+}
+// For usage in LLVM_DEBUG macros.
+inline std::string DebugStr(const MaybeAlign &MA) {
+ if (MA)
+ return std::to_string(MA->value());
+ return "None";
+}
+#endif // NDEBUG
+
#undef ALIGN_CHECK_ISPOSITIVE
-#undef ALIGN_CHECK_ISSET
} // namespace llvm
diff --git a/llvm/include/llvm/Support/Allocator.h b/llvm/include/llvm/Support/Allocator.h
index 670335ffecbcb..40c967ccc4857 100644
--- a/llvm/include/llvm/Support/Allocator.h
+++ b/llvm/include/llvm/Support/Allocator.h
@@ -7,13 +7,10 @@
//===----------------------------------------------------------------------===//
/// \file
///
-/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both
-/// of these conform to an LLVM "Allocator" concept which consists of an
-/// Allocate method accepting a size and alignment, and a Deallocate accepting
-/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of
-/// Allocate and Deallocate for setting size and alignment based on the final
-/// type. These overloads are typically provided by a base class template \c
-/// AllocatorBase.
+/// This file defines the BumpPtrAllocator interface. BumpPtrAllocator conforms
+/// to the LLVM "Allocator" concept and is similar to MallocAllocator, but
+/// objects cannot be deallocated. Their lifetime is tied to the lifetime of the
+/// allocator.
///
//===----------------------------------------------------------------------===//
@@ -23,6 +20,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Alignment.h"
+#include "llvm/Support/AllocatorBase.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -38,81 +36,6 @@
namespace llvm {
-/// CRTP base class providing obvious overloads for the core \c
-/// Allocate() methods of LLVM-style allocators.
-///
-/// This base class both documents the full public interface exposed by all
-/// LLVM-style allocators, and redirects all of the overloads to a single core
-/// set of methods which the derived class must define.
-template <typename DerivedT> class AllocatorBase {
-public:
- /// Allocate \a Size bytes of \a Alignment aligned memory. This method
- /// must be implemented by \c DerivedT.
- void *Allocate(size_t Size, size_t Alignment) {
-#ifdef __clang__
- static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>(
- &AllocatorBase::Allocate) !=
- static_cast<void *(DerivedT::*)(size_t, size_t)>(
- &DerivedT::Allocate),
- "Class derives from AllocatorBase without implementing the "
- "core Allocate(size_t, size_t) overload!");
-#endif
- return static_cast<DerivedT *>(this)->Allocate(Size, Alignment);
- }
-
- /// Deallocate \a Ptr to \a Size bytes of memory allocated by this
- /// allocator.
- void Deallocate(const void *Ptr, size_t Size) {
-#ifdef __clang__
- static_assert(static_cast<void (AllocatorBase::*)(const void *, size_t)>(
- &AllocatorBase::Deallocate) !=
- static_cast<void (DerivedT::*)(const void *, size_t)>(
- &DerivedT::Deallocate),
- "Class derives from AllocatorBase without implementing the "
- "core Deallocate(void *) overload!");
-#endif
- return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size);
- }
-
- // The rest of these methods are helpers that redirect to one of the above
- // core methods.
-
- /// Allocate space for a sequence of objects without constructing them.
- template <typename T> T *Allocate(size_t Num = 1) {
- return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
- }
-
- /// Deallocate space for a sequence of objects without constructing them.
- template <typename T>
- typename std::enable_if<
- !std::is_same<typename std::remove_cv<T>::type, void>::value, void>::type
- Deallocate(T *Ptr, size_t Num = 1) {
- Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T));
- }
-};
-
-class MallocAllocator : public AllocatorBase<MallocAllocator> {
-public:
- void Reset() {}
-
- LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
- size_t /*Alignment*/) {
- return safe_malloc(Size);
- }
-
- // Pull in base class overloads.
- using AllocatorBase<MallocAllocator>::Allocate;
-
- void Deallocate(const void *Ptr, size_t /*Size*/) {
- free(const_cast<void *>(Ptr));
- }
-
- // Pull in base class overloads.
- using AllocatorBase<MallocAllocator>::Deallocate;
-
- void PrintStats() const {}
-};
-
namespace detail {
// We call out to an external function to actually print the message as the
@@ -136,16 +59,22 @@ void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated,
/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator
/// object, which wraps malloc, to allocate memory, but it can be changed to
/// use a custom allocator.
+///
+/// The GrowthDelay specifies after how many allocated slabs the allocator
+/// increases the size of the slabs.
template <typename AllocatorT = MallocAllocator, size_t SlabSize = 4096,
- size_t SizeThreshold = SlabSize>
+ size_t SizeThreshold = SlabSize, size_t GrowthDelay = 128>
class BumpPtrAllocatorImpl
- : public AllocatorBase<
- BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>> {
+ : public AllocatorBase<BumpPtrAllocatorImpl<AllocatorT, SlabSize,
+ SizeThreshold, GrowthDelay>> {
public:
static_assert(SizeThreshold <= SlabSize,
"The SizeThreshold must be at most the SlabSize to ensure "
"that objects larger than a slab go into their own memory "
"allocation.");
+ static_assert(GrowthDelay > 0,
+ "GrowthDelay must be at least 1 which already increases the"
+ "slab size after each allocated slab.");
BumpPtrAllocatorImpl() = default;
@@ -241,7 +170,7 @@ public:
// 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);
+ void *NewSlab = Allocator.Allocate(PaddedSize, alignof(std::max_align_t));
// We own the new slab and don't want anyone reading anyting other than
// pieces returned from this method. So poison the whole slab.
__asan_poison_memory_region(NewSlab, PaddedSize);
@@ -279,7 +208,7 @@ public:
// Bump pointer allocators are expected to never free their storage; and
// clients expect pointers to remain valid for non-dereferencing uses even
// after deallocation.
- void Deallocate(const void *Ptr, size_t Size) {
+ void Deallocate(const void *Ptr, size_t Size, size_t /*Alignment*/) {
__asan_poison_memory_region(Ptr, Size);
}
@@ -391,10 +320,11 @@ private:
static size_t computeSlabSize(unsigned SlabIdx) {
// Scale the actual allocated slab size based on the number of slabs
- // allocated. Every 128 slabs allocated, we double the allocated size to
- // reduce allocation frequency, but saturate at multiplying the slab size by
- // 2^30.
- return SlabSize * ((size_t)1 << std::min<size_t>(30, SlabIdx / 128));
+ // allocated. Every GrowthDelay slabs allocated, we double
+ // the allocated size to reduce allocation frequency, but saturate at
+ // multiplying the slab size by 2^30.
+ return SlabSize *
+ ((size_t)1 << std::min<size_t>(30, SlabIdx / GrowthDelay));
}
/// Allocate a new slab and move the bump pointers over into the new
@@ -402,7 +332,8 @@ private:
void StartNewSlab() {
size_t AllocatedSlabSize = computeSlabSize(Slabs.size());
- void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0);
+ void *NewSlab =
+ Allocator.Allocate(AllocatedSlabSize, alignof(std::max_align_t));
// We own the new slab and don't want anyone reading anything other than
// pieces returned from this method. So poison the whole slab.
__asan_poison_memory_region(NewSlab, AllocatedSlabSize);
@@ -418,7 +349,7 @@ private:
for (; I != E; ++I) {
size_t AllocatedSlabSize =
computeSlabSize(std::distance(Slabs.begin(), I));
- Allocator.Deallocate(*I, AllocatedSlabSize);
+ Allocator.Deallocate(*I, AllocatedSlabSize, alignof(std::max_align_t));
}
}
@@ -427,7 +358,7 @@ private:
for (auto &PtrAndSize : CustomSizedSlabs) {
void *Ptr = PtrAndSize.first;
size_t Size = PtrAndSize.second;
- Allocator.Deallocate(Ptr, Size);
+ Allocator.Deallocate(Ptr, Size, alignof(std::max_align_t));
}
}
@@ -498,26 +429,21 @@ public:
} // end namespace llvm
-template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold>
-void *operator new(size_t Size,
- llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize,
- SizeThreshold> &Allocator) {
- struct S {
- char c;
- union {
- double D;
- long double LD;
- long long L;
- void *P;
- } x;
- };
- return Allocator.Allocate(
- Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x)));
+template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold,
+ size_t GrowthDelay>
+void *
+operator new(size_t Size,
+ llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold,
+ GrowthDelay> &Allocator) {
+ return Allocator.Allocate(Size, std::min((size_t)llvm::NextPowerOf2(Size),
+ alignof(std::max_align_t)));
}
-template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold>
-void operator delete(
- void *, llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold> &) {
+template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold,
+ size_t GrowthDelay>
+void operator delete(void *,
+ llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize,
+ SizeThreshold, GrowthDelay> &) {
}
#endif // LLVM_SUPPORT_ALLOCATOR_H
diff --git a/llvm/include/llvm/Support/AllocatorBase.h b/llvm/include/llvm/Support/AllocatorBase.h
new file mode 100644
index 0000000000000..e5549d111622e
--- /dev/null
+++ b/llvm/include/llvm/Support/AllocatorBase.h
@@ -0,0 +1,103 @@
+//===- AllocatorBase.h - Simple memory allocation abstraction ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines MallocAllocator. MallocAllocator conforms to the LLVM
+/// "Allocator" concept which consists of an Allocate method accepting a size
+/// and alignment, and a Deallocate accepting a pointer and size. Further, the
+/// LLVM "Allocator" concept has overloads of Allocate and Deallocate for
+/// setting size and alignment based on the final type. These overloads are
+/// typically provided by a base class template \c AllocatorBase.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ALLOCATORBASE_H
+#define LLVM_SUPPORT_ALLOCATORBASE_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MemAlloc.h"
+
+namespace llvm {
+
+/// CRTP base class providing obvious overloads for the core \c
+/// Allocate() methods of LLVM-style allocators.
+///
+/// This base class both documents the full public interface exposed by all
+/// LLVM-style allocators, and redirects all of the overloads to a single core
+/// set of methods which the derived class must define.
+template <typename DerivedT> class AllocatorBase {
+public:
+ /// Allocate \a Size bytes of \a Alignment aligned memory. This method
+ /// must be implemented by \c DerivedT.
+ void *Allocate(size_t Size, size_t Alignment) {
+#ifdef __clang__
+ static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>(
+ &AllocatorBase::Allocate) !=
+ static_cast<void *(DerivedT::*)(size_t, size_t)>(
+ &DerivedT::Allocate),
+ "Class derives from AllocatorBase without implementing the "
+ "core Allocate(size_t, size_t) overload!");
+#endif
+ return static_cast<DerivedT *>(this)->Allocate(Size, Alignment);
+ }
+
+ /// Deallocate \a Ptr to \a Size bytes of memory allocated by this
+ /// allocator.
+ void Deallocate(const void *Ptr, size_t Size, size_t Alignment) {
+#ifdef __clang__
+ static_assert(
+ static_cast<void (AllocatorBase::*)(const void *, size_t, size_t)>(
+ &AllocatorBase::Deallocate) !=
+ static_cast<void (DerivedT::*)(const void *, size_t, size_t)>(
+ &DerivedT::Deallocate),
+ "Class derives from AllocatorBase without implementing the "
+ "core Deallocate(void *) overload!");
+#endif
+ return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size, Alignment);
+ }
+
+ // The rest of these methods are helpers that redirect to one of the above
+ // core methods.
+
+ /// Allocate space for a sequence of objects without constructing them.
+ template <typename T> T *Allocate(size_t Num = 1) {
+ return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
+ }
+
+ /// Deallocate space for a sequence of objects without constructing them.
+ template <typename T>
+ std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value, void>
+ Deallocate(T *Ptr, size_t Num = 1) {
+ Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T), alignof(T));
+ }
+};
+
+class MallocAllocator : public AllocatorBase<MallocAllocator> {
+public:
+ void Reset() {}
+
+ LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) {
+ return allocate_buffer(Size, Alignment);
+ }
+
+ // Pull in base class overloads.
+ using AllocatorBase<MallocAllocator>::Allocate;
+
+ void Deallocate(const void *Ptr, size_t Size, size_t Alignment) {
+ deallocate_buffer(const_cast<void *>(Ptr), Size, Alignment);
+ }
+
+ // Pull in base class overloads.
+ using AllocatorBase<MallocAllocator>::Deallocate;
+
+ void PrintStats() const {}
+};
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_ALLOCATORBASE_H
diff --git a/llvm/include/llvm/Support/AtomicOrdering.h b/llvm/include/llvm/Support/AtomicOrdering.h
index 763bc3ea7b282..a8d89955fa2b5 100644
--- a/llvm/include/llvm/Support/AtomicOrdering.h
+++ b/llvm/include/llvm/Support/AtomicOrdering.h
@@ -53,7 +53,7 @@ template <typename Int> inline bool isValidAtomicOrderingCABI(Int I) {
///
/// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst
/// \-->consume-->acquire--/
-enum class AtomicOrdering {
+enum class AtomicOrdering : unsigned {
NotAtomic = 0,
Unordered = 1,
Monotonic = 2, // Equivalent to C++'s relaxed.
@@ -61,7 +61,8 @@ enum class AtomicOrdering {
Acquire = 4,
Release = 5,
AcquireRelease = 6,
- SequentiallyConsistent = 7
+ SequentiallyConsistent = 7,
+ LAST = SequentiallyConsistent
};
bool operator<(AtomicOrdering, AtomicOrdering) = delete;
diff --git a/llvm/include/llvm/Support/Base64.h b/llvm/include/llvm/Support/Base64.h
new file mode 100644
index 0000000000000..62064a35aa344
--- /dev/null
+++ b/llvm/include/llvm/Support/Base64.h
@@ -0,0 +1,56 @@
+//===--- Base64.h - Base64 Encoder/Decoder ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides generic base64 encoder/decoder.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_BASE64_H
+#define LLVM_SUPPORT_BASE64_H
+
+#include <string>
+
+namespace llvm {
+
+template <class InputBytes> std::string encodeBase64(InputBytes const &Bytes) {
+ static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+ std::string Buffer;
+ Buffer.resize(((Bytes.size() + 2) / 3) * 4);
+
+ size_t i = 0, j = 0;
+ for (size_t n = Bytes.size() / 3 * 3; i < n; i += 3, j += 4) {
+ uint32_t x = ((unsigned char)Bytes[i] << 16) |
+ ((unsigned char)Bytes[i + 1] << 8) |
+ (unsigned char)Bytes[i + 2];
+ Buffer[j + 0] = Table[(x >> 18) & 63];
+ Buffer[j + 1] = Table[(x >> 12) & 63];
+ Buffer[j + 2] = Table[(x >> 6) & 63];
+ Buffer[j + 3] = Table[x & 63];
+ }
+ if (i + 1 == Bytes.size()) {
+ uint32_t x = ((unsigned char)Bytes[i] << 16);
+ Buffer[j + 0] = Table[(x >> 18) & 63];
+ Buffer[j + 1] = Table[(x >> 12) & 63];
+ Buffer[j + 2] = '=';
+ Buffer[j + 3] = '=';
+ } else if (i + 2 == Bytes.size()) {
+ uint32_t x =
+ ((unsigned char)Bytes[i] << 16) | ((unsigned char)Bytes[i + 1] << 8);
+ Buffer[j + 0] = Table[(x >> 18) & 63];
+ Buffer[j + 1] = Table[(x >> 12) & 63];
+ Buffer[j + 2] = Table[(x >> 6) & 63];
+ Buffer[j + 3] = '=';
+ }
+ return Buffer;
+}
+
+} // end namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/Support/BinaryStreamArray.h b/llvm/include/llvm/Support/BinaryStreamArray.h
index 1634983d26ce0..3ba65c07cfe20 100644
--- a/llvm/include/llvm/Support/BinaryStreamArray.h
+++ b/llvm/include/llvm/Support/BinaryStreamArray.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Error.h"
#include <cassert>
diff --git a/llvm/include/llvm/Support/BinaryStreamReader.h b/llvm/include/llvm/Support/BinaryStreamReader.h
index b7d61c02667b3..b611707807c0a 100644
--- a/llvm/include/llvm/Support/BinaryStreamReader.h
+++ b/llvm/include/llvm/Support/BinaryStreamReader.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/ConvertUTF.h"
@@ -89,7 +90,7 @@ public:
template <typename T> Error readEnum(T &Dest) {
static_assert(std::is_enum<T>::value,
"Cannot call readEnum with non-enum value!");
- typename std::underlying_type<T>::type N;
+ std::underlying_type_t<T> N;
if (auto EC = readInteger(N))
return EC;
Dest = static_cast<T>(N);
diff --git a/llvm/include/llvm/Support/BinaryStreamWriter.h b/llvm/include/llvm/Support/BinaryStreamWriter.h
index 86d2389d91820..ceba792e6b266 100644
--- a/llvm/include/llvm/Support/BinaryStreamWriter.h
+++ b/llvm/include/llvm/Support/BinaryStreamWriter.h
@@ -75,7 +75,7 @@ public:
static_assert(std::is_enum<T>::value,
"Cannot call writeEnum with non-Enum type");
- using U = typename std::underlying_type<T>::type;
+ using U = std::underlying_type_t<T>;
return writeInteger<U>(static_cast<U>(Num));
}
diff --git a/llvm/include/llvm/Support/BranchProbability.h b/llvm/include/llvm/Support/BranchProbability.h
index cd9d369b4f4e6..6c7ad1fe2a52c 100644
--- a/llvm/include/llvm/Support/BranchProbability.h
+++ b/llvm/include/llvm/Support/BranchProbability.h
@@ -32,8 +32,8 @@ class BranchProbability {
uint32_t N;
// Denominator, which is a constant value.
- static const uint32_t D = 1u << 31;
- static const uint32_t UnknownN = UINT32_MAX;
+ static constexpr uint32_t D = 1u << 31;
+ static constexpr uint32_t UnknownN = UINT32_MAX;
// Construct a BranchProbability with only numerator assuming the denominator
// is 1<<31. For internal use only.
diff --git a/llvm/include/llvm/Support/CFGDiff.h b/llvm/include/llvm/Support/CFGDiff.h
new file mode 100644
index 0000000000000..94734ce70e02c
--- /dev/null
+++ b/llvm/include/llvm/Support/CFGDiff.h
@@ -0,0 +1,250 @@
+//===- CFGDiff.h - Define a CFG snapshot. -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines specializations of GraphTraits that allows generic
+// algorithms to see a different snapshot of a CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CFGDIFF_H
+#define LLVM_SUPPORT_CFGDIFF_H
+
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/CFGUpdate.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+
+// Two booleans are used to define orders in graphs:
+// InverseGraph defines when we need to reverse the whole graph and is as such
+// also equivalent to applying updates in reverse.
+// InverseEdge defines whether we want to change the edges direction. E.g., for
+// a non-inversed graph, the children are naturally the successors when
+// InverseEdge is false and the predecessors when InverseEdge is true.
+
+// We define two base clases that call into GraphDiff, one for successors
+// (CFGSuccessors), where InverseEdge is false, and one for predecessors
+// (CFGPredecessors), where InverseEdge is true.
+// FIXME: Further refactoring may merge the two base classes into a single one
+// templated / parametrized on using succ_iterator/pred_iterator and false/true
+// for the InverseEdge.
+
+// CFGViewChildren and CFGViewPredecessors, both can be parametrized to
+// consider the graph inverted or not (i.e. InverseGraph). Successors
+// implicitly has InverseEdge = false and Predecessors implicitly has
+// InverseEdge = true (see calls to GraphDiff methods in there). The GraphTraits
+// instantiations that follow define the value of InverseGraph.
+
+// GraphTraits instantiations:
+// - GraphDiff<BasicBlock *> is equivalent to InverseGraph = false
+// - GraphDiff<Inverse<BasicBlock *>> is equivalent to InverseGraph = true
+// - second pair item is BasicBlock *, then InverseEdge = false (so it inherits
+// from CFGViewChildren).
+// - second pair item is Inverse<BasicBlock *>, then InverseEdge = true (so it
+// inherits from CFGViewPredecessors).
+
+// The 4 GraphTraits are as follows:
+// 1. std::pair<const GraphDiff<BasicBlock *> *, BasicBlock *>> :
+// CFGViewChildren<false>
+// Regular CFG, children means successors, InverseGraph = false,
+// InverseEdge = false.
+// 2. std::pair<const GraphDiff<Inverse<BasicBlock *>> *, BasicBlock *>> :
+// CFGViewChildren<true>
+// Reverse the graph, get successors but reverse-apply updates,
+// InverseGraph = true, InverseEdge = false.
+// 3. std::pair<const GraphDiff<BasicBlock *> *, Inverse<BasicBlock *>>> :
+// CFGViewPredecessors<false>
+// Regular CFG, reverse edges, so children mean predecessors,
+// InverseGraph = false, InverseEdge = true.
+// 4. std::pair<const GraphDiff<Inverse<BasicBlock *>> *, Inverse<BasicBlock *>>
+// : CFGViewPredecessors<true>
+// Reverse the graph and the edges, InverseGraph = true, InverseEdge = true.
+
+namespace llvm {
+
+// GraphDiff defines a CFG snapshot: given a set of Update<NodePtr>, provide
+// utilities to skip edges marked as deleted and return a set of edges marked as
+// newly inserted. The current diff treats the CFG as a graph rather than a
+// multigraph. Added edges are pruned to be unique, and deleted edges will
+// remove all existing edges between two blocks.
+template <typename NodePtr, bool InverseGraph = false> class GraphDiff {
+ using UpdateMapType = SmallDenseMap<NodePtr, SmallVector<NodePtr, 2>>;
+ struct EdgesInsertedDeleted {
+ UpdateMapType Succ;
+ UpdateMapType Pred;
+ };
+ // Store Deleted edges on position 0, and Inserted edges on position 1.
+ EdgesInsertedDeleted Edges[2];
+ // By default, it is assumed that, given a CFG and a set of updates, we wish
+ // to apply these updates as given. If UpdatedAreReverseApplied is set, the
+ // updates will be applied in reverse: deleted edges are considered re-added
+ // and inserted edges are considered deleted when returning children.
+ bool UpdatedAreReverseApplied;
+ // Using a singleton empty vector for all node requests with no
+ // children.
+ SmallVector<NodePtr, 0> Empty;
+
+ // Keep the list of legalized updates for a deterministic order of updates
+ // when using a GraphDiff for incremental updates in the DominatorTree.
+ // The list is kept in reverse to allow popping from end.
+ SmallVector<cfg::Update<NodePtr>, 4> LegalizedUpdates;
+
+ void printMap(raw_ostream &OS, const UpdateMapType &M) const {
+ for (auto Pair : M)
+ for (auto Child : Pair.second) {
+ OS << "(";
+ Pair.first->printAsOperand(OS, false);
+ OS << ", ";
+ Child->printAsOperand(OS, false);
+ OS << ") ";
+ }
+ OS << "\n";
+ }
+
+public:
+ GraphDiff() : UpdatedAreReverseApplied(false) {}
+ GraphDiff(ArrayRef<cfg::Update<NodePtr>> Updates,
+ bool ReverseApplyUpdates = false) {
+ cfg::LegalizeUpdates<NodePtr>(Updates, LegalizedUpdates, InverseGraph,
+ /*ReverseResultOrder=*/true);
+ // The legalized updates are stored in reverse so we can pop_back when doing
+ // incremental updates.
+ for (auto U : LegalizedUpdates) {
+ unsigned IsInsert =
+ (U.getKind() == cfg::UpdateKind::Insert) == !ReverseApplyUpdates;
+ Edges[IsInsert].Succ[U.getFrom()].push_back(U.getTo());
+ Edges[IsInsert].Pred[U.getTo()].push_back(U.getFrom());
+ }
+ UpdatedAreReverseApplied = ReverseApplyUpdates;
+ }
+
+ auto getLegalizedUpdates() const {
+ return make_range(LegalizedUpdates.begin(), LegalizedUpdates.end());
+ }
+
+ unsigned getNumLegalizedUpdates() const { return LegalizedUpdates.size(); }
+
+ cfg::Update<NodePtr> popUpdateForIncrementalUpdates() {
+ assert(!LegalizedUpdates.empty() && "No updates to apply!");
+ auto U = LegalizedUpdates.pop_back_val();
+ unsigned IsInsert =
+ (U.getKind() == cfg::UpdateKind::Insert) == !UpdatedAreReverseApplied;
+ auto &SuccList = Edges[IsInsert].Succ[U.getFrom()];
+ assert(SuccList.back() == U.getTo());
+ SuccList.pop_back();
+ if (SuccList.empty())
+ Edges[IsInsert].Succ.erase(U.getFrom());
+
+ auto &PredList = Edges[IsInsert].Pred[U.getTo()];
+ assert(PredList.back() == U.getFrom());
+ PredList.pop_back();
+ if (PredList.empty())
+ Edges[IsInsert].Pred.erase(U.getTo());
+ return U;
+ }
+
+ bool ignoreChild(const NodePtr BB, NodePtr EdgeEnd, bool InverseEdge) const {
+ // Used to filter nullptr in clang.
+ if (EdgeEnd == nullptr)
+ return true;
+ auto &DeleteChildren =
+ (InverseEdge != InverseGraph) ? Edges[0].Pred : Edges[0].Succ;
+ auto It = DeleteChildren.find(BB);
+ if (It == DeleteChildren.end())
+ return false;
+ auto &EdgesForBB = It->second;
+ return llvm::find(EdgesForBB, EdgeEnd) != EdgesForBB.end();
+ }
+
+ iterator_range<typename SmallVectorImpl<NodePtr>::const_iterator>
+ getAddedChildren(const NodePtr BB, bool InverseEdge) const {
+ auto &InsertChildren =
+ (InverseEdge != InverseGraph) ? Edges[1].Pred : Edges[1].Succ;
+ auto It = InsertChildren.find(BB);
+ if (It == InsertChildren.end())
+ return make_range(Empty.begin(), Empty.end());
+ return make_range(It->second.begin(), It->second.end());
+ }
+
+ void print(raw_ostream &OS) const {
+ OS << "===== GraphDiff: CFG edge changes to create a CFG snapshot. \n"
+ "===== (Note: notion of children/inverse_children depends on "
+ "the direction of edges and the graph.)\n";
+ OS << "Children to insert:\n\t";
+ printMap(OS, Edges[1].Succ);
+ OS << "Children to delete:\n\t";
+ printMap(OS, Edges[0].Succ);
+ OS << "Inverse_children to insert:\n\t";
+ printMap(OS, Edges[1].Pred);
+ OS << "Inverse_children to delete:\n\t";
+ printMap(OS, Edges[0].Pred);
+ OS << "\n";
+ }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
+#endif
+};
+
+template <typename GraphT, bool InverseGraph = false, bool InverseEdge = false,
+ typename GT = GraphTraits<GraphT>>
+struct CFGViewChildren {
+ using DataRef = const GraphDiff<typename GT::NodeRef, InverseGraph> *;
+ using NodeRef = std::pair<DataRef, typename GT::NodeRef>;
+
+ template<typename Range>
+ static auto makeChildRange(Range &&R, DataRef DR) {
+ using Iter = WrappedPairNodeDataIterator<decltype(std::forward<Range>(R).begin()), NodeRef, DataRef>;
+ return make_range(Iter(R.begin(), DR), Iter(R.end(), DR));
+ }
+
+ static auto children(NodeRef N) {
+
+ // filter iterator init:
+ auto R = make_range(GT::child_begin(N.second), GT::child_end(N.second));
+ // This lambda is copied into the iterators and persists to callers, ensure
+ // captures are by value or otherwise have sufficient lifetime.
+ auto First = make_filter_range(makeChildRange(R, N.first), [N](NodeRef C) {
+ return !C.first->ignoreChild(N.second, C.second, InverseEdge);
+ });
+
+ // new inserts iterator init:
+ auto InsertVec = N.first->getAddedChildren(N.second, InverseEdge);
+ auto Second = makeChildRange(InsertVec, N.first);
+
+ auto CR = concat<NodeRef>(First, Second);
+
+ // concat_range contains references to other ranges, returning it would
+ // leave those references dangling - the iterators contain
+ // other iterators by value so they're safe to return.
+ return make_range(CR.begin(), CR.end());
+ }
+
+ static auto child_begin(NodeRef N) {
+ return children(N).begin();
+ }
+
+ static auto child_end(NodeRef N) {
+ return children(N).end();
+ }
+
+ using ChildIteratorType = decltype(child_end(std::declval<NodeRef>()));
+};
+
+template <typename T, bool B>
+struct GraphTraits<std::pair<const GraphDiff<T, B> *, T>>
+ : CFGViewChildren<T, B> {};
+template <typename T, bool B>
+struct GraphTraits<std::pair<const GraphDiff<T, B> *, Inverse<T>>>
+ : CFGViewChildren<Inverse<T>, B, true> {};
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_CFGDIFF_H
diff --git a/llvm/include/llvm/Support/CFGUpdate.h b/llvm/include/llvm/Support/CFGUpdate.h
index eeaf5d0a21acd..af4cd6ed1f1df 100644
--- a/llvm/include/llvm/Support/CFGUpdate.h
+++ b/llvm/include/llvm/Support/CFGUpdate.h
@@ -62,7 +62,7 @@ public:
template <typename NodePtr>
void LegalizeUpdates(ArrayRef<Update<NodePtr>> AllUpdates,
SmallVectorImpl<Update<NodePtr>> &Result,
- bool InverseGraph) {
+ bool InverseGraph, bool ReverseResultOrder = false) {
// Count the total number of inserions of each edge.
// Each insertion adds 1 and deletion subtracts 1. The end number should be
// one of {-1 (deletion), 0 (NOP), +1 (insertion)}. Otherwise, the sequence
@@ -104,11 +104,11 @@ void LegalizeUpdates(ArrayRef<Update<NodePtr>> AllUpdates,
Operations[{U.getTo(), U.getFrom()}] = int(i);
}
- llvm::sort(Result,
- [&Operations](const Update<NodePtr> &A, const Update<NodePtr> &B) {
- return Operations[{A.getFrom(), A.getTo()}] >
- Operations[{B.getFrom(), B.getTo()}];
- });
+ llvm::sort(Result, [&](const Update<NodePtr> &A, const Update<NodePtr> &B) {
+ const auto &OpA = Operations[{A.getFrom(), A.getTo()}];
+ const auto &OpB = Operations[{B.getFrom(), B.getTo()}];
+ return ReverseResultOrder ? OpA < OpB : OpA > OpB;
+ });
}
} // end namespace cfg
diff --git a/llvm/include/llvm/Support/CachePruning.h b/llvm/include/llvm/Support/CachePruning.h
index a72a86439f6a5..10d6372f9163c 100644
--- a/llvm/include/llvm/Support/CachePruning.h
+++ b/llvm/include/llvm/Support/CachePruning.h
@@ -14,12 +14,13 @@
#ifndef LLVM_SUPPORT_CACHE_PRUNING_H
#define LLVM_SUPPORT_CACHE_PRUNING_H
-#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Optional.h"
#include <chrono>
namespace llvm {
template <typename T> class Expected;
+class StringRef;
/// Policy for the pruneCache() function. A default constructed
/// CachePruningPolicy provides a reasonable default policy.
diff --git a/llvm/include/llvm/Support/Casting.h b/llvm/include/llvm/Support/Casting.h
index 46bdedb04cfe6..d6f7793d5df01 100644
--- a/llvm/include/llvm/Support/Casting.h
+++ b/llvm/include/llvm/Support/Casting.h
@@ -61,8 +61,7 @@ struct isa_impl {
/// Always allow upcasts, and perform no dynamic check for them.
template <typename To, typename From>
-struct isa_impl<
- To, From, typename std::enable_if<std::is_base_of<To, From>::value>::type> {
+struct isa_impl<To, From, std::enable_if_t<std::is_base_of<To, From>::value>> {
static inline bool doit(const From &) { return true; }
};
@@ -133,24 +132,30 @@ struct isa_impl_wrap<To, FromTy, FromTy> {
}
};
-// isa<X> - Return true if the parameter to the template is an instance of the
-// template type argument. Used like this:
+// isa<X> - Return true if the parameter to the template is an instance of one
+// of the template type arguments. Used like this:
//
// if (isa<Type>(myVal)) { ... }
+// if (isa<Type0, Type1, Type2>(myVal)) { ... }
//
template <class X, class Y> LLVM_NODISCARD inline bool isa(const Y &Val) {
return isa_impl_wrap<X, const Y,
typename simplify_type<const Y>::SimpleType>::doit(Val);
}
+template <typename First, typename Second, typename... Rest, typename Y>
+LLVM_NODISCARD inline bool isa(const Y &Val) {
+ return isa<First>(Val) || isa<Second, Rest...>(Val);
+}
+
// isa_and_nonnull<X> - Functionally identical to isa, except that a null value
// is accepted.
//
-template <class X, class Y>
+template <typename... X, class Y>
LLVM_NODISCARD inline bool isa_and_nonnull(const Y &Val) {
if (!Val)
return false;
- return isa<X>(Val);
+ return isa<X...>(Val);
}
//===----------------------------------------------------------------------===//
@@ -184,7 +189,7 @@ 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;
+ using ResultType = std::remove_pointer_t<PointerType>;
public:
using ret_type = std::unique_ptr<ResultType>;
@@ -244,8 +249,8 @@ template <class X> struct is_simple_type {
// cast<Instruction>(myVal)->getParent()
//
template <class X, class Y>
-inline typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, const Y>::ret_type>::type
+inline std::enable_if_t<!is_simple_type<Y>::value,
+ typename cast_retty<X, const Y>::ret_type>
cast(const Y &Val) {
assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
return cast_convert_val<
@@ -280,10 +285,9 @@ cast(std::unique_ptr<Y> &&Val) {
// accepted.
//
template <class X, class Y>
-LLVM_NODISCARD inline
- typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, const Y>::ret_type>::type
- cast_or_null(const Y &Val) {
+LLVM_NODISCARD inline std::enable_if_t<
+ !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>
+cast_or_null(const Y &Val) {
if (!Val)
return nullptr;
assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
@@ -291,10 +295,9 @@ LLVM_NODISCARD inline
}
template <class X, class Y>
-LLVM_NODISCARD inline
- typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, Y>::ret_type>::type
- cast_or_null(Y &Val) {
+LLVM_NODISCARD inline std::enable_if_t<!is_simple_type<Y>::value,
+ typename cast_retty<X, Y>::ret_type>
+cast_or_null(Y &Val) {
if (!Val)
return nullptr;
assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
@@ -326,10 +329,9 @@ cast_or_null(std::unique_ptr<Y> &&Val) {
//
template <class X, class Y>
-LLVM_NODISCARD inline
- typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, const Y>::ret_type>::type
- dyn_cast(const Y &Val) {
+LLVM_NODISCARD inline std::enable_if_t<
+ !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>
+dyn_cast(const Y &Val) {
return isa<X>(Val) ? cast<X>(Val) : nullptr;
}
@@ -347,18 +349,16 @@ LLVM_NODISCARD inline typename cast_retty<X, Y *>::ret_type dyn_cast(Y *Val) {
// value is accepted.
//
template <class X, class Y>
-LLVM_NODISCARD inline
- typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, const Y>::ret_type>::type
- dyn_cast_or_null(const Y &Val) {
+LLVM_NODISCARD inline std::enable_if_t<
+ !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>
+dyn_cast_or_null(const Y &Val) {
return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
}
template <class X, class Y>
-LLVM_NODISCARD inline
- typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, Y>::ret_type>::type
- dyn_cast_or_null(Y &Val) {
+LLVM_NODISCARD inline std::enable_if_t<!is_simple_type<Y>::value,
+ typename cast_retty<X, Y>::ret_type>
+dyn_cast_or_null(Y &Val) {
return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
}
@@ -382,8 +382,7 @@ LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr<Y> &Val)
}
template <class X, class Y>
-LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val)
- -> decltype(cast<X>(Val)) {
+LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val) {
return unique_dyn_cast<X, Y>(Val);
}
@@ -398,8 +397,7 @@ LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr<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)) {
+LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val) {
return unique_dyn_cast_or_null<X, Y>(Val);
}
diff --git a/llvm/include/llvm/Support/CheckedArithmetic.h b/llvm/include/llvm/Support/CheckedArithmetic.h
index 8a50e3d5ddf6f..035e4533322cb 100644
--- a/llvm/include/llvm/Support/CheckedArithmetic.h
+++ b/llvm/include/llvm/Support/CheckedArithmetic.h
@@ -25,8 +25,8 @@ namespace {
/// \p RHS.
/// \return Empty optional if the operation overflows, or result otherwise.
template <typename T, typename F>
-typename std::enable_if<std::is_integral<T>::value && sizeof(T) * 8 <= 64,
- llvm::Optional<T>>::type
+std::enable_if_t<std::is_integral<T>::value && sizeof(T) * 8 <= 64,
+ llvm::Optional<T>>
checkedOp(T LHS, T RHS, F Op, bool Signed = true) {
llvm::APInt ALHS(/*BitSize=*/sizeof(T) * 8, LHS, Signed);
llvm::APInt ARHS(/*BitSize=*/sizeof(T) * 8, RHS, Signed);
@@ -44,7 +44,7 @@ namespace llvm {
/// \return Optional of sum if no signed overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
checkedAdd(T LHS, T RHS) {
return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov);
}
@@ -53,7 +53,7 @@ checkedAdd(T LHS, T RHS) {
/// \return Optional of sum if no signed overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
checkedSub(T LHS, T RHS) {
return checkedOp(LHS, RHS, &llvm::APInt::ssub_ov);
}
@@ -62,7 +62,7 @@ checkedSub(T LHS, T RHS) {
/// \return Optional of product if no signed overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
checkedMul(T LHS, T RHS) {
return checkedOp(LHS, RHS, &llvm::APInt::smul_ov);
}
@@ -71,7 +71,7 @@ checkedMul(T LHS, T RHS) {
/// \return Optional of result if no signed overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
checkedMulAdd(T A, T B, T C) {
if (auto Product = checkedMul(A, B))
return checkedAdd(*Product, C);
@@ -82,7 +82,7 @@ checkedMulAdd(T A, T B, T C) {
/// \return Optional of sum if no unsigned overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_unsigned<T>::value, llvm::Optional<T>>
checkedAddUnsigned(T LHS, T RHS) {
return checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, /*Signed=*/false);
}
@@ -91,7 +91,7 @@ checkedAddUnsigned(T LHS, T RHS) {
/// \return Optional of product if no unsigned overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_unsigned<T>::value, llvm::Optional<T>>
checkedMulUnsigned(T LHS, T RHS) {
return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, /*Signed=*/false);
}
@@ -100,7 +100,7 @@ checkedMulUnsigned(T LHS, T RHS) {
/// \return Optional of result if no unsigned overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_unsigned<T>::value, llvm::Optional<T>>
checkedMulAddUnsigned(T A, T B, T C) {
if (auto Product = checkedMulUnsigned(A, B))
return checkedAddUnsigned(*Product, C);
diff --git a/llvm/include/llvm/Support/Chrono.h b/llvm/include/llvm/Support/Chrono.h
index 334ab60835a44..098512dce783b 100644
--- a/llvm/include/llvm/Support/Chrono.h
+++ b/llvm/include/llvm/Support/Chrono.h
@@ -112,8 +112,8 @@ 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
+ typedef std::conditional_t<std::chrono::treat_as_floating_point<Rep>::value,
+ double, intmax_t>
InternalRep;
template <typename AsPeriod> static InternalRep getAs(const Dur &D) {
diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h
index 05374e34aa7d4..466945e40a9ce 100644
--- a/llvm/include/llvm/Support/CommandLine.h
+++ b/llvm/include/llvm/Support/CommandLine.h
@@ -45,7 +45,6 @@
namespace llvm {
class StringSaver;
-class raw_ostream;
/// cl Namespace - This namespace contains all of the command line option
/// processing machinery. It is intentionally a short name to make qualified
@@ -488,14 +487,13 @@ struct callback_traits : public callback_traits<decltype(&F::operator())> {};
template <typename R, typename C, typename... Args>
struct callback_traits<R (C::*)(Args...) const> {
using result_type = R;
- using arg_type = typename std::tuple_element<0, std::tuple<Args...>>::type;
+ using arg_type = std::tuple_element_t<0, std::tuple<Args...>>;
static_assert(sizeof...(Args) == 1, "callback function must have one and only one parameter");
static_assert(std::is_same<result_type, void>::value,
"callback return type must be void");
- static_assert(
- std::is_lvalue_reference<arg_type>::value &&
- std::is_const<typename std::remove_reference<arg_type>::type>::value,
- "callback arg_type must be a const lvalue reference");
+ static_assert(std::is_lvalue_reference<arg_type>::value &&
+ std::is_const<std::remove_reference_t<arg_type>>::value,
+ "callback arg_type must be a const lvalue reference");
};
} // namespace detail
@@ -1453,16 +1451,16 @@ class opt : public Option,
}
}
- template <class T, class = typename std::enable_if<
- std::is_assignable<T&, T>::value>::type>
+ template <class T,
+ class = std::enable_if_t<std::is_assignable<T &, T>::value>>
void setDefaultImpl() {
const OptionValue<DataType> &V = this->getDefault();
if (V.hasValue())
this->setValue(V.getValue());
}
- template <class T, class = typename std::enable_if<
- !std::is_assignable<T&, T>::value>::type>
+ template <class T,
+ class = std::enable_if_t<!std::is_assignable<T &, T>::value>>
void setDefaultImpl(...) {}
void setDefault() override { setDefaultImpl<DataType>(); }
@@ -1607,8 +1605,8 @@ public:
reference front() { return Storage.front(); }
const_reference front() const { return Storage.front(); }
- operator std::vector<DataType>&() { return Storage; }
- operator ArrayRef<DataType>() { return Storage; }
+ operator std::vector<DataType> &() { return Storage; }
+ operator ArrayRef<DataType>() const { return Storage; }
std::vector<DataType> *operator&() { return &Storage; }
const std::vector<DataType> *operator&() const { return &Storage; }
@@ -2028,6 +2026,13 @@ void TokenizeWindowsCommandLine(StringRef Source, StringSaver &Saver,
SmallVectorImpl<const char *> &NewArgv,
bool MarkEOLs = false);
+/// Tokenizes a Windows command line while attempting to avoid copies. If no
+/// quoting or escaping was used, this produces substrings of the original
+/// string. If a token requires unquoting, it will be allocated with the
+/// StringSaver.
+void TokenizeWindowsCommandLineNoCopy(StringRef Source, StringSaver &Saver,
+ SmallVectorImpl<StringRef> &NewArgv);
+
/// String tokenization function type. Should be compatible with either
/// Windows or Unix command line tokenizers.
using TokenizerCallback = void (*)(StringRef Source, StringSaver &Saver,
diff --git a/llvm/include/llvm/Support/Compiler.h b/llvm/include/llvm/Support/Compiler.h
index 6f6f65cad6f5b..80ea76240d6cf 100644
--- a/llvm/include/llvm/Support/Compiler.h
+++ b/llvm/include/llvm/Support/Compiler.h
@@ -95,7 +95,8 @@
/// Does the compiler support ref-qualifiers for *this?
///
/// Sadly, this is separate from just rvalue reference support because GCC
-/// and MSVC implemented this later than everything else.
+/// and MSVC implemented this later than everything else. This appears to be
+/// corrected in MSVC 2019 but not MSVC 2017.
#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1)
#define LLVM_HAS_RVALUE_REFERENCE_THIS 1
#else
@@ -288,6 +289,22 @@
#define LLVM_REQUIRE_CONSTANT_INITIALIZATION
#endif
+/// LLVM_GSL_OWNER - Apply this to owning classes like SmallVector to enable
+/// lifetime warnings.
+#if LLVM_HAS_CPP_ATTRIBUTE(gsl::Owner)
+#define LLVM_GSL_OWNER [[gsl::Owner]]
+#else
+#define LLVM_GSL_OWNER
+#endif
+
+/// LLVM_GSL_POINTER - Apply this to non-owning classes like
+/// StringRef to enable lifetime warnings.
+#if LLVM_HAS_CPP_ATTRIBUTE(gsl::Pointer)
+#define LLVM_GSL_POINTER [[gsl::Pointer]]
+#else
+#define LLVM_GSL_POINTER
+#endif
+
/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
/// pedantic diagnostics.
#ifdef __GNUC__
@@ -356,7 +373,6 @@
#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
@@ -542,48 +558,4 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#define LLVM_ENABLE_EXCEPTIONS 1
#endif
-#ifdef __cplusplus
-namespace llvm {
-
-/// Allocate a buffer of memory with the given size and alignment.
-///
-/// 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/llvm/include/llvm/Support/CrashRecoveryContext.h b/llvm/include/llvm/Support/CrashRecoveryContext.h
index 9522c4742244e..61a1bd405a4d4 100644
--- a/llvm/include/llvm/Support/CrashRecoveryContext.h
+++ b/llvm/include/llvm/Support/CrashRecoveryContext.h
@@ -99,7 +99,8 @@ public:
/// Explicitly trigger a crash recovery in the current process, and
/// return failure from RunSafely(). This function does not return.
- void HandleCrash();
+ LLVM_ATTRIBUTE_NORETURN
+ void HandleExit(int RetCode);
/// In case of a crash, this is the crash identifier.
int RetCode = 0;
diff --git a/llvm/include/llvm/Support/DataExtractor.h b/llvm/include/llvm/Support/DataExtractor.h
index 0be478811b22f..f9335c161563c 100644
--- a/llvm/include/llvm/Support/DataExtractor.h
+++ b/llvm/include/llvm/Support/DataExtractor.h
@@ -105,19 +105,32 @@ public:
/// updated with the offset of the byte that follows the NULL
/// terminator byte.
///
- /// @param[in,out] offset_ptr
+ /// @param[in,out] OffsetPtr
/// A pointer to an offset within the data that will be advanced
/// by the appropriate number of bytes if the value is extracted
/// correctly. If the offset is out of bounds or there are not
/// enough bytes to extract this value, the offset will be left
/// unmodified.
///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
/// @return
/// A pointer to the C string value in the data. If the offset
/// pointed to by \a offset_ptr is out of bounds, or if the
/// offset plus the length of the C string is out of bounds,
/// NULL will be returned.
- const char *getCStr(uint64_t *offset_ptr) const;
+ const char *getCStr(uint64_t *OffsetPtr, Error *Err = nullptr) const {
+ return getCStrRef(OffsetPtr, Err).data();
+ }
+
+ /// Extract a C string from the location given by the cursor. In case of an
+ /// extraction error, or if the cursor is already in an error state, a
+ /// nullptr is returned.
+ const char *getCStr(Cursor &C) const { return getCStrRef(C).data(); }
/// Extract a C string from \a *offset_ptr.
///
@@ -127,19 +140,102 @@ public:
/// updated with the offset of the byte that follows the NULL
/// terminator byte.
///
- /// \param[in,out] offset_ptr
+ /// \param[in,out] OffsetPtr
/// A pointer to an offset within the data that will be advanced
/// by the appropriate number of bytes if the value is extracted
/// correctly. If the offset is out of bounds or there are not
/// enough bytes to extract this value, the offset will be left
/// unmodified.
///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
/// \return
/// A 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;
+ StringRef getCStrRef(uint64_t *OffsetPtr, Error *Err = nullptr) const;
+
+ /// Extract a C string (as a StringRef) from the location given by the cursor.
+ /// In case of an extraction error, or if the cursor is already in an error
+ /// state, a default-initialized StringRef is returned.
+ StringRef getCStrRef(Cursor &C) const {
+ return getCStrRef(&C.Offset, &C.Err);
+ }
+
+ /// Extract a fixed length string from \a *OffsetPtr and consume \a Length
+ /// bytes.
+ ///
+ /// Returns a StringRef for the string from the data at the offset
+ /// pointed to by \a OffsetPtr. A fixed length C string will be extracted
+ /// and the \a OffsetPtr will be advanced by \a Length bytes.
+ ///
+ /// \param[in,out] OffsetPtr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// \param[in] Length
+ /// The length of the fixed length string to extract. If there are not
+ /// enough bytes in the data to extract the full string, the offset will
+ /// be left unmodified.
+ ///
+ /// \param[in] TrimChars
+ /// A set of characters to trim from the end of the string. Fixed length
+ /// strings are commonly either NULL terminated by one or more zero
+ /// bytes. Some clients have one or more spaces at the end of the string,
+ /// but a good default is to trim the NULL characters.
+ ///
+ /// \return
+ /// A StringRef for the C string value in the data. If the offset
+ /// pointed to by \a OffsetPtr is out of bounds, or if the
+ /// offset plus the length of the C string is out of bounds,
+ /// a default-initialized StringRef will be returned.
+ StringRef getFixedLengthString(uint64_t *OffsetPtr,
+ uint64_t Length, StringRef TrimChars = {"\0", 1}) const;
+
+ /// Extract a fixed number of bytes from the specified offset.
+ ///
+ /// Returns a StringRef for the bytes from the data at the offset
+ /// pointed to by \a OffsetPtr. A fixed length C string will be extracted
+ /// and the \a OffsetPtr will be advanced by \a Length bytes.
+ ///
+ /// \param[in,out] OffsetPtr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// \param[in] Length
+ /// The number of bytes to extract. If there are not enough bytes in the
+ /// data to extract all of the bytes, the offset will be left unmodified.
+ ///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
+ /// \return
+ /// A StringRef for the extracted bytes. If the offset pointed to by
+ /// \a OffsetPtr is out of bounds, or if the offset plus the length
+ /// is out of bounds, a default-initialized StringRef will be returned.
+ StringRef getBytes(uint64_t *OffsetPtr, uint64_t Length,
+ Error *Err = nullptr) const;
+
+ /// Extract a fixed number of bytes from the location given by the cursor. In
+ /// case of an extraction error, or if the cursor is already in an error
+ /// state, a default-initialized StringRef is returned.
+ StringRef getBytes(Cursor &C, uint64_t Length) {
+ return getBytes(&C.Offset, Length, &C.Err);
+ }
/// Extract an unsigned integer of size \a byte_size from \a
/// *offset_ptr.
@@ -365,15 +461,26 @@ public:
/// \a offset_ptr, construct a uint32_t from them and update the offset
/// on success.
///
- /// @param[in,out] offset_ptr
+ /// @param[in,out] OffsetPtr
/// A pointer to an offset within the data that will be advanced
/// by the 3 bytes if the value is extracted correctly. If the offset
/// is out of bounds or there are not enough bytes to extract this value,
/// the offset will be left unmodified.
///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
/// @return
/// The extracted 24-bit value represented in a uint32_t.
- uint32_t getU24(uint64_t *offset_ptr) const;
+ uint32_t getU24(uint64_t *OffsetPtr, Error *Err = nullptr) const;
+
+ /// Extract a single 24-bit unsigned value from the location given by the
+ /// cursor. In case of an extraction error, or if the cursor is already in an
+ /// error state, zero is returned.
+ uint32_t getU24(Cursor &C) const { return getU24(&C.Offset, &C.Err); }
/// Extract a uint32_t value from \a *offset_ptr.
///
@@ -486,16 +593,27 @@ public:
/// pointed to by \a offset_ptr will be updated with the offset of
/// the byte following the last extracted byte.
///
- /// @param[in,out] offset_ptr
+ /// @param[in,out] OffsetPtr
/// A pointer to an offset within the data that will be advanced
/// by the appropriate number of bytes if the value is extracted
/// correctly. If the offset is out of bounds or there are not
/// enough bytes to extract this value, the offset will be left
/// unmodified.
///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
/// @return
/// The extracted signed integer value.
- int64_t getSLEB128(uint64_t *offset_ptr) const;
+ int64_t getSLEB128(uint64_t *OffsetPtr, Error *Err = nullptr) const;
+
+ /// Extract an signed LEB128 value from the location given by the cursor.
+ /// In case of an extraction error, or if the cursor is already in an error
+ /// state, zero is returned.
+ int64_t getSLEB128(Cursor &C) const { return getSLEB128(&C.Offset, &C.Err); }
/// Extract a unsigned LEB128 value from \a *offset_ptr.
///
@@ -521,7 +639,7 @@ public:
/// 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.
+ /// Extract an unsigned LEB128 value from the location given by the cursor.
/// In case of an extraction error, or if the cursor is already in an error
/// state, zero is returned.
uint64_t getULEB128(Cursor &C) const { return getULEB128(&C.Offset, &C.Err); }
@@ -571,6 +689,16 @@ protected:
// public.
static uint64_t &getOffset(Cursor &C) { return C.Offset; }
static Error &getError(Cursor &C) { return C.Err; }
+
+private:
+ /// If it is possible to read \a Size bytes at offset \a Offset, returns \b
+ /// true. Otherwise, returns \b false. If \a E is not nullptr, also sets the
+ /// error object to indicate an error.
+ bool prepareRead(uint64_t Offset, uint64_t Size, Error *E) const;
+
+ template <typename T> T getU(uint64_t *OffsetPtr, Error *Err) const;
+ template <typename T>
+ T *getUs(uint64_t *OffsetPtr, T *Dst, uint32_t Count, Error *Err) const;
};
} // namespace llvm
diff --git a/llvm/include/llvm/Support/DebugCounter.h b/llvm/include/llvm/Support/DebugCounter.h
index e7d1fa68f21ae..cd9474a4d9184 100644
--- a/llvm/include/llvm/Support/DebugCounter.h
+++ b/llvm/include/llvm/Support/DebugCounter.h
@@ -44,14 +44,15 @@
#define LLVM_SUPPORT_DEBUGCOUNTER_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/UniqueVector.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
#include <string>
namespace llvm {
+class raw_ostream;
+
class DebugCounter {
public:
~DebugCounter();
@@ -68,7 +69,7 @@ public:
// line option parsing. The main reason to register counters is to produce a
// nice list of them on the command line, but i'm not sure this is worth it.
static unsigned registerCounter(StringRef Name, StringRef Desc) {
- return instance().addCounter(Name, Desc);
+ return instance().addCounter(std::string(Name), std::string(Desc));
}
inline static bool shouldExecute(unsigned CounterName) {
if (!isCountingEnabled())
diff --git a/llvm/include/llvm/Support/ELFAttributeParser.h b/llvm/include/llvm/Support/ELFAttributeParser.h
new file mode 100644
index 0000000000000..8bf87b2d84f05
--- /dev/null
+++ b/llvm/include/llvm/Support/ELFAttributeParser.h
@@ -0,0 +1,72 @@
+//===- ELF AttributeParser.h - ELF Attribute Parser -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ELFATTRIBUTEPARSER_H
+#define LLVM_SUPPORT_ELFATTRIBUTEPARSER_H
+
+#include "ELFAttributes.h"
+#include "ScopedPrinter.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Error.h"
+
+#include <unordered_map>
+
+namespace llvm {
+class StringRef;
+
+class ELFAttributeParser {
+ StringRef vendor;
+ std::unordered_map<unsigned, unsigned> attributes;
+ std::unordered_map<unsigned, StringRef> attributesStr;
+
+ virtual Error handler(uint64_t tag, bool &handled) = 0;
+
+protected:
+ ScopedPrinter *sw;
+ TagNameMap tagToStringMap;
+ DataExtractor de{ArrayRef<uint8_t>{}, true, 0};
+ DataExtractor::Cursor cursor{0};
+
+ void printAttribute(unsigned tag, unsigned value, StringRef valueDesc);
+
+ Error parseStringAttribute(const char *name, unsigned tag,
+ ArrayRef<const char *> strings);
+ Error parseAttributeList(uint32_t length);
+ void parseIndexList(SmallVectorImpl<uint8_t> &indexList);
+ Error parseSubsection(uint32_t length);
+
+public:
+ virtual ~ELFAttributeParser() { static_cast<void>(!cursor.takeError()); }
+ Error integerAttribute(unsigned tag);
+ Error stringAttribute(unsigned tag);
+
+ ELFAttributeParser(ScopedPrinter *sw, TagNameMap tagNameMap, StringRef vendor)
+ : vendor(vendor), sw(sw), tagToStringMap(tagNameMap) {}
+
+ ELFAttributeParser(TagNameMap tagNameMap, StringRef vendor)
+ : vendor(vendor), sw(nullptr), tagToStringMap(tagNameMap) {}
+
+ Error parse(ArrayRef<uint8_t> section, support::endianness endian);
+
+ Optional<unsigned> getAttributeValue(unsigned tag) const {
+ auto I = attributes.find(tag);
+ if (I == attributes.end())
+ return None;
+ return I->second;
+ }
+ Optional<StringRef> getAttributeString(unsigned tag) const {
+ auto I = attributesStr.find(tag);
+ if (I == attributesStr.end())
+ return None;
+ return I->second;
+ }
+};
+
+} // namespace llvm
+#endif
diff --git a/llvm/include/llvm/Support/ELFAttributes.h b/llvm/include/llvm/Support/ELFAttributes.h
new file mode 100644
index 0000000000000..c8a7ae142b9af
--- /dev/null
+++ b/llvm/include/llvm/Support/ELFAttributes.h
@@ -0,0 +1,37 @@
+//===-- ELFAttributes.h - ELF Attributes ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ELFATTRIBUTES_H
+#define LLVM_SUPPORT_ELFATTRIBUTES_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+struct TagNameItem {
+ unsigned attr;
+ StringRef tagName;
+};
+
+using TagNameMap = ArrayRef<TagNameItem>;
+
+namespace ELFAttrs {
+
+enum AttrType : unsigned { File = 1, Section = 2, Symbol = 3 };
+
+StringRef attrTypeAsString(unsigned attr, TagNameMap tagNameMap,
+ bool hasTagPrefix = true);
+Optional<unsigned> attrTypeFromString(StringRef tag, TagNameMap tagNameMap);
+
+// Magic numbers for ELF attributes.
+enum AttrMagic { Format_Version = 0x41 };
+
+} // namespace ELFAttrs
+} // namespace llvm
+#endif
diff --git a/llvm/include/llvm/Support/Endian.h b/llvm/include/llvm/Support/Endian.h
index 87aecedd3a4b4..5e7c1e961b9d1 100644
--- a/llvm/include/llvm/Support/Endian.h
+++ b/llvm/include/llvm/Support/Endian.h
@@ -13,9 +13,7 @@
#ifndef LLVM_SUPPORT_ENDIAN_H
#define LLVM_SUPPORT_ENDIAN_H
-#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/SwapByteOrder.h"
#include <cassert>
#include <cstddef>
@@ -111,7 +109,7 @@ inline void write(void *memory, value_type value) {
}
template <typename value_type>
-using make_unsigned_t = typename std::make_unsigned<value_type>::type;
+using make_unsigned_t = std::make_unsigned_t<value_type>;
/// Read a value of a particular endianness from memory, for a location
/// that starts at the given bit offset within the first byte.
diff --git a/llvm/include/llvm/Support/Errno.h b/llvm/include/llvm/Support/Errno.h
index aedb5fb292b84..dc3b3322ed982 100644
--- a/llvm/include/llvm/Support/Errno.h
+++ b/llvm/include/llvm/Support/Errno.h
@@ -30,8 +30,8 @@ std::string StrError();
std::string StrError(int errnum);
template <typename FailT, typename Fun, typename... Args>
-inline auto RetryAfterSignal(const FailT &Fail, const Fun &F,
- const Args &... As) -> decltype(F(As...)) {
+inline decltype(auto) RetryAfterSignal(const FailT &Fail, const Fun &F,
+ const Args &... As) {
decltype(F(As...)) Res;
do {
errno = 0;
diff --git a/llvm/include/llvm/Support/Error.h b/llvm/include/llvm/Support/Error.h
index 44676338808b4..9dd1bb7cb96de 100644
--- a/llvm/include/llvm/Support/Error.h
+++ b/llvm/include/llvm/Support/Error.h
@@ -269,9 +269,13 @@ private:
}
ErrorInfoBase *getPtr() const {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
return reinterpret_cast<ErrorInfoBase*>(
reinterpret_cast<uintptr_t>(Payload) &
~static_cast<uintptr_t>(0x1));
+#else
+ return Payload;
+#endif
}
void setPtr(ErrorInfoBase *EI) {
@@ -294,10 +298,12 @@ private:
}
void setChecked(bool V) {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
Payload = reinterpret_cast<ErrorInfoBase*>(
(reinterpret_cast<uintptr_t>(Payload) &
~static_cast<uintptr_t>(0x1)) |
(V ? 0 : 1));
+#endif
}
std::unique_ptr<ErrorInfoBase> takePayload() {
@@ -434,21 +440,21 @@ 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;
+ static constexpr bool isRef = std::is_reference<T>::value;
- using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
+ using wrap = std::reference_wrapper<std::remove_reference_t<T>>;
using error_type = std::unique_ptr<ErrorInfoBase>;
public:
- using storage_type = typename std::conditional<isRef, wrap, T>::type;
+ using storage_type = std::conditional_t<isRef, wrap, T>;
using value_type = T;
private:
- using reference = typename std::remove_reference<T>::type &;
- using const_reference = const typename std::remove_reference<T>::type &;
- using pointer = typename std::remove_reference<T>::type *;
- using const_pointer = const typename std::remove_reference<T>::type *;
+ using reference = std::remove_reference_t<T> &;
+ using const_reference = const std::remove_reference_t<T> &;
+ using pointer = std::remove_reference_t<T> *;
+ using const_pointer = const std::remove_reference_t<T> *;
public:
/// Create an Expected<T> error value from the given Error.
@@ -472,12 +478,12 @@ public:
/// must be convertible to T.
template <typename OtherT>
Expected(OtherT &&Val,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
- * = nullptr)
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr)
: HasError(false)
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
// Expected is unchecked upon construction in Debug builds.
- , Unchecked(true)
+ ,
+ Unchecked(true)
#endif
{
new (getStorage()) storage_type(std::forward<OtherT>(Val));
@@ -489,9 +495,9 @@ public:
/// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
/// must be convertible to T.
template <class OtherT>
- Expected(Expected<OtherT> &&Other,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
- * = nullptr) {
+ Expected(
+ Expected<OtherT> &&Other,
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr) {
moveConstruct(std::move(Other));
}
@@ -500,8 +506,7 @@ public:
template <class OtherT>
explicit Expected(
Expected<OtherT> &&Other,
- typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
- nullptr) {
+ std::enable_if_t<!std::is_convertible<OtherT, T>::value> * = nullptr) {
moveConstruct(std::move(Other));
}
diff --git a/llvm/include/llvm/Support/ErrorHandling.h b/llvm/include/llvm/Support/ErrorHandling.h
index f75c2984a9ff7..7cbc668b3a0e8 100644
--- a/llvm/include/llvm/Support/ErrorHandling.h
+++ b/llvm/include/llvm/Support/ErrorHandling.h
@@ -66,7 +66,7 @@ class StringRef;
///
/// If no error handler is installed the default is to print the message to
/// standard error, followed by a newline.
-/// After the error handler is called this function will call exit(1), it
+/// After the error handler is called this function will call abort(), it
/// does not return.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason,
bool gen_crash_diag = true);
@@ -103,8 +103,8 @@ 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.
+/// functions, this function might not terminate, e.g. the user
+/// defined error handler throws an exception, but it won't return.
///
/// Note: When throwing an exception in the bad alloc handler, make sure that
/// the following unwind succeeds, e.g. do not trigger additional allocations
@@ -113,7 +113,8 @@ void install_out_of_memory_new_handler();
/// 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);
+LLVM_ATTRIBUTE_NORETURN void report_bad_alloc_error(const char *Reason,
+ bool GenCrashDiag = true);
/// This function calls abort(), and prints the optional message to stderr.
/// Use the llvm_unreachable macro (that adds location info), instead of
@@ -127,7 +128,7 @@ llvm_unreachable_internal(const char *msg = nullptr, const char *file = nullptr,
/// In !NDEBUG builds, prints the message and location info to stderr.
/// In NDEBUG builds, becomes an optimizer hint that the current location
/// is not supposed to be reachable. On compilers that don't support
-/// such hints, prints a reduced message instead.
+/// such hints, prints a reduced message instead and aborts the program.
///
/// Use this instead of assert(0). It conveys intent more clearly and
/// allows compilers to omit some unnecessary code.
diff --git a/llvm/include/llvm/Support/ErrorOr.h b/llvm/include/llvm/Support/ErrorOr.h
index 8211f4d8a098b..1fbccc1d1e263 100644
--- a/llvm/include/llvm/Support/ErrorOr.h
+++ b/llvm/include/llvm/Support/ErrorOr.h
@@ -56,25 +56,25 @@ template<class T>
class ErrorOr {
template <class OtherT> friend class ErrorOr;
- static const bool isRef = std::is_reference<T>::value;
+ static constexpr bool isRef = std::is_reference<T>::value;
- using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
+ using wrap = std::reference_wrapper<std::remove_reference_t<T>>;
public:
- using storage_type = typename std::conditional<isRef, wrap, T>::type;
+ using storage_type = std::conditional_t<isRef, wrap, T>;
private:
- using reference = typename std::remove_reference<T>::type &;
- using const_reference = const typename std::remove_reference<T>::type &;
- using pointer = typename std::remove_reference<T>::type *;
- using const_pointer = const typename std::remove_reference<T>::type *;
+ using reference = std::remove_reference_t<T> &;
+ using const_reference = const std::remove_reference_t<T> &;
+ using pointer = std::remove_reference_t<T> *;
+ using const_pointer = const std::remove_reference_t<T> *;
public:
template <class E>
ErrorOr(E ErrorCode,
- typename std::enable_if<std::is_error_code_enum<E>::value ||
- std::is_error_condition_enum<E>::value,
- void *>::type = nullptr)
+ std::enable_if_t<std::is_error_code_enum<E>::value ||
+ std::is_error_condition_enum<E>::value,
+ void *> = nullptr)
: HasError(true) {
new (getErrorStorage()) std::error_code(make_error_code(ErrorCode));
}
@@ -85,8 +85,7 @@ public:
template <class OtherT>
ErrorOr(OtherT &&Val,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
- * = nullptr)
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr)
: HasError(false) {
new (getStorage()) storage_type(std::forward<OtherT>(Val));
}
@@ -96,18 +95,16 @@ public:
}
template <class OtherT>
- ErrorOr(
- const ErrorOr<OtherT> &Other,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
- nullptr) {
+ ErrorOr(const ErrorOr<OtherT> &Other,
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr) {
copyConstruct(Other);
}
template <class OtherT>
explicit ErrorOr(
const ErrorOr<OtherT> &Other,
- typename std::enable_if<
- !std::is_convertible<OtherT, const T &>::value>::type * = nullptr) {
+ std::enable_if_t<!std::is_convertible<OtherT, const T &>::value> * =
+ nullptr) {
copyConstruct(Other);
}
@@ -116,10 +113,8 @@ public:
}
template <class OtherT>
- ErrorOr(
- ErrorOr<OtherT> &&Other,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
- nullptr) {
+ ErrorOr(ErrorOr<OtherT> &&Other,
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr) {
moveConstruct(std::move(Other));
}
@@ -128,8 +123,7 @@ public:
template <class OtherT>
explicit ErrorOr(
ErrorOr<OtherT> &&Other,
- typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
- nullptr) {
+ std::enable_if_t<!std::is_convertible<OtherT, T>::value> * = nullptr) {
moveConstruct(std::move(Other));
}
@@ -266,9 +260,9 @@ private:
};
template <class T, class E>
-typename std::enable_if<std::is_error_code_enum<E>::value ||
- std::is_error_condition_enum<E>::value,
- bool>::type
+std::enable_if_t<std::is_error_code_enum<E>::value ||
+ std::is_error_condition_enum<E>::value,
+ bool>
operator==(const ErrorOr<T> &Err, E Code) {
return Err.getError() == Code;
}
diff --git a/llvm/include/llvm/Support/ExtensibleRTTI.h b/llvm/include/llvm/Support/ExtensibleRTTI.h
new file mode 100644
index 0000000000000..6b8510ce759f9
--- /dev/null
+++ b/llvm/include/llvm/Support/ExtensibleRTTI.h
@@ -0,0 +1,135 @@
+//===-- llvm/Support/ExtensibleRTTI.h - ExtensibleRTTI support --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// \file
+//
+// Defines an extensible RTTI mechanism designed to work with Casting.h.
+//
+// Extensible RTTI differs from LLVM's primary RTTI mechanism (see
+// llvm.org/docs/HowToSetUpLLVMStyleRTTI.html) by supporting open type
+// hierarchies, where new types can be added from outside libraries without
+// needing to change existing code. LLVM's primary RTTI mechanism should be
+// preferred where possible, but where open hierarchies are needed this system
+// can be used.
+//
+// The RTTIRoot class defines methods for comparing type ids. Implementations
+// of these methods can be injected into new classes using the RTTIExtends
+// class template.
+//
+// E.g.
+//
+// @code{.cpp}
+// class MyBaseClass : public RTTIExtends<MyBaseClass, RTTIRoot> {
+// public:
+// static char ID;
+// virtual void foo() = 0;
+// };
+//
+// class MyDerivedClass1 : public RTTIExtends<MyDerivedClass1, MyBaseClass> {
+// public:
+// static char ID;
+// void foo() override {}
+// };
+//
+// class MyDerivedClass2 : public RTTIExtends<MyDerivedClass2, MyBaseClass> {
+// public:
+// static char ID;
+// void foo() override {}
+// };
+//
+// char MyBaseClass::ID = 0;
+// char MyDerivedClass1::ID = 0;
+// char MyDerivedClass2:: ID = 0;
+//
+// void fn() {
+// std::unique_ptr<MyBaseClass> B = llvm::make_unique<MyDerivedClass1>();
+// llvm::outs() << isa<MyBaseClass>(B) << "\n"; // Outputs "1".
+// llvm::outs() << isa<MyDerivedClass1>(B) << "\n"; // Outputs "1".
+// llvm::outs() << isa<MyDerivedClass2>(B) << "\n"; // Outputs "0'.
+// }
+//
+// @endcode
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_EXTENSIBLERTTI_H
+#define LLVM_SUPPORT_EXTENSIBLERTTI_H
+
+namespace llvm {
+
+template <typename ThisT, typename ParentT> class RTTIExtends;
+
+/// Base class for the extensible RTTI hierarchy.
+///
+/// This class defines virtual methods, dynamicClassID and isA, that enable
+/// type comparisons.
+class RTTIRoot {
+public:
+ virtual ~RTTIRoot() = default;
+
+ /// Returns the class ID for this type.
+ static const void *classID() { return &ID; }
+
+ /// Returns the class ID for the dynamic type of this RTTIRoot instance.
+ virtual const void *dynamicClassID() const = 0;
+
+ /// Returns true if this class's ID matches the given class ID.
+ virtual bool isA(const void *const ClassID) const {
+ return ClassID == classID();
+ }
+
+ /// Check whether this instance is a subclass of QueryT.
+ template <typename QueryT>
+ bool isA() const { return isA(QueryT::classID()); }
+
+private:
+ virtual void anchor();
+
+ static char ID;
+};
+
+/// Inheritance utility for extensible RTTI.
+///
+/// Supports single inheritance only: A class can only have one
+/// ExtensibleRTTI-parent (i.e. a parent for which the isa<> test will work),
+/// though it can have many non-ExtensibleRTTI parents.
+///
+/// RTTIExtents uses CRTP so the first template argument to RTTIExtends is the
+/// newly introduced type, and the *second* argument is the parent class.
+///
+/// class MyType : public RTTIExtends<MyType, RTTIRoot> {
+/// public:
+/// static char ID;
+/// };
+///
+/// class MyDerivedType : public RTTIExtends<MyDerivedType, MyType> {
+/// public:
+/// static char ID;
+/// };
+///
+template <typename ThisT, typename ParentT>
+class RTTIExtends : public ParentT {
+public:
+ // Inherit constructors from ParentT.
+ using ParentT::ParentT;
+
+ static const void *classID() { return &ThisT::ID; }
+
+ const void *dynamicClassID() const override { return &ThisT::ID; }
+
+ bool isA(const void *const ClassID) const override {
+ return ClassID == classID() || ParentT::isA(ClassID);
+ }
+
+ static bool classof(const RTTIRoot *R) { return R->isA<ThisT>(); }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_EXTENSIBLERTTI_H
diff --git a/llvm/include/llvm/Support/FileCheck.h b/llvm/include/llvm/Support/FileCheck.h
index 429e36cfcbb5f..2f0e641394d57 100644
--- a/llvm/include/llvm/Support/FileCheck.h
+++ b/llvm/include/llvm/Support/FileCheck.h
@@ -24,13 +24,15 @@ namespace llvm {
/// Contains info about various FileCheck options.
struct FileCheckRequest {
- std::vector<std::string> CheckPrefixes;
+ std::vector<StringRef> CheckPrefixes;
+ std::vector<StringRef> CommentPrefixes;
bool NoCanonicalizeWhiteSpace = false;
- std::vector<std::string> ImplicitCheckNot;
- std::vector<std::string> GlobalDefines;
+ std::vector<StringRef> ImplicitCheckNot;
+ std::vector<StringRef> GlobalDefines;
bool AllowEmptyInput = false;
bool MatchFullLines = false;
bool IgnoreCase = false;
+ bool IsDefaultCheckPrefix = false;
bool EnableVarScope = false;
bool AllowDeprecatedDagOverlap = false;
bool Verbose = false;
@@ -52,6 +54,7 @@ enum FileCheckKind {
CheckDAG,
CheckLabel,
CheckEmpty,
+ CheckComment,
/// Indicates the pattern only matches the end of file. This is used for
/// trailing CHECK-NOTs.
@@ -87,7 +90,7 @@ struct FileCheckDiag {
/// What is the FileCheck directive for this diagnostic?
Check::FileCheckType CheckTy;
/// Where is the FileCheck directive for this diagnostic?
- unsigned CheckLine, CheckCol;
+ SMLoc CheckLoc;
/// What type of match result does this diagnostic describe?
///
/// A directive's supplied pattern is said to be either expected or excluded
@@ -159,7 +162,13 @@ public:
///
/// Only expected strings whose prefix is one of those listed in \p PrefixRE
/// are recorded. \returns true in case of an error, false otherwise.
- bool readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE);
+ ///
+ /// If \p ImpPatBufferIDRange, then the range (inclusive start, exclusive end)
+ /// of IDs for source buffers added to \p SM for implicit patterns are
+ /// recorded in it. The range is empty if there are none.
+ bool
+ readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
+ std::pair<unsigned, unsigned> *ImpPatBufferIDRange = nullptr);
bool ValidateCheckPrefixes();
diff --git a/llvm/include/llvm/Support/FileCollector.h b/llvm/include/llvm/Support/FileCollector.h
index 079fe3efab9d3..2b5e9c669b680 100644
--- a/llvm/include/llvm/Support/FileCollector.h
+++ b/llvm/include/llvm/Support/FileCollector.h
@@ -12,23 +12,44 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/Support/VirtualFileSystem.h"
-
#include <mutex>
+#include <string>
namespace llvm {
-
-/// Collects files into a directory and generates a mapping that can be used by
-/// the VFS.
+class FileCollectorFileSystem;
+class Twine;
+
+/// Captures file system interaction and generates data to be later replayed
+/// with the RedirectingFileSystem.
+///
+/// For any file that gets accessed we eventually create:
+/// - a copy of the file inside Root
+/// - a record in RedirectingFileSystem mapping that maps:
+/// current real path -> path to the copy in Root
+///
+/// That intent is that later when the mapping is used by RedirectingFileSystem
+/// it simulates the state of FS that we collected.
+///
+/// We generate file copies and mapping lazily - see writeMapping and copyFiles.
+/// We don't try to capture the state of the file at the exact time when it's
+/// accessed. Files might get changed, deleted ... we record only the "final"
+/// state.
+///
+/// In order to preserve the relative topology of files we use their real paths
+/// as relative paths inside of the Root.
class FileCollector {
public:
+ /// \p Root is the directory where collected files are will be stored.
+ /// \p OverlayRoot is VFS mapping root.
+ /// \p Root directory gets created in copyFiles unless it already exists.
FileCollector(std::string Root, std::string OverlayRoot);
void addFile(const Twine &file);
+ void addDirectory(const Twine &Dir);
/// Write the yaml mapping (for the VFS) to the given file.
- std::error_code writeMapping(StringRef mapping_file);
+ std::error_code writeMapping(StringRef MappingFile);
/// Copy the files into the root directory.
///
@@ -37,14 +58,14 @@ public:
/// removed after it was added to the mapping.
std::error_code copyFiles(bool StopOnError = true);
- /// Create a VFS that collects all the paths that might be looked at by the
- /// file system accesses.
+ /// Create a VFS that uses \p Collector to collect files accessed via \p
+ /// BaseFS.
static IntrusiveRefCntPtr<vfs::FileSystem>
createCollectorVFS(IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
std::shared_ptr<FileCollector> Collector);
private:
- void addFileImpl(StringRef SrcPath);
+ friend FileCollectorFileSystem;
bool markAsSeen(StringRef Path) {
if (Path.empty())
@@ -55,18 +76,27 @@ private:
bool getRealPath(StringRef SrcPath, SmallVectorImpl<char> &Result);
void addFileToMapping(StringRef VirtualPath, StringRef RealPath) {
- VFSWriter.addFileMapping(VirtualPath, RealPath);
+ if (sys::fs::is_directory(VirtualPath))
+ VFSWriter.addDirectoryMapping(VirtualPath, RealPath);
+ else
+ VFSWriter.addFileMapping(VirtualPath, RealPath);
}
protected:
- /// Synchronizes adding files.
+ void addFileImpl(StringRef SrcPath);
+
+ llvm::vfs::directory_iterator
+ addDirectoryImpl(const llvm::Twine &Dir,
+ IntrusiveRefCntPtr<vfs::FileSystem> FS, std::error_code &EC);
+
+ /// Synchronizes access to Seen, VFSWriter and SymlinkMap.
std::mutex Mutex;
- /// The root directory where files are copied.
- std::string Root;
+ /// The directory where collected files are copied to in copyFiles().
+ const std::string Root;
/// The root directory where the VFS overlay lives.
- std::string OverlayRoot;
+ const std::string OverlayRoot;
/// Tracks already seen files so they can be skipped.
StringSet<> Seen;
diff --git a/llvm/include/llvm/Support/FileOutputBuffer.h b/llvm/include/llvm/Support/FileOutputBuffer.h
index bdc1425d43617..8eb36d0034ad4 100644
--- a/llvm/include/llvm/Support/FileOutputBuffer.h
+++ b/llvm/include/llvm/Support/FileOutputBuffer.h
@@ -13,11 +13,9 @@
#ifndef LLVM_SUPPORT_FILEOUTPUTBUFFER_H
#define LLVM_SUPPORT_FILEOUTPUTBUFFER_H
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
namespace llvm {
/// FileOutputBuffer - This interface provides simple way to create an in-memory
diff --git a/llvm/include/llvm/Support/FormatAdapters.h b/llvm/include/llvm/Support/FormatAdapters.h
index a0e8cc4391912..495205d11748b 100644
--- a/llvm/include/llvm/Support/FormatAdapters.h
+++ b/llvm/include/llvm/Support/FormatAdapters.h
@@ -9,7 +9,6 @@
#ifndef LLVM_SUPPORT_FORMATADAPTERS_H
#define LLVM_SUPPORT_FORMATADAPTERS_H
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatCommon.h"
@@ -35,7 +34,7 @@ public:
: FormatAdapter<T>(std::forward<T>(Item)), Where(Where), Amount(Amount),
Fill(Fill) {}
- void format(llvm::raw_ostream &Stream, StringRef Style) {
+ void format(llvm::raw_ostream &Stream, StringRef Style) override {
auto Adapter = detail::build_format_adapter(std::forward<T>(this->Item));
FmtAlign(Adapter, Where, Amount, Fill).format(Stream, Style);
}
@@ -49,7 +48,7 @@ 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) {
+ void format(llvm::raw_ostream &Stream, StringRef Style) override {
auto Adapter = detail::build_format_adapter(std::forward<T>(this->Item));
Stream.indent(Left);
Adapter.format(Stream, Style);
@@ -64,7 +63,7 @@ public:
RepeatAdapter(T &&Item, size_t Count)
: FormatAdapter<T>(std::forward<T>(Item)), Count(Count) {}
- void format(llvm::raw_ostream &Stream, StringRef Style) {
+ void format(llvm::raw_ostream &Stream, StringRef Style) override {
auto Adapter = detail::build_format_adapter(std::forward<T>(this->Item));
for (size_t I = 0; I < Count; ++I) {
Adapter.format(Stream, Style);
@@ -77,7 +76,9 @@ 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; }
+ void format(llvm::raw_ostream &Stream, StringRef Style) override {
+ Stream << Item;
+ }
};
}
diff --git a/llvm/include/llvm/Support/FormatProviders.h b/llvm/include/llvm/Support/FormatProviders.h
index 629a4845716a4..c31481a292595 100644
--- a/llvm/include/llvm/Support/FormatProviders.h
+++ b/llvm/include/llvm/Support/FormatProviders.h
@@ -124,7 +124,7 @@ protected:
template <typename T>
struct format_provider<
- T, typename std::enable_if<detail::use_integral_formatter<T>::value>::type>
+ T, std::enable_if_t<detail::use_integral_formatter<T>::value>>
: public detail::HelperFunctions {
private:
public:
@@ -173,7 +173,7 @@ public:
/// cases indicates the minimum number of nibbles to print.
template <typename T>
struct format_provider<
- T, typename std::enable_if<detail::use_pointer_formatter<T>::value>::type>
+ T, std::enable_if_t<detail::use_pointer_formatter<T>::value>>
: public detail::HelperFunctions {
private:
public:
@@ -198,7 +198,7 @@ public:
template <typename T>
struct format_provider<
- T, typename std::enable_if<detail::use_string_formatter<T>::value>::type> {
+ T, std::enable_if_t<detail::use_string_formatter<T>::value>> {
static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
size_t N = StringRef::npos;
if (!Style.empty() && Style.getAsInteger(10, N)) {
@@ -230,8 +230,8 @@ template <> struct format_provider<Twine> {
/// character. Otherwise, it is treated as an integer options string.
///
template <typename T>
-struct format_provider<
- T, typename std::enable_if<detail::use_char_formatter<T>::value>::type> {
+struct format_provider<T,
+ std::enable_if_t<detail::use_char_formatter<T>::value>> {
static void format(const char &V, llvm::raw_ostream &Stream,
StringRef Style) {
if (Style.empty())
@@ -296,8 +296,8 @@ template <> struct format_provider<bool> {
/// else.
template <typename T>
-struct format_provider<
- T, typename std::enable_if<detail::use_double_formatter<T>::value>::type>
+struct format_provider<T,
+ std::enable_if_t<detail::use_double_formatter<T>::value>>
: public detail::HelperFunctions {
static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
FloatStyle S;
diff --git a/llvm/include/llvm/Support/FormatVariadic.h b/llvm/include/llvm/Support/FormatVariadic.h
index 86a9d30cc138d..dfafc3ccb44e4 100644
--- a/llvm/include/llvm/Support/FormatVariadic.h
+++ b/llvm/include/llvm/Support/FormatVariadic.h
@@ -25,6 +25,7 @@
#ifndef LLVM_SUPPORT_FORMATVARIADIC_H
#define LLVM_SUPPORT_FORMATVARIADIC_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
@@ -63,23 +64,8 @@ struct ReplacementItem {
class formatv_object_base {
protected:
- // The parameters are stored in a std::tuple, which does not provide runtime
- // indexing capabilities. In order to enable runtime indexing, we use this
- // structure to put the parameters into a std::vector. Since the parameters
- // are not all the same type, we use some type-erasure by wrapping the
- // parameters in a template class that derives from a non-template superclass.
- // Essentially, we are converting a std::tuple<Derived<Ts...>> to a
- // std::vector<Base*>.
- struct create_adapters {
- template <typename... Ts>
- std::vector<detail::format_adapter *> operator()(Ts &... Items) {
- return std::vector<detail::format_adapter *>{&Items...};
- }
- };
-
StringRef Fmt;
- std::vector<detail::format_adapter *> Adapters;
- std::vector<ReplacementItem> Replacements;
+ ArrayRef<detail::format_adapter *> Adapters;
static bool consumeFieldLayout(StringRef &Spec, AlignStyle &Where,
size_t &Align, char &Pad);
@@ -87,23 +73,16 @@ protected:
static std::pair<ReplacementItem, StringRef>
splitLiteralAndReplacement(StringRef Fmt);
-public:
- formatv_object_base(StringRef Fmt, std::size_t ParamCount)
- : Fmt(Fmt), Replacements(parseFormatString(Fmt)) {
- Adapters.reserve(ParamCount);
- }
+ formatv_object_base(StringRef Fmt,
+ ArrayRef<detail::format_adapter *> Adapters)
+ : Fmt(Fmt), Adapters(Adapters) {}
formatv_object_base(formatv_object_base const &rhs) = delete;
+ formatv_object_base(formatv_object_base &&rhs) = default;
- formatv_object_base(formatv_object_base &&rhs)
- : Fmt(std::move(rhs.Fmt)),
- Adapters(), // Adapters are initialized by formatv_object
- Replacements(std::move(rhs.Replacements)) {
- Adapters.reserve(rhs.Adapters.size());
- };
-
+public:
void format(raw_ostream &S) const {
- for (auto &R : Replacements) {
+ for (auto &R : parseFormatString(Fmt)) {
if (R.Type == ReplacementType::Empty)
continue;
if (R.Type == ReplacementType::Literal) {
@@ -121,7 +100,7 @@ public:
Align.format(S, R.Options);
}
}
- static std::vector<ReplacementItem> parseFormatString(StringRef Fmt);
+ static SmallVector<ReplacementItem, 2> parseFormatString(StringRef Fmt);
static Optional<ReplacementItem> parseReplacementItem(StringRef Spec);
@@ -150,12 +129,29 @@ template <typename Tuple> class formatv_object : public formatv_object_base {
// of the parameters, we have to own the storage for the parameters here, and
// have the base class store type-erased pointers into this tuple.
Tuple Parameters;
+ std::array<detail::format_adapter *, std::tuple_size<Tuple>::value>
+ ParameterPointers;
+
+ // The parameters are stored in a std::tuple, which does not provide runtime
+ // indexing capabilities. In order to enable runtime indexing, we use this
+ // structure to put the parameters into a std::array. Since the parameters
+ // are not all the same type, we use some type-erasure by wrapping the
+ // parameters in a template class that derives from a non-template superclass.
+ // Essentially, we are converting a std::tuple<Derived<Ts...>> to a
+ // std::array<Base*>.
+ struct create_adapters {
+ template <typename... Ts>
+ std::array<detail::format_adapter *, std::tuple_size<Tuple>::value>
+ operator()(Ts &... Items) {
+ return {{&Items...}};
+ }
+ };
public:
formatv_object(StringRef Fmt, Tuple &&Params)
- : formatv_object_base(Fmt, std::tuple_size<Tuple>::value),
+ : formatv_object_base(Fmt, ParameterPointers),
Parameters(std::move(Params)) {
- Adapters = apply_tuple(create_adapters(), Parameters);
+ ParameterPointers = apply_tuple(create_adapters(), Parameters);
}
formatv_object(formatv_object const &rhs) = delete;
@@ -163,7 +159,8 @@ public:
formatv_object(formatv_object &&rhs)
: formatv_object_base(std::move(rhs)),
Parameters(std::move(rhs.Parameters)) {
- Adapters = apply_tuple(create_adapters(), Parameters);
+ ParameterPointers = apply_tuple(create_adapters(), Parameters);
+ Adapters = ParameterPointers;
}
};
diff --git a/llvm/include/llvm/Support/FormatVariadicDetails.h b/llvm/include/llvm/Support/FormatVariadicDetails.h
index e3c185134daa4..d5e67b756a472 100644
--- a/llvm/include/llvm/Support/FormatVariadicDetails.h
+++ b/llvm/include/llvm/Support/FormatVariadicDetails.h
@@ -36,7 +36,7 @@ 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);
+ format_provider<std::decay_t<T>>::format(Item, S, Options);
}
};
@@ -59,7 +59,7 @@ template <typename T> class missing_format_adapter;
//
template <class T> class has_FormatProvider {
public:
- using Decayed = typename std::decay<T>::type;
+ using Decayed = std::decay_t<T>;
typedef void (*Signature_format)(const Decayed &, llvm::raw_ostream &,
StringRef);
@@ -75,14 +75,14 @@ public:
// Test if raw_ostream& << T -> raw_ostream& is findable via ADL.
template <class T> class has_StreamOperator {
public:
- using ConstRefT = const typename std::decay<T>::type &;
+ using ConstRefT = const std::decay_t<T> &;
template <typename U>
- static char test(typename std::enable_if<
- std::is_same<decltype(std::declval<llvm::raw_ostream &>()
- << std::declval<U>()),
- llvm::raw_ostream &>::value,
- int *>::type);
+ static char test(
+ std::enable_if_t<std::is_same<decltype(std::declval<llvm::raw_ostream &>()
+ << std::declval<U>()),
+ llvm::raw_ostream &>::value,
+ int *>);
template <typename U> static double test(...);
@@ -95,8 +95,8 @@ 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> {};
+ std::is_base_of<format_adapter, std::remove_reference_t<T>>::value> {
+};
// Simple template that decides whether a type T should use the format_provider
// based format() invocation. The member function takes priority, so this test
@@ -127,34 +127,32 @@ struct uses_missing_provider
};
template <typename T>
-typename std::enable_if<uses_format_member<T>::value, T>::type
+std::enable_if_t<uses_format_member<T>::value, T>
build_format_adapter(T &&Item) {
return std::forward<T>(Item);
}
template <typename T>
-typename std::enable_if<uses_format_provider<T>::value,
- provider_format_adapter<T>>::type
+std::enable_if_t<uses_format_provider<T>::value, provider_format_adapter<T>>
build_format_adapter(T &&Item) {
return provider_format_adapter<T>(std::forward<T>(Item));
}
template <typename T>
-typename std::enable_if<uses_stream_operator<T>::value,
- stream_operator_format_adapter<T>>::type
+std::enable_if_t<uses_stream_operator<T>::value,
+ stream_operator_format_adapter<T>>
build_format_adapter(T &&Item) {
// If the caller passed an Error by value, then stream_operator_format_adapter
// would be responsible for consuming it.
// Make the caller opt into this by calling fmt_consume().
static_assert(
- !std::is_same<llvm::Error, typename std::remove_cv<T>::type>::value,
+ !std::is_same<llvm::Error, std::remove_cv_t<T>>::value,
"llvm::Error-by-value must be wrapped in fmt_consume() for formatv");
return stream_operator_format_adapter<T>(std::forward<T>(Item));
}
template <typename T>
-typename std::enable_if<uses_missing_provider<T>::value,
- missing_format_adapter<T>>::type
+std::enable_if_t<uses_missing_provider<T>::value, missing_format_adapter<T>>
build_format_adapter(T &&Item) {
return missing_format_adapter<T>();
}
diff --git a/llvm/include/llvm/Support/FormattedStream.h b/llvm/include/llvm/Support/FormattedStream.h
index b49c8d86531db..5f937cfa79840 100644
--- a/llvm/include/llvm/Support/FormattedStream.h
+++ b/llvm/include/llvm/Support/FormattedStream.h
@@ -14,6 +14,7 @@
#ifndef LLVM_SUPPORT_FORMATTEDSTREAM_H
#define LLVM_SUPPORT_FORMATTEDSTREAM_H
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
#include <utility>
@@ -21,8 +22,11 @@ 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.
-///
+/// boundaries and querying the number of lines written to the stream. This
+/// assumes that the contents of the stream is valid UTF-8 encoded text. This
+/// doesn't attempt to handle everything Unicode can do (combining characters,
+/// right-to-left markers, etc), but should cover the cases likely to appear in
+/// source code or diagnostic messages.
class formatted_raw_ostream : public raw_ostream {
/// TheStream - The real stream we output to. We set it to be
/// unbuffered, since we're already doing our own buffering.
@@ -40,6 +44,14 @@ class formatted_raw_ostream : public raw_ostream {
///
const char *Scanned;
+ /// PartialUTF8Char - Either empty or a prefix of a UTF-8 code unit sequence
+ /// for a Unicode scalar value which should be prepended to the buffer for the
+ /// next call to ComputePosition. This is needed when the buffer is flushed
+ /// when it ends part-way through the UTF-8 encoding of a Unicode scalar
+ /// value, so that we can compute the display width of the character once we
+ /// have the rest of it.
+ SmallString<4> PartialUTF8Char;
+
void write_impl(const char *Ptr, size_t Size) override;
/// current_pos - Return the current position within the stream,
@@ -52,10 +64,16 @@ class formatted_raw_ostream : public raw_ostream {
}
/// ComputePosition - Examine the given output buffer and figure out the new
- /// position after output.
- ///
+ /// position after output. This is safe to call multiple times on the same
+ /// buffer, as it records the most recently scanned character and resumes from
+ /// there when the buffer has not been flushed.
void ComputePosition(const char *Ptr, size_t size);
+ /// UpdatePosition - scan the characters in [Ptr, Ptr+Size), and update the
+ /// line and column numbers. Unlike ComputePosition, this must be called
+ /// exactly once on each region of the buffer.
+ void UpdatePosition(const char *Ptr, size_t Size);
+
void setStream(raw_ostream &Stream) {
releaseStream();
@@ -105,11 +123,17 @@ public:
/// \param NewCol - The column to move to.
formatted_raw_ostream &PadToColumn(unsigned NewCol);
- /// getColumn - Return the column number
- unsigned getColumn() { return Position.first; }
+ unsigned getColumn() {
+ // Calculate current position, taking buffer contents into account.
+ ComputePosition(getBufferStart(), GetNumBytesInBuffer());
+ return Position.first;
+ }
- /// getLine - Return the line number
- unsigned getLine() { return Position.second; }
+ unsigned getLine() {
+ // Calculate current position, taking buffer contents into account.
+ ComputePosition(getBufferStart(), GetNumBytesInBuffer());
+ return Position.second;
+ }
raw_ostream &resetColor() override {
TheStream->resetColor();
diff --git a/llvm/include/llvm/Support/GenericDomTree.h b/llvm/include/llvm/Support/GenericDomTree.h
index 2545a075062a1..10e591a69d369 100644
--- a/llvm/include/llvm/Support/GenericDomTree.h
+++ b/llvm/include/llvm/Support/GenericDomTree.h
@@ -25,7 +25,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
-#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
@@ -78,18 +77,25 @@ template <class NodeT> class DomTreeNodeBase {
const_iterator begin() const { return Children.begin(); }
const_iterator end() const { return Children.end(); }
+ DomTreeNodeBase *const &back() const { return Children.back(); }
+ DomTreeNodeBase *&back() { return Children.back(); }
+
+ iterator_range<iterator> children() { return make_range(begin(), end()); }
+ iterator_range<const_iterator> children() const {
+ return make_range(begin(), end());
+ }
+
NodeT *getBlock() const { return TheBB; }
DomTreeNodeBase *getIDom() const { return IDom; }
unsigned getLevel() const { return Level; }
- const std::vector<DomTreeNodeBase *> &getChildren() const { return Children; }
-
std::unique_ptr<DomTreeNodeBase> addChild(
std::unique_ptr<DomTreeNodeBase> C) {
Children.push_back(C.get());
return C;
}
+ bool isLeaf() const { return Children.empty(); }
size_t getNumChildren() const { return Children.size(); }
void clearAllChildren() { Children.clear(); }
@@ -225,7 +231,7 @@ class DominatorTreeBase {
using ParentPtr = decltype(std::declval<NodeT *>()->getParent());
static_assert(std::is_pointer<ParentPtr>::value,
"Currently NodeT's parent must be a pointer type");
- using ParentType = typename std::remove_pointer<ParentPtr>::type;
+ using ParentType = std::remove_pointer_t<ParentPtr>;
static constexpr bool IsPostDominator = IsPostDom;
using UpdateType = cfg::Update<NodePtr>;
@@ -277,11 +283,27 @@ protected:
DominatorTreeBase(const DominatorTreeBase &) = delete;
DominatorTreeBase &operator=(const DominatorTreeBase &) = delete;
- /// getRoots - Return the root blocks of the current CFG. This may include
- /// multiple blocks if we are computing post dominators. For forward
- /// dominators, this will always be a single block (the entry node).
+ /// Iteration over roots.
///
- const SmallVectorImpl<NodeT *> &getRoots() const { return Roots; }
+ /// This may include multiple blocks if we are computing post dominators.
+ /// For forward dominators, this will always be a single block (the entry
+ /// block).
+ using root_iterator = typename SmallVectorImpl<NodeT *>::iterator;
+ using const_root_iterator = typename SmallVectorImpl<NodeT *>::const_iterator;
+
+ root_iterator root_begin() { return Roots.begin(); }
+ const_root_iterator root_begin() const { return Roots.begin(); }
+ root_iterator root_end() { return Roots.end(); }
+ const_root_iterator root_end() const { return Roots.end(); }
+
+ size_t root_size() const { return Roots.size(); }
+
+ iterator_range<root_iterator> roots() {
+ return make_range(root_begin(), root_end());
+ }
+ iterator_range<const_root_iterator> roots() const {
+ return make_range(root_begin(), root_end());
+ }
/// isPostDominator - Returns true if analysis based of postdoms
///
@@ -319,8 +341,6 @@ protected:
return false;
}
- void releaseMemory() { reset(); }
-
/// getNode - return the (Post)DominatorTree node for the specified basic
/// block. This is the same as using operator[] on this class. The result
/// may (but is not required to) be null for a forward (backwards)
@@ -570,8 +590,7 @@ protected:
DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB);
assert(IDomNode && "Not immediate dominator specified for block!");
DFSInfoValid = false;
- return (DomTreeNodes[BB] = IDomNode->addChild(
- std::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get();
+ return createChild(BB, IDomNode);
}
/// Add a new node to the forward dominator tree and make it a new root.
@@ -584,8 +603,7 @@ protected:
assert(!this->isPostDominator() &&
"Cannot change root of post-dominator tree");
DFSInfoValid = false;
- DomTreeNodeBase<NodeT> *NewNode = (DomTreeNodes[BB] =
- std::make_unique<DomTreeNodeBase<NodeT>>(BB, nullptr)).get();
+ DomTreeNodeBase<NodeT> *NewNode = createNode(BB);
if (Roots.empty()) {
addRoot(BB);
} else {
@@ -620,7 +638,7 @@ protected:
void eraseNode(NodeT *BB) {
DomTreeNodeBase<NodeT> *Node = getNode(BB);
assert(Node && "Removing node that isn't in dominator tree.");
- assert(Node->getChildren().empty() && "Node is not a leaf node.");
+ assert(Node->isLeaf() && "Node is not a leaf node.");
DFSInfoValid = false;
@@ -754,9 +772,6 @@ public:
return DomTreeBuilder::Verify(*this, VL);
}
-protected:
- void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
-
void reset() {
DomTreeNodes.clear();
Roots.clear();
@@ -766,6 +781,21 @@ protected:
SlowQueries = 0;
}
+protected:
+ void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
+
+ DomTreeNodeBase<NodeT> *createChild(NodeT *BB, DomTreeNodeBase<NodeT> *IDom) {
+ return (DomTreeNodes[BB] = IDom->addChild(
+ std::make_unique<DomTreeNodeBase<NodeT>>(BB, IDom)))
+ .get();
+ }
+
+ DomTreeNodeBase<NodeT> *createNode(NodeT *BB) {
+ return (DomTreeNodes[BB] =
+ std::make_unique<DomTreeNodeBase<NodeT>>(BB, nullptr))
+ .get();
+ }
+
// NewBB is split and now it has one successor. Update dominator tree to
// reflect this change.
template <class N>
diff --git a/llvm/include/llvm/Support/GenericDomTreeConstruction.h b/llvm/include/llvm/Support/GenericDomTreeConstruction.h
index 7c0278e8770ee..464de4e2b3ba1 100644
--- a/llvm/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/llvm/include/llvm/Support/GenericDomTreeConstruction.h
@@ -7,11 +7,11 @@
//===----------------------------------------------------------------------===//
/// \file
///
-/// Generic dominator tree construction - This file provides routines to
+/// Generic dominator tree construction - this file provides routines to
/// construct immediate dominator information for a flow-graph based on the
/// Semi-NCA algorithm described in this dissertation:
///
-/// Linear-Time Algorithms for Dominators and Related Problems
+/// [1] Linear-Time Algorithms for Dominators and Related Problems
/// Loukas Georgiadis, Princeton University, November 2005, pp. 21-23:
/// ftp://ftp.cs.princeton.edu/reports/2005/737.pdf
///
@@ -20,13 +20,15 @@
///
/// O(n^2) worst cases happen when the computation of nearest common ancestors
/// requires O(n) average time, which is very unlikely in real world. If this
-/// ever turns out to be an issue, consider implementing a hybrid algorithm.
+/// ever turns out to be an issue, consider implementing a hybrid algorithm
+/// that uses SLT to perform full constructions and SemiNCA for incremental
+/// updates.
///
/// The file uses the Depth Based Search algorithm to perform incremental
/// updates (insertion and deletions). The implemented algorithm is based on
/// this publication:
///
-/// An Experimental Study of Dynamic Dominators
+/// [2] An Experimental Study of Dynamic Dominators
/// Loukas Georgiadis, et al., April 12 2016, pp. 5-7, 9-10:
/// https://arxiv.org/pdf/1604.02711.pdf
///
@@ -35,7 +37,6 @@
#ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
#define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
-#include <queue>
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DepthFirstIterator.h"
@@ -43,6 +44,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GenericDomTree.h"
+#include <queue>
#define DEBUG_TYPE "dom-tree-builder"
@@ -185,9 +187,7 @@ struct SemiNCAInfo {
// Add a new tree node for this NodeT, and link it as a child of
// IDomNode
- return (DT.DomTreeNodes[BB] = IDomNode->addChild(
- std::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode)))
- .get();
+ return DT.createChild(BB, IDomNode);
}
static bool AlwaysDescend(NodePtr, NodePtr) { return true; }
@@ -585,9 +585,7 @@ struct SemiNCAInfo {
// all real exits (including multiple exit blocks, infinite loops).
NodePtr Root = IsPostDom ? nullptr : DT.Roots[0];
- DT.RootNode = (DT.DomTreeNodes[Root] =
- std::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr))
- .get();
+ DT.RootNode = DT.createNode(Root);
SNCA.attachNewSubtree(DT, DT.RootNode);
}
@@ -597,8 +595,6 @@ struct SemiNCAInfo {
// Loop over all of the discovered blocks in the function...
for (size_t i = 1, e = NumToNode.size(); i != e; ++i) {
NodePtr W = NumToNode[i];
- LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node "
- << BlockNamePrinter(W) << "\n");
// Don't replace this with 'count', the insertion side effect is important
if (DT.DomTreeNodes[W]) continue; // Haven't calculated this node yet?
@@ -610,8 +606,7 @@ struct SemiNCAInfo {
// Add a new tree node for this BasicBlock, and link it as a child of
// IDomNode.
- DT.DomTreeNodes[W] = IDomNode->addChild(
- std::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode));
+ DT.createChild(W, IDomNode);
}
}
@@ -661,10 +656,7 @@ struct SemiNCAInfo {
// The unreachable node becomes a new root -- a tree node for it.
TreeNodePtr VirtualRoot = DT.getNode(nullptr);
- FromTN =
- (DT.DomTreeNodes[From] = VirtualRoot->addChild(
- std::make_unique<DomTreeNodeBase<NodeT>>(From, VirtualRoot)))
- .get();
+ FromTN = DT.createChild(From, VirtualRoot);
DT.Roots.push_back(From);
}
@@ -732,7 +724,7 @@ struct SemiNCAInfo {
LLVM_DEBUG(dbgs() << "Roots are different in updated trees\n"
<< "The entire tree needs to be rebuilt\n");
// It may be possible to update the tree without recalculating it, but
- // we do not know yet how to do it, and it happens rarely in practise.
+ // we do not know yet how to do it, and it happens rarely in practice.
CalculateFromScratch(DT, BUI);
}
}
@@ -757,13 +749,13 @@ struct SemiNCAInfo {
LLVM_DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n");
const unsigned NCDLevel = NCD->getLevel();
- // Based on Lemma 2.5 from the second paper, after insertion of (From,To), v
- // is affected iff depth(NCD)+1 < depth(v) && a path P from To to v exists
- // where every w on P s.t. depth(v) <= depth(w)
+ // Based on Lemma 2.5 from [2], after insertion of (From,To), v is affected
+ // iff depth(NCD)+1 < depth(v) && a path P from To to v exists where every
+ // w on P s.t. depth(v) <= depth(w)
//
// This reduces to a widest path problem (maximizing the depth of the
// minimum vertex in the path) which can be solved by a modified version of
- // Dijkstra with a bucket queue (named depth-based search in the paper).
+ // Dijkstra with a bucket queue (named depth-based search in [2]).
// To is in the path, so depth(NCD)+1 < depth(v) <= depth(To). Nothing
// affected if this does not hold.
@@ -957,7 +949,7 @@ struct SemiNCAInfo {
<< BlockNamePrinter(ToIDom) << "\n");
// To remains reachable after deletion.
- // (Based on the caption under Figure 4. from the second paper.)
+ // (Based on the caption under Figure 4. from [2].)
if (FromTN != ToIDom || HasProperSupport(DT, BUI, ToTN))
DeleteReachable(DT, BUI, FromTN, ToTN);
else
@@ -976,7 +968,7 @@ struct SemiNCAInfo {
LLVM_DEBUG(dbgs() << "\tRebuilding subtree\n");
// Find the top of the subtree that needs to be rebuilt.
- // (Based on the lemma 2.6 from the second paper.)
+ // (Based on the lemma 2.6 from [2].)
const NodePtr ToIDom =
DT.findNearestCommonDominator(FromTN->getBlock(), ToTN->getBlock());
assert(ToIDom || DT.isPostDominator());
@@ -1008,7 +1000,7 @@ struct SemiNCAInfo {
}
// Checks if a node has proper support, as defined on the page 3 and later
- // explained on the page 7 of the second paper.
+ // explained on the page 7 of [2].
static bool HasProperSupport(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr TN) {
LLVM_DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN)
@@ -1033,7 +1025,7 @@ struct SemiNCAInfo {
}
// Handle deletions that make destination node unreachable.
- // (Based on the lemma 2.7 from the second paper.)
+ // (Based on the lemma 2.7 from the [2].)
static void DeleteUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr ToTN) {
LLVM_DEBUG(dbgs() << "Deleting unreachable subtree "
@@ -1372,7 +1364,7 @@ struct SemiNCAInfo {
if (!DT.DFSInfoValid || !DT.Parent)
return true;
- const NodePtr RootBB = IsPostDom ? nullptr : DT.getRoots()[0];
+ const NodePtr RootBB = IsPostDom ? nullptr : *DT.root_begin();
const TreeNodePtr Root = DT.getNode(RootBB);
auto PrintNodeAndDFSNums = [](const TreeNodePtr TN) {
@@ -1396,7 +1388,7 @@ struct SemiNCAInfo {
const TreeNodePtr Node = NodeToTN.second.get();
// Handle tree leaves.
- if (Node->getChildren().empty()) {
+ if (Node->isLeaf()) {
if (Node->getDFSNumIn() + 1 != Node->getDFSNumOut()) {
errs() << "Tree leaf should have DFSOut = DFSIn + 1:\n\t";
PrintNodeAndDFSNums(Node);
@@ -1493,9 +1485,9 @@ struct SemiNCAInfo {
// LEFT, and thus, LEFT is really an ancestor (in the dominator tree) of
// RIGHT, not a sibling.
- // It is possible to verify the parent and sibling properties in
- // linear time, but the algorithms are complex. Instead, we do it in a
- // straightforward N^2 and N^3 way below, using direct path reachability.
+ // It is possible to verify the parent and sibling properties in linear time,
+ // but the algorithms are complex. Instead, we do it in a straightforward
+ // N^2 and N^3 way below, using direct path reachability.
// Checks if the tree has the parent property: if for all edges from V to W in
// the input graph, such that V is reachable, the parent of W in the tree is
@@ -1508,7 +1500,8 @@ struct SemiNCAInfo {
for (auto &NodeToTN : DT.DomTreeNodes) {
const TreeNodePtr TN = NodeToTN.second.get();
const NodePtr BB = TN->getBlock();
- if (!BB || TN->getChildren().empty()) continue;
+ if (!BB || TN->isLeaf())
+ continue;
LLVM_DEBUG(dbgs() << "Verifying parent property of node "
<< BlockNamePrinter(TN) << "\n");
@@ -1517,7 +1510,7 @@ struct SemiNCAInfo {
return From != BB && To != BB;
});
- for (TreeNodePtr Child : TN->getChildren())
+ for (TreeNodePtr Child : TN->children())
if (NodeToInfo.count(Child->getBlock()) != 0) {
errs() << "Child " << BlockNamePrinter(Child)
<< " reachable after its parent " << BlockNamePrinter(BB)
@@ -1541,17 +1534,17 @@ struct SemiNCAInfo {
for (auto &NodeToTN : DT.DomTreeNodes) {
const TreeNodePtr TN = NodeToTN.second.get();
const NodePtr BB = TN->getBlock();
- if (!BB || TN->getChildren().empty()) continue;
+ if (!BB || TN->isLeaf())
+ continue;
- const auto &Siblings = TN->getChildren();
- for (const TreeNodePtr N : Siblings) {
+ for (const TreeNodePtr N : TN->children()) {
clear();
NodePtr BBN = N->getBlock();
doFullDFSWalk(DT, [BBN](NodePtr From, NodePtr To) {
return From != BBN && To != BBN;
});
- for (const TreeNodePtr S : Siblings) {
+ for (const TreeNodePtr S : TN->children()) {
if (S == N) continue;
if (NodeToInfo.count(S->getBlock()) == 0) {
@@ -1571,7 +1564,7 @@ struct SemiNCAInfo {
// Check if the given tree is the same as a freshly computed one for the same
// Parent.
- // Running time: O(N^2), but faster in practise (same as tree construction).
+ // Running time: O(N^2), but faster in practice (same as tree construction).
//
// Note that this does not check if that the tree construction algorithm is
// correct and should be only used for fast (but possibly unsound)
@@ -1648,12 +1641,12 @@ bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL) {
if (!SNCA.IsSameAsFreshTree(DT))
return false;
- // Common checks to verify the properties of the tree. O(N log N) at worst
+ // Common checks to verify the properties of the tree. O(N log N) at worst.
if (!SNCA.verifyRoots(DT) || !SNCA.verifyReachability(DT) ||
!SNCA.VerifyLevels(DT) || !SNCA.VerifyDFSNumbers(DT))
return false;
- // Extra checks depending on VerificationLevel. Up to O(N^3)
+ // Extra checks depending on VerificationLevel. Up to O(N^3).
if (VL == DomTreeT::VerificationLevel::Basic ||
VL == DomTreeT::VerificationLevel::Full)
if (!SNCA.verifyParentProperty(DT))
diff --git a/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h b/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h
index 25eb7cd7b6d57..a8fca70159f5f 100644
--- a/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h
+++ b/llvm/include/llvm/Support/GenericIteratedDominanceFrontier.h
@@ -57,7 +57,7 @@ template <class NodeTy, bool IsPostDom> struct ChildrenGetterTy {
template <class NodeTy, bool IsPostDom> class IDFCalculatorBase {
public:
using OrderedNodeTy =
- typename std::conditional<IsPostDom, Inverse<NodeTy *>, NodeTy *>::type;
+ std::conditional_t<IsPostDom, Inverse<NodeTy *>, NodeTy *>;
using ChildrenGetterTy =
IDFCalculatorDetail::ChildrenGetterTy<NodeTy, IsPostDom>;
@@ -129,7 +129,7 @@ ChildrenGetterTy<NodeTy, IsPostDom>::get(const NodeRef &N) {
template <class NodeTy, bool IsPostDom>
void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
- SmallVectorImpl<NodeTy *> &PHIBlocks) {
+ SmallVectorImpl<NodeTy *> &IDFBlocks) {
// Use a priority queue keyed on dominator tree level so that inserted nodes
// are handled from the bottom of the dominator tree upwards. We also augment
// the level with a DFS number to ensure that the blocks are ordered in a
@@ -144,15 +144,16 @@ void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
DT.updateDFSNumbers();
- for (NodeTy *BB : *DefBlocks) {
- if (DomTreeNodeBase<NodeTy> *Node = DT.getNode(BB))
- PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
- }
-
SmallVector<DomTreeNodeBase<NodeTy> *, 32> Worklist;
SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedPQ;
SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedWorklist;
+ for (NodeTy *BB : *DefBlocks)
+ if (DomTreeNodeBase<NodeTy> *Node = DT.getNode(BB)) {
+ PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
+ VisitedWorklist.insert(Node);
+ }
+
while (!PQ.empty()) {
DomTreeNodePair RootPair = PQ.top();
PQ.pop();
@@ -164,9 +165,8 @@ void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
// most Root's level are added to the iterated dominance frontier of the
// definition set.
- Worklist.clear();
+ assert(Worklist.empty());
Worklist.push_back(Root);
- VisitedWorklist.insert(Root);
while (!Worklist.empty()) {
DomTreeNodeBase<NodeTy> *Node = Worklist.pop_back_val();
@@ -187,7 +187,7 @@ void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
if (useLiveIn && !LiveInBlocks->count(SuccBB))
return;
- PHIBlocks.emplace_back(SuccBB);
+ IDFBlocks.emplace_back(SuccBB);
if (!DefBlocks->count(SuccBB))
PQ.push(std::make_pair(
SuccNode, std::make_pair(SuccLevel, SuccNode->getDFSNumIn())));
diff --git a/llvm/include/llvm/Support/GlobPattern.h b/llvm/include/llvm/Support/GlobPattern.h
index 0098ac65fd308..3e5989d025007 100644
--- a/llvm/include/llvm/Support/GlobPattern.h
+++ b/llvm/include/llvm/Support/GlobPattern.h
@@ -16,15 +16,15 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include <vector>
// This class represents a glob pattern. Supported metacharacters
// are "*", "?", "\", "[<chars>]", "[^<chars>]", and "[!<chars>]".
namespace llvm {
-class BitVector;
+
template <typename T> class ArrayRef;
+class StringRef;
class GlobPattern {
public:
diff --git a/llvm/include/llvm/Support/GraphWriter.h b/llvm/include/llvm/Support/GraphWriter.h
index 466a0449e2579..f9241b1e8081b 100644
--- a/llvm/include/llvm/Support/GraphWriter.h
+++ b/llvm/include/llvm/Support/GraphWriter.h
@@ -126,7 +126,7 @@ public:
}
void writeHeader(const std::string &Title) {
- std::string GraphName = DTraits.getGraphName(G);
+ std::string GraphName(DTraits.getGraphName(G));
if (!Title.empty())
O << "digraph \"" << DOT::EscapeString(Title) << "\" {\n";
@@ -330,11 +330,8 @@ std::string WriteGraph(const GraphType &G, const Twine &Name,
const Twine &Title = "",
std::string Filename = "") {
int FD;
- // Windows can't always handle long paths, so limit the length of the name.
- std::string N = Name.str();
- N = N.substr(0, std::min<std::size_t>(N.size(), 140));
if (Filename.empty()) {
- Filename = createGraphFilename(N, FD);
+ Filename = createGraphFilename(Name.str(), FD);
} else {
std::error_code EC = sys::fs::openFileForWrite(Filename, FD);
@@ -344,6 +341,8 @@ std::string WriteGraph(const GraphType &G, const Twine &Name,
} else if (EC) {
errs() << "error writing into file" << "\n";
return "";
+ } else {
+ errs() << "writing to the newly created file " << Filename << "\n";
}
}
raw_fd_ostream O(FD, /*shouldClose=*/ true);
@@ -359,6 +358,17 @@ std::string WriteGraph(const GraphType &G, const Twine &Name,
return Filename;
}
+/// DumpDotGraph - Just dump a dot graph to the user-provided file name.
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+template <typename GraphType>
+LLVM_DUMP_METHOD void
+dumpDotGraphToFile(const GraphType &G, const Twine &FileName,
+ const Twine &Title, bool ShortNames = false,
+ const Twine &Name = "") {
+ llvm::WriteGraph(G, Name, ShortNames, Title, FileName.str());
+}
+#endif
+
/// ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file,
/// then cleanup. For use from the debugger.
///
diff --git a/llvm/include/llvm/Support/Host.h b/llvm/include/llvm/Support/Host.h
index 44f543c363db5..d4ef389450cc8 100644
--- a/llvm/include/llvm/Support/Host.h
+++ b/llvm/include/llvm/Support/Host.h
@@ -13,11 +13,13 @@
#ifndef LLVM_SUPPORT_HOST_H
#define LLVM_SUPPORT_HOST_H
-#include "llvm/ADT/StringMap.h"
-
#include <string>
namespace llvm {
+class MallocAllocator;
+class StringRef;
+template <typename ValueTy, typename AllocatorTy> class StringMap;
+
namespace sys {
/// getDefaultTargetTriple() - Return the default target triple the compiler
@@ -50,7 +52,7 @@ namespace sys {
/// all valid LLVM feature names.
///
/// \return - True on success.
- bool getHostCPUFeatures(StringMap<bool> &Features);
+ bool getHostCPUFeatures(StringMap<bool, MallocAllocator> &Features);
/// Get the number of physical cores (as opposed to logical cores returned
/// from thread::hardware_concurrency(), which includes hyperthreads).
diff --git a/llvm/include/llvm/Support/ItaniumManglingCanonicalizer.h b/llvm/include/llvm/Support/ItaniumManglingCanonicalizer.h
index 6920000340d4f..8e1b3d631983d 100644
--- a/llvm/include/llvm/Support/ItaniumManglingCanonicalizer.h
+++ b/llvm/include/llvm/Support/ItaniumManglingCanonicalizer.h
@@ -14,11 +14,13 @@
#ifndef LLVM_SUPPORT_ITANIUMMANGLINGCANONICALIZER_H
#define LLVM_SUPPORT_ITANIUMMANGLINGCANONICALIZER_H
-#include "llvm/ADT/StringRef.h"
-
#include <cstddef>
+#include <cstdint>
namespace llvm {
+
+class StringRef;
+
/// Canonicalizer for mangled names.
///
/// This class allows specifying a list of "equivalent" manglings. For example,
diff --git a/llvm/include/llvm/Support/JSON.h b/llvm/include/llvm/Support/JSON.h
index 2c63468c401a1..8b1c66234fe87 100644
--- a/llvm/include/llvm/Support/JSON.h
+++ b/llvm/include/llvm/Support/JSON.h
@@ -329,32 +329,28 @@ public:
Value(std::nullptr_t) : Type(T_Null) {}
// Boolean (disallow implicit conversions).
// (The last template parameter is a dummy to keep templates distinct.)
- template <
- typename T,
- typename = typename std::enable_if<std::is_same<T, bool>::value>::type,
- bool = false>
+ template <typename T,
+ typename = std::enable_if_t<std::is_same<T, bool>::value>,
+ bool = false>
Value(T B) : Type(T_Boolean) {
create<bool>(B);
}
// Integers (except boolean). Must be non-narrowing convertible to int64_t.
- template <
- typename T,
- typename = typename std::enable_if<std::is_integral<T>::value>::type,
- typename = typename std::enable_if<!std::is_same<T, bool>::value>::type>
+ template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>,
+ typename = std::enable_if_t<!std::is_same<T, bool>::value>>
Value(T I) : Type(T_Integer) {
create<int64_t>(int64_t{I});
}
// Floating point. Must be non-narrowing convertible to double.
template <typename T,
- typename =
- typename std::enable_if<std::is_floating_point<T>::value>::type,
+ typename = std::enable_if_t<std::is_floating_point<T>::value>,
double * = nullptr>
Value(T D) : Type(T_Double) {
create<double>(double{D});
}
// Serializable types: with a toJSON(const T&)->Value function, found by ADL.
template <typename T,
- typename = typename std::enable_if<std::is_same<
+ typename = std::enable_if_t<std::is_same<
Value, decltype(toJSON(*(const T *)nullptr))>::value>,
Value * = nullptr>
Value(const T &V) : Value(toJSON(V)) {}
@@ -565,7 +561,7 @@ inline bool Object::erase(StringRef K) {
// See comments on Value.
inline bool fromJSON(const Value &E, std::string &Out) {
if (auto S = E.getAsString()) {
- Out = *S;
+ Out = std::string(*S);
return true;
}
return false;
@@ -598,6 +594,13 @@ inline bool fromJSON(const Value &E, bool &Out) {
}
return false;
}
+inline bool fromJSON(const Value &E, std::nullptr_t &Out) {
+ if (auto S = E.getAsNull()) {
+ Out = *S;
+ return true;
+ }
+ return false;
+}
template <typename T> bool fromJSON(const Value &E, llvm::Optional<T> &Out) {
if (E.getAsNull()) {
Out = llvm::None;
@@ -625,7 +628,7 @@ bool fromJSON(const Value &E, std::map<std::string, T> &Out) {
if (auto *O = E.getAsObject()) {
Out.clear();
for (const auto &KV : *O)
- if (!fromJSON(KV.second, Out[llvm::StringRef(KV.first)]))
+ if (!fromJSON(KV.second, Out[std::string(llvm::StringRef(KV.first))]))
return false;
return true;
}
diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h
index ff25b6fc572ce..69040cd23f039 100644
--- a/llvm/include/llvm/Support/KnownBits.h
+++ b/llvm/include/llvm/Support/KnownBits.h
@@ -122,39 +122,55 @@ public:
return ~Zero;
}
- /// Truncate the underlying known Zero and One bits. This is equivalent
- /// to truncating the value we're tracking.
+ /// Return known bits for a truncation of the value we're tracking.
KnownBits trunc(unsigned BitWidth) const {
return KnownBits(Zero.trunc(BitWidth), One.trunc(BitWidth));
}
- /// Extends the underlying known Zero and One bits.
- /// By setting ExtendedBitsAreKnownZero=true this will be equivalent to
- /// zero extending the value we're tracking.
- /// With ExtendedBitsAreKnownZero=false the extended bits are set to unknown.
- KnownBits zext(unsigned BitWidth, bool ExtendedBitsAreKnownZero) const {
+ /// Return known bits for an "any" extension of the value we're tracking,
+ /// where we don't know anything about the extended bits.
+ KnownBits anyext(unsigned BitWidth) const {
+ return KnownBits(Zero.zext(BitWidth), One.zext(BitWidth));
+ }
+
+ /// Return known bits for a zero extension of the value we're tracking.
+ KnownBits zext(unsigned BitWidth) const {
unsigned OldBitWidth = getBitWidth();
APInt NewZero = Zero.zext(BitWidth);
- if (ExtendedBitsAreKnownZero)
- NewZero.setBitsFrom(OldBitWidth);
+ NewZero.setBitsFrom(OldBitWidth);
return KnownBits(NewZero, One.zext(BitWidth));
}
- /// Sign extends the underlying known Zero and One bits. This is equivalent
- /// to sign extending the value we're tracking.
+ /// Return known bits for a sign extension of the value we're tracking.
KnownBits sext(unsigned BitWidth) const {
return KnownBits(Zero.sext(BitWidth), One.sext(BitWidth));
}
- /// Extends or truncates the underlying known Zero and One bits. When
- /// extending the extended bits can either be set as known zero (if
- /// ExtendedBitsAreKnownZero=true) or as unknown (if
- /// ExtendedBitsAreKnownZero=false).
- KnownBits zextOrTrunc(unsigned BitWidth,
- bool ExtendedBitsAreKnownZero) const {
+ /// Return known bits for an "any" extension or truncation of the value we're
+ /// tracking.
+ KnownBits anyextOrTrunc(unsigned BitWidth) const {
+ if (BitWidth > getBitWidth())
+ return anyext(BitWidth);
+ if (BitWidth < getBitWidth())
+ return trunc(BitWidth);
+ return *this;
+ }
+
+ /// Return known bits for a zero extension or truncation of the value we're
+ /// tracking.
+ KnownBits zextOrTrunc(unsigned BitWidth) const {
if (BitWidth > getBitWidth())
- return zext(BitWidth, ExtendedBitsAreKnownZero);
- return KnownBits(Zero.zextOrTrunc(BitWidth), One.zextOrTrunc(BitWidth));
+ return zext(BitWidth);
+ if (BitWidth < getBitWidth())
+ return trunc(BitWidth);
+ return *this;
+ }
+
+ /// Return a KnownBits with the extracted bits
+ /// [bitPosition,bitPosition+numBits).
+ KnownBits extractBits(unsigned NumBits, unsigned BitPosition) const {
+ return KnownBits(Zero.extractBits(NumBits, BitPosition),
+ One.extractBits(NumBits, BitPosition));
}
/// Returns the minimum number of trailing zero bits.
@@ -224,8 +240,47 @@ public:
/// Compute known bits resulting from adding LHS and RHS.
static KnownBits computeForAddSub(bool Add, bool NSW, const KnownBits &LHS,
KnownBits RHS);
+
+ /// Update known bits based on ANDing with RHS.
+ KnownBits &operator&=(const KnownBits &RHS);
+
+ /// Update known bits based on ORing with RHS.
+ KnownBits &operator|=(const KnownBits &RHS);
+
+ /// Update known bits based on XORing with RHS.
+ KnownBits &operator^=(const KnownBits &RHS);
};
+inline KnownBits operator&(KnownBits LHS, const KnownBits &RHS) {
+ LHS &= RHS;
+ return LHS;
+}
+
+inline KnownBits operator&(const KnownBits &LHS, KnownBits &&RHS) {
+ RHS &= LHS;
+ return std::move(RHS);
+}
+
+inline KnownBits operator|(KnownBits LHS, const KnownBits &RHS) {
+ LHS |= RHS;
+ return LHS;
+}
+
+inline KnownBits operator|(const KnownBits &LHS, KnownBits &&RHS) {
+ RHS |= LHS;
+ return std::move(RHS);
+}
+
+inline KnownBits operator^(KnownBits LHS, const KnownBits &RHS) {
+ LHS ^= RHS;
+ return LHS;
+}
+
+inline KnownBits operator^(const KnownBits &LHS, KnownBits &&RHS) {
+ RHS ^= LHS;
+ return std::move(RHS);
+}
+
} // end namespace llvm
#endif
diff --git a/llvm/include/llvm/Support/LEB128.h b/llvm/include/llvm/Support/LEB128.h
index a02b83ca95975..8ab35431354d5 100644
--- a/llvm/include/llvm/Support/LEB128.h
+++ b/llvm/include/llvm/Support/LEB128.h
@@ -134,7 +134,7 @@ inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr,
if (error)
*error = nullptr;
do {
- if (end && p == end) {
+ if (p == end) {
if (error)
*error = "malformed uleb128, extends past end";
if (n)
@@ -168,7 +168,7 @@ inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr,
if (error)
*error = nullptr;
do {
- if (end && p == end) {
+ if (p == end) {
if (error)
*error = "malformed sleb128, extends past end";
if (n)
diff --git a/llvm/include/llvm/Support/LockFileManager.h b/llvm/include/llvm/Support/LockFileManager.h
index 2efeca3b62001..ab66621e67566 100644
--- a/llvm/include/llvm/Support/LockFileManager.h
+++ b/llvm/include/llvm/Support/LockFileManager.h
@@ -78,8 +78,8 @@ public:
/// For a shared lock, wait until the owner releases the lock.
/// Total timeout for the file to appear is ~1.5 minutes.
- /// \param MaxSeconds the maximum wait time per iteration in seconds.
- WaitForUnlockResult waitForUnlock(const unsigned MaxSeconds = 40);
+ /// \param MaxSeconds the maximum total wait time in seconds.
+ WaitForUnlockResult waitForUnlock(const unsigned MaxSeconds = 90);
/// Remove the lock file. This may delete a different lock file than
/// the one previously read if there is a race.
diff --git a/llvm/include/llvm/Support/LowLevelTypeImpl.h b/llvm/include/llvm/Support/LowLevelTypeImpl.h
index 6ef7c298bc28f..c1d516f2fe587 100644
--- a/llvm/include/llvm/Support/LowLevelTypeImpl.h
+++ b/llvm/include/llvm/Support/LowLevelTypeImpl.h
@@ -27,6 +27,7 @@
#define LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/MachineValueType.h"
#include <cassert>
@@ -137,6 +138,26 @@ public:
: LLT::scalar(NewEltSize);
}
+ /// Return a vector or scalar with the same element type and the new number of
+ /// elements.
+ LLT changeNumElements(unsigned NewNumElts) const {
+ return LLT::scalarOrVector(NewNumElts, getScalarType());
+ }
+
+ /// Return a type that is \p Factor times smaller. Reduces the number of
+ /// elements if this is a vector, or the bitwidth for scalar/pointers. Does
+ /// not attempt to handle cases that aren't evenly divisible.
+ LLT divide(int Factor) const {
+ assert(Factor != 1);
+ if (isVector()) {
+ assert(getNumElements() % Factor == 0);
+ return scalarOrVector(getNumElements() / Factor, getElementType());
+ }
+
+ assert(getSizeInBits() % Factor == 0);
+ return scalar(getSizeInBits() / Factor);
+ }
+
bool isByteSized() const { return (getSizeInBits() & 7) == 0; }
unsigned getScalarSizeInBits() const {
@@ -174,6 +195,13 @@ public:
void print(raw_ostream &OS) const;
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() const {
+ print(dbgs());
+ dbgs() << '\n';
+ }
+#endif
+
bool operator==(const LLT &RHS) const {
return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
RHS.RawData == RawData;
diff --git a/llvm/include/llvm/Support/MD5.h b/llvm/include/llvm/Support/MD5.h
index bb2bdbf1bed22..3b2d5b974d0bf 100644
--- a/llvm/include/llvm/Support/MD5.h
+++ b/llvm/include/llvm/Support/MD5.h
@@ -28,7 +28,6 @@
#ifndef LLVM_SUPPORT_MD5_H
#define LLVM_SUPPORT_MD5_H
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Endian.h"
#include <array>
@@ -36,6 +35,7 @@
namespace llvm {
+template <unsigned N> class SmallString;
template <typename T> class ArrayRef;
class MD5 {
diff --git a/llvm/include/llvm/Support/MSVCErrorWorkarounds.h b/llvm/include/llvm/Support/MSVCErrorWorkarounds.h
index 30e8febae20b9..bf983dc1e406b 100644
--- a/llvm/include/llvm/Support/MSVCErrorWorkarounds.h
+++ b/llvm/include/llvm/Support/MSVCErrorWorkarounds.h
@@ -59,22 +59,19 @@ public:
template <typename OtherT>
MSVCPExpected(
OtherT &&Val,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
- nullptr)
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr)
: Expected<T>(std::move(Val)) {}
template <class OtherT>
MSVCPExpected(
Expected<OtherT> &&Other,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
- nullptr)
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr)
: Expected<T>(std::move(Other)) {}
template <class OtherT>
explicit MSVCPExpected(
Expected<OtherT> &&Other,
- typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
- nullptr)
+ std::enable_if_t<!std::is_convertible<OtherT, T>::value> * = nullptr)
: Expected<T>(std::move(Other)) {}
};
diff --git a/llvm/include/llvm/Support/MachineValueType.h b/llvm/include/llvm/Support/MachineValueType.h
index 26b45a602763a..3bb8220e72e5d 100644
--- a/llvm/include/llvm/Support/MachineValueType.h
+++ b/llvm/include/llvm/Support/MachineValueType.h
@@ -47,158 +47,179 @@ namespace llvm {
FIRST_INTEGER_VALUETYPE = i1,
LAST_INTEGER_VALUETYPE = i128,
- f16 = 8, // This is a 16 bit floating point value
- f32 = 9, // This is a 32 bit floating point value
- f64 = 10, // This is a 64 bit floating point value
- f80 = 11, // This is a 80 bit floating point value
- f128 = 12, // This is a 128 bit floating point value
- ppcf128 = 13, // This is a PPC 128-bit floating point value
-
- FIRST_FP_VALUETYPE = f16,
+ bf16 = 8, // This is a 16 bit brain floating point value
+ f16 = 9, // This is a 16 bit floating point value
+ f32 = 10, // This is a 32 bit floating point value
+ f64 = 11, // This is a 64 bit floating point value
+ f80 = 12, // This is a 80 bit floating point value
+ f128 = 13, // This is a 128 bit floating point value
+ ppcf128 = 14, // This is a PPC 128-bit floating point value
+
+ FIRST_FP_VALUETYPE = bf16,
LAST_FP_VALUETYPE = ppcf128,
- v1i1 = 14, // 1 x i1
- v2i1 = 15, // 2 x i1
- v4i1 = 16, // 4 x i1
- v8i1 = 17, // 8 x i1
- v16i1 = 18, // 16 x i1
- v32i1 = 19, // 32 x i1
- v64i1 = 20, // 64 x i1
- v128i1 = 21, // 128 x i1
- v256i1 = 22, // 256 x i1
- v512i1 = 23, // 512 x i1
- v1024i1 = 24, // 1024 x i1
-
- v1i8 = 25, // 1 x i8
- v2i8 = 26, // 2 x i8
- v4i8 = 27, // 4 x i8
- v8i8 = 28, // 8 x i8
- v16i8 = 29, // 16 x i8
- v32i8 = 30, // 32 x i8
- v64i8 = 31, // 64 x i8
- v128i8 = 32, //128 x i8
- v256i8 = 33, //256 x i8
-
- v1i16 = 34, // 1 x i16
- v2i16 = 35, // 2 x i16
- v3i16 = 36, // 3 x i16
- v4i16 = 37, // 4 x i16
- v8i16 = 38, // 8 x i16
- v16i16 = 39, // 16 x i16
- v32i16 = 40, // 32 x i16
- v64i16 = 41, // 64 x i16
- v128i16 = 42, //128 x i16
-
- v1i32 = 43, // 1 x i32
- v2i32 = 44, // 2 x i32
- v3i32 = 45, // 3 x i32
- v4i32 = 46, // 4 x i32
- v5i32 = 47, // 5 x i32
- v8i32 = 48, // 8 x i32
- v16i32 = 49, // 16 x i32
- v32i32 = 50, // 32 x i32
- v64i32 = 51, // 64 x i32
- v128i32 = 52, // 128 x i32
- v256i32 = 53, // 256 x i32
- v512i32 = 54, // 512 x i32
- v1024i32 = 55, // 1024 x i32
- v2048i32 = 56, // 2048 x i32
-
- v1i64 = 57, // 1 x i64
- v2i64 = 58, // 2 x i64
- v4i64 = 59, // 4 x i64
- v8i64 = 60, // 8 x i64
- v16i64 = 61, // 16 x i64
- v32i64 = 62, // 32 x i64
-
- v1i128 = 63, // 1 x i128
+ v1i1 = 15, // 1 x i1
+ v2i1 = 16, // 2 x i1
+ v4i1 = 17, // 4 x i1
+ v8i1 = 18, // 8 x i1
+ v16i1 = 19, // 16 x i1
+ v32i1 = 20, // 32 x i1
+ v64i1 = 21, // 64 x i1
+ v128i1 = 22, // 128 x i1
+ v256i1 = 23, // 256 x i1
+ v512i1 = 24, // 512 x i1
+ v1024i1 = 25, // 1024 x i1
+
+ v1i8 = 26, // 1 x i8
+ v2i8 = 27, // 2 x i8
+ v4i8 = 28, // 4 x i8
+ v8i8 = 29, // 8 x i8
+ v16i8 = 30, // 16 x i8
+ v32i8 = 31, // 32 x i8
+ v64i8 = 32, // 64 x i8
+ v128i8 = 33, //128 x i8
+ v256i8 = 34, //256 x i8
+
+ v1i16 = 35, // 1 x i16
+ v2i16 = 36, // 2 x i16
+ v3i16 = 37, // 3 x i16
+ v4i16 = 38, // 4 x i16
+ v8i16 = 39, // 8 x i16
+ v16i16 = 40, // 16 x i16
+ v32i16 = 41, // 32 x i16
+ v64i16 = 42, // 64 x i16
+ v128i16 = 43, //128 x i16
+
+ v1i32 = 44, // 1 x i32
+ v2i32 = 45, // 2 x i32
+ v3i32 = 46, // 3 x i32
+ v4i32 = 47, // 4 x i32
+ v5i32 = 48, // 5 x i32
+ v8i32 = 49, // 8 x i32
+ v16i32 = 50, // 16 x i32
+ v32i32 = 51, // 32 x i32
+ v64i32 = 52, // 64 x i32
+ v128i32 = 53, // 128 x i32
+ v256i32 = 54, // 256 x i32
+ v512i32 = 55, // 512 x i32
+ v1024i32 = 56, // 1024 x i32
+ v2048i32 = 57, // 2048 x i32
+
+ v1i64 = 58, // 1 x i64
+ v2i64 = 59, // 2 x i64
+ v4i64 = 60, // 4 x i64
+ v8i64 = 61, // 8 x i64
+ v16i64 = 62, // 16 x i64
+ v32i64 = 63, // 32 x i64
+
+ v1i128 = 64, // 1 x i128
FIRST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE = v1i1,
LAST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE = v1i128,
- v2f16 = 64, // 2 x f16
- v3f16 = 65, // 3 x f16
- v4f16 = 66, // 4 x f16
- v8f16 = 67, // 8 x f16
- v16f16 = 68, // 16 x f16
- v32f16 = 69, // 32 x f16
- v1f32 = 70, // 1 x f32
- v2f32 = 71, // 2 x f32
- v3f32 = 72, // 3 x f32
- v4f32 = 73, // 4 x f32
- v5f32 = 74, // 5 x f32
- v8f32 = 75, // 8 x f32
- v16f32 = 76, // 16 x f32
- v32f32 = 77, // 32 x f32
- v64f32 = 78, // 64 x f32
- v128f32 = 79, // 128 x f32
- v256f32 = 80, // 256 x f32
- v512f32 = 81, // 512 x f32
- v1024f32 = 82, // 1024 x f32
- v2048f32 = 83, // 2048 x f32
- v1f64 = 84, // 1 x f64
- v2f64 = 85, // 2 x f64
- v4f64 = 86, // 4 x f64
- v8f64 = 87, // 8 x f64
+ v2f16 = 65, // 2 x f16
+ v3f16 = 66, // 3 x f16
+ v4f16 = 67, // 4 x f16
+ v8f16 = 68, // 8 x f16
+ v16f16 = 69, // 16 x f16
+ v32f16 = 70, // 32 x f16
+ v64f16 = 71, // 64 x f16
+ v128f16 = 72, // 128 x f16
+ v2bf16 = 73, // 2 x bf16
+ v3bf16 = 74, // 3 x bf16
+ v4bf16 = 75, // 4 x bf16
+ v8bf16 = 76, // 8 x bf16
+ v16bf16 = 77, // 16 x bf16
+ v32bf16 = 78, // 32 x bf16
+ v64bf16 = 79, // 64 x bf16
+ v128bf16 = 80, // 128 x bf16
+ v1f32 = 81, // 1 x f32
+ v2f32 = 82, // 2 x f32
+ v3f32 = 83, // 3 x f32
+ v4f32 = 84, // 4 x f32
+ v5f32 = 85, // 5 x f32
+ v8f32 = 86, // 8 x f32
+ v16f32 = 87, // 16 x f32
+ v32f32 = 88, // 32 x f32
+ v64f32 = 89, // 64 x f32
+ v128f32 = 90, // 128 x f32
+ v256f32 = 91, // 256 x f32
+ v512f32 = 92, // 512 x f32
+ v1024f32 = 93, // 1024 x f32
+ v2048f32 = 94, // 2048 x f32
+ v1f64 = 95, // 1 x f64
+ v2f64 = 96, // 2 x f64
+ v4f64 = 97, // 4 x f64
+ v8f64 = 98, // 8 x f64
+ v16f64 = 99, // 16 x f64
+ v32f64 = 100, // 32 x f64
FIRST_FP_FIXEDLEN_VECTOR_VALUETYPE = v2f16,
- LAST_FP_FIXEDLEN_VECTOR_VALUETYPE = v8f64,
+ LAST_FP_FIXEDLEN_VECTOR_VALUETYPE = v32f64,
FIRST_FIXEDLEN_VECTOR_VALUETYPE = v1i1,
- LAST_FIXEDLEN_VECTOR_VALUETYPE = v8f64,
-
- nxv1i1 = 88, // n x 1 x i1
- nxv2i1 = 89, // n x 2 x i1
- nxv4i1 = 90, // n x 4 x i1
- nxv8i1 = 91, // n x 8 x i1
- nxv16i1 = 92, // n x 16 x i1
- nxv32i1 = 93, // n x 32 x i1
-
- nxv1i8 = 94, // n x 1 x i8
- nxv2i8 = 95, // n x 2 x i8
- nxv4i8 = 96, // n x 4 x i8
- nxv8i8 = 97, // n x 8 x i8
- nxv16i8 = 98, // n x 16 x i8
- nxv32i8 = 99, // n x 32 x i8
-
- nxv1i16 = 100, // n x 1 x i16
- nxv2i16 = 101, // n x 2 x i16
- nxv4i16 = 102, // n x 4 x i16
- nxv8i16 = 103, // n x 8 x i16
- nxv16i16 = 104, // n x 16 x i16
- nxv32i16 = 105, // n x 32 x i16
-
- nxv1i32 = 106, // n x 1 x i32
- nxv2i32 = 107, // n x 2 x i32
- nxv4i32 = 108, // n x 4 x i32
- nxv8i32 = 109, // n x 8 x i32
- nxv16i32 = 110, // n x 16 x i32
- nxv32i32 = 111, // n x 32 x i32
-
- nxv1i64 = 112, // n x 1 x i64
- nxv2i64 = 113, // n x 2 x i64
- nxv4i64 = 114, // n x 4 x i64
- nxv8i64 = 115, // n x 8 x i64
- nxv16i64 = 116, // n x 16 x i64
- nxv32i64 = 117, // n x 32 x i64
+ LAST_FIXEDLEN_VECTOR_VALUETYPE = v32f64,
+
+ nxv1i1 = 101, // n x 1 x i1
+ nxv2i1 = 102, // n x 2 x i1
+ nxv4i1 = 103, // n x 4 x i1
+ nxv8i1 = 104, // n x 8 x i1
+ nxv16i1 = 105, // n x 16 x i1
+ nxv32i1 = 106, // n x 32 x i1
+ nxv64i1 = 107, // n x 64 x i1
+
+ nxv1i8 = 108, // n x 1 x i8
+ nxv2i8 = 109, // n x 2 x i8
+ nxv4i8 = 110, // n x 4 x i8
+ nxv8i8 = 111, // n x 8 x i8
+ nxv16i8 = 112, // n x 16 x i8
+ nxv32i8 = 113, // n x 32 x i8
+ nxv64i8 = 114, // n x 64 x i8
+
+ nxv1i16 = 115, // n x 1 x i16
+ nxv2i16 = 116, // n x 2 x i16
+ nxv4i16 = 117, // n x 4 x i16
+ nxv8i16 = 118, // n x 8 x i16
+ nxv16i16 = 119, // n x 16 x i16
+ nxv32i16 = 120, // n x 32 x i16
+
+ nxv1i32 = 121, // n x 1 x i32
+ nxv2i32 = 122, // n x 2 x i32
+ nxv4i32 = 123, // n x 4 x i32
+ nxv8i32 = 124, // n x 8 x i32
+ nxv16i32 = 125, // n x 16 x i32
+ nxv32i32 = 126, // n x 32 x i32
+
+ nxv1i64 = 127, // n x 1 x i64
+ nxv2i64 = 128, // n x 2 x i64
+ nxv4i64 = 129, // n x 4 x i64
+ nxv8i64 = 130, // n x 8 x i64
+ nxv16i64 = 131, // n x 16 x i64
+ nxv32i64 = 132, // n x 32 x i64
FIRST_INTEGER_SCALABLE_VECTOR_VALUETYPE = nxv1i1,
LAST_INTEGER_SCALABLE_VECTOR_VALUETYPE = nxv32i64,
- nxv2f16 = 118, // n x 2 x f16
- nxv4f16 = 119, // n x 4 x f16
- nxv8f16 = 120, // n x 8 x f16
- nxv1f32 = 121, // n x 1 x f32
- nxv2f32 = 122, // n x 2 x f32
- nxv4f32 = 123, // n x 4 x f32
- nxv8f32 = 124, // n x 8 x f32
- nxv16f32 = 125, // n x 16 x f32
- nxv1f64 = 126, // n x 1 x f64
- nxv2f64 = 127, // n x 2 x f64
- nxv4f64 = 128, // n x 4 x f64
- nxv8f64 = 129, // n x 8 x f64
-
- FIRST_FP_SCALABLE_VECTOR_VALUETYPE = nxv2f16,
+ nxv1f16 = 133, // n x 1 x f16
+ nxv2f16 = 134, // n x 2 x f16
+ nxv4f16 = 135, // n x 4 x f16
+ nxv8f16 = 136, // n x 8 x f16
+ nxv16f16 = 137, // n x 16 x f16
+ nxv32f16 = 138, // n x 32 x f16
+ nxv2bf16 = 139, // n x 2 x bf16
+ nxv4bf16 = 140, // n x 4 x bf16
+ nxv8bf16 = 141, // n x 8 x bf16
+ nxv1f32 = 142, // n x 1 x f32
+ nxv2f32 = 143, // n x 2 x f32
+ nxv4f32 = 144, // n x 4 x f32
+ nxv8f32 = 145, // n x 8 x f32
+ nxv16f32 = 146, // n x 16 x f32
+ nxv1f64 = 147, // n x 1 x f64
+ nxv2f64 = 148, // n x 2 x f64
+ nxv4f64 = 149, // n x 4 x f64
+ nxv8f64 = 150, // n x 8 x f64
+
+ FIRST_FP_SCALABLE_VECTOR_VALUETYPE = nxv1f16,
LAST_FP_SCALABLE_VECTOR_VALUETYPE = nxv8f64,
FIRST_SCALABLE_VECTOR_VALUETYPE = nxv1i1,
@@ -207,20 +228,20 @@ namespace llvm {
FIRST_VECTOR_VALUETYPE = v1i1,
LAST_VECTOR_VALUETYPE = nxv8f64,
- x86mmx = 130, // This is an X86 MMX value
+ x86mmx = 151, // This is an X86 MMX value
- Glue = 131, // This glues nodes together during pre-RA sched
+ Glue = 152, // This glues nodes together during pre-RA sched
- isVoid = 132, // This has no value
+ isVoid = 153, // This has no value
- Untyped = 133, // This value takes a register, but has
- // unspecified type. The register class
- // will be determined by the opcode.
+ Untyped = 154, // This value takes a register, but has
+ // unspecified type. The register class
+ // will be determined by the opcode.
- exnref = 134, // WebAssembly's exnref type
+ exnref = 155, // WebAssembly's exnref type
- FIRST_VALUETYPE = 1, // This is always the beginning of the list.
- LAST_VALUETYPE = 135, // This always remains at the end of the list.
+ FIRST_VALUETYPE = 1, // This is always the beginning of the list.
+ LAST_VALUETYPE = 156, // This always remains at the end of the list.
// This is the current maximum for LAST_VALUETYPE.
// MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors
@@ -332,17 +353,19 @@ namespace llvm {
/// Return true if this is a 32-bit vector type.
bool is32BitVector() const {
- return (SimpleTy == MVT::v32i1 || SimpleTy == MVT::v4i8 ||
- SimpleTy == MVT::v2i16 || SimpleTy == MVT::v1i32 ||
- SimpleTy == MVT::v2f16 || SimpleTy == MVT::v1f32);
+ return (SimpleTy == MVT::v32i1 || SimpleTy == MVT::v4i8 ||
+ SimpleTy == MVT::v2i16 || SimpleTy == MVT::v1i32 ||
+ SimpleTy == MVT::v2f16 || SimpleTy == MVT::v2bf16 ||
+ SimpleTy == MVT::v1f32);
}
/// Return true if this is a 64-bit vector type.
bool is64BitVector() const {
- return (SimpleTy == MVT::v64i1 || SimpleTy == MVT::v8i8 ||
- SimpleTy == MVT::v4i16 || SimpleTy == MVT::v2i32 ||
- SimpleTy == MVT::v1i64 || SimpleTy == MVT::v4f16 ||
- SimpleTy == MVT::v2f32 || SimpleTy == MVT::v1f64);
+ return (SimpleTy == MVT::v64i1 || SimpleTy == MVT::v8i8 ||
+ SimpleTy == MVT::v4i16 || SimpleTy == MVT::v2i32 ||
+ SimpleTy == MVT::v1i64 || SimpleTy == MVT::v4f16 ||
+ SimpleTy == MVT::v4bf16 ||SimpleTy == MVT::v2f32 ||
+ SimpleTy == MVT::v1f64);
}
/// Return true if this is a 128-bit vector type.
@@ -350,44 +373,50 @@ namespace llvm {
return (SimpleTy == MVT::v128i1 || SimpleTy == MVT::v16i8 ||
SimpleTy == MVT::v8i16 || SimpleTy == MVT::v4i32 ||
SimpleTy == MVT::v2i64 || SimpleTy == MVT::v1i128 ||
- SimpleTy == MVT::v8f16 || SimpleTy == MVT::v4f32 ||
- SimpleTy == MVT::v2f64);
+ SimpleTy == MVT::v8f16 || SimpleTy == MVT::v8bf16 ||
+ SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64);
}
/// Return true if this is a 256-bit vector type.
bool is256BitVector() const {
- return (SimpleTy == MVT::v16f16 || SimpleTy == MVT::v8f32 ||
- SimpleTy == MVT::v4f64 || SimpleTy == MVT::v32i8 ||
- SimpleTy == MVT::v16i16 || SimpleTy == MVT::v8i32 ||
- SimpleTy == MVT::v4i64 || SimpleTy == MVT::v256i1);
+ return (SimpleTy == MVT::v16f16 || SimpleTy == MVT::v16bf16 ||
+ SimpleTy == MVT::v8f32 || SimpleTy == MVT::v4f64 ||
+ SimpleTy == MVT::v32i8 || SimpleTy == MVT::v16i16 ||
+ SimpleTy == MVT::v8i32 || SimpleTy == MVT::v4i64 ||
+ SimpleTy == MVT::v256i1);
}
/// Return true if this is a 512-bit vector type.
bool is512BitVector() const {
- return (SimpleTy == MVT::v32f16 || SimpleTy == MVT::v16f32 ||
- SimpleTy == MVT::v8f64 || SimpleTy == MVT::v512i1 ||
- SimpleTy == MVT::v64i8 || SimpleTy == MVT::v32i16 ||
- SimpleTy == MVT::v16i32 || SimpleTy == MVT::v8i64);
+ return (SimpleTy == MVT::v32f16 || SimpleTy == MVT::v32bf16 ||
+ SimpleTy == MVT::v16f32 || SimpleTy == MVT::v8f64 ||
+ SimpleTy == MVT::v512i1 || SimpleTy == MVT::v64i8 ||
+ SimpleTy == MVT::v32i16 || SimpleTy == MVT::v16i32 ||
+ SimpleTy == MVT::v8i64);
}
/// Return true if this is a 1024-bit vector type.
bool is1024BitVector() const {
return (SimpleTy == MVT::v1024i1 || SimpleTy == MVT::v128i8 ||
SimpleTy == MVT::v64i16 || SimpleTy == MVT::v32i32 ||
- SimpleTy == MVT::v16i64);
+ SimpleTy == MVT::v16i64 || SimpleTy == MVT::v64f16 ||
+ SimpleTy == MVT::v32f32 || SimpleTy == MVT::v16f64 ||
+ SimpleTy == MVT::v64bf16);
}
/// Return true if this is a 2048-bit vector type.
bool is2048BitVector() const {
- return (SimpleTy == MVT::v256i8 || SimpleTy == MVT::v128i16 ||
- SimpleTy == MVT::v64i32 || SimpleTy == MVT::v32i64);
+ return (SimpleTy == MVT::v256i8 || SimpleTy == MVT::v128i16 ||
+ SimpleTy == MVT::v64i32 || SimpleTy == MVT::v32i64 ||
+ SimpleTy == MVT::v128f16 || SimpleTy == MVT::v64f32 ||
+ SimpleTy == MVT::v32f64 || SimpleTy == MVT::v128bf16);
}
/// Return true if this is an overloaded type for TableGen.
bool isOverloaded() const {
- return (SimpleTy==MVT::Any ||
- SimpleTy==MVT::iAny || SimpleTy==MVT::fAny ||
- SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny);
+ return (SimpleTy == MVT::Any || SimpleTy == MVT::iAny ||
+ SimpleTy == MVT::fAny || SimpleTy == MVT::vAny ||
+ SimpleTy == MVT::iPTRAny);
}
/// Return a VT for a vector type with the same element type but
@@ -441,7 +470,8 @@ namespace llvm {
case nxv4i1:
case nxv8i1:
case nxv16i1:
- case nxv32i1: return i1;
+ case nxv32i1:
+ case nxv64i1: return i1;
case v1i8:
case v2i8:
case v4i8:
@@ -456,7 +486,8 @@ namespace llvm {
case nxv4i8:
case nxv8i8:
case nxv16i8:
- case nxv32i8: return i8;
+ case nxv32i8:
+ case nxv64i8: return i8;
case v1i16:
case v2i16:
case v3i16:
@@ -511,9 +542,25 @@ namespace llvm {
case v8f16:
case v16f16:
case v32f16:
+ case v64f16:
+ case v128f16:
+ case nxv1f16:
case nxv2f16:
case nxv4f16:
- case nxv8f16: return f16;
+ case nxv8f16:
+ case nxv16f16:
+ case nxv32f16: return f16;
+ case v2bf16:
+ case v3bf16:
+ case v4bf16:
+ case v8bf16:
+ case v16bf16:
+ case v32bf16:
+ case v64bf16:
+ case v128bf16:
+ case nxv2bf16:
+ case nxv4bf16:
+ case nxv8bf16: return bf16;
case v1f32:
case v2f32:
case v3f32:
@@ -537,6 +584,8 @@ namespace llvm {
case v2f64:
case v4f64:
case v8f64:
+ case v16f64:
+ case v32f64:
case nxv1f64:
case nxv2f64:
case nxv4f64:
@@ -564,36 +613,48 @@ namespace llvm {
case v128i8:
case v128i16:
case v128i32:
+ case v128f16:
+ case v128bf16:
case v128f32: return 128;
case v64i1:
case v64i8:
case v64i16:
case v64i32:
- case v64f32: return 64;
+ case v64f16:
+ case v64bf16:
+ case v64f32:
+ case nxv64i1:
+ case nxv64i8: return 64;
case v32i1:
case v32i8:
case v32i16:
case v32i32:
case v32i64:
case v32f16:
+ case v32bf16:
case v32f32:
+ case v32f64:
case nxv32i1:
case nxv32i8:
case nxv32i16:
case nxv32i32:
- case nxv32i64: return 32;
+ case nxv32i64:
+ case nxv32f16: return 32;
case v16i1:
case v16i8:
case v16i16:
case v16i32:
case v16i64:
case v16f16:
+ case v16bf16:
case v16f32:
+ case v16f64:
case nxv16i1:
case nxv16i8:
case nxv16i16:
case nxv16i32:
case nxv16i64:
+ case nxv16f16:
case nxv16f32: return 16;
case v8i1:
case v8i8:
@@ -601,6 +662,7 @@ namespace llvm {
case v8i32:
case v8i64:
case v8f16:
+ case v8bf16:
case v8f32:
case v8f64:
case nxv8i1:
@@ -609,6 +671,7 @@ namespace llvm {
case nxv8i32:
case nxv8i64:
case nxv8f16:
+ case nxv8bf16:
case nxv8f32:
case nxv8f64: return 8;
case v5i32:
@@ -619,6 +682,7 @@ namespace llvm {
case v4i32:
case v4i64:
case v4f16:
+ case v4bf16:
case v4f32:
case v4f64:
case nxv4i1:
@@ -627,11 +691,13 @@ namespace llvm {
case nxv4i32:
case nxv4i64:
case nxv4f16:
+ case nxv4bf16:
case nxv4f32:
case nxv4f64: return 4;
case v3i16:
case v3i32:
case v3f16:
+ case v3bf16:
case v3f32: return 3;
case v2i1:
case v2i8:
@@ -639,6 +705,7 @@ namespace llvm {
case v2i32:
case v2i64:
case v2f16:
+ case v2bf16:
case v2f32:
case v2f64:
case nxv2i1:
@@ -647,6 +714,7 @@ namespace llvm {
case nxv2i32:
case nxv2i64:
case nxv2f16:
+ case nxv2bf16:
case nxv2f32:
case nxv2f64: return 2;
case v1i1:
@@ -662,6 +730,7 @@ namespace llvm {
case nxv1i16:
case nxv1i32:
case nxv1i64:
+ case nxv1f16:
case nxv1f32:
case nxv1f64: return 1;
}
@@ -671,6 +740,11 @@ namespace llvm {
return { getVectorNumElements(), isScalableVector() };
}
+ /// Given a vector type, return the minimum number of elements it contains.
+ unsigned getVectorMinNumElements() const {
+ return getVectorElementCount().Min;
+ }
+
/// Returns the size of the specified MVT in bits.
///
/// If the value type is a scalable vector type, the scalable property will
@@ -709,18 +783,21 @@ namespace llvm {
case nxv8i1: return TypeSize::Scalable(8);
case i16 :
case f16:
+ case bf16:
case v16i1:
case v2i8:
case v1i16: return TypeSize::Fixed(16);
case nxv16i1:
case nxv2i8:
- case nxv1i16: return TypeSize::Scalable(16);
+ case nxv1i16:
+ case nxv1f16: return TypeSize::Scalable(16);
case f32 :
case i32 :
case v32i1:
case v4i8:
case v2i16:
case v2f16:
+ case v2bf16:
case v1f32:
case v1i32: return TypeSize::Fixed(32);
case nxv32i1:
@@ -728,9 +805,11 @@ namespace llvm {
case nxv2i16:
case nxv1i32:
case nxv2f16:
+ case nxv2bf16:
case nxv1f32: return TypeSize::Scalable(32);
case v3i16:
- case v3f16: return TypeSize::Fixed(48);
+ case v3f16:
+ case v3bf16: return TypeSize::Fixed(48);
case x86mmx:
case f64 :
case i64 :
@@ -740,13 +819,16 @@ namespace llvm {
case v2i32:
case v1i64:
case v4f16:
+ case v4bf16:
case v2f32:
case v1f64: return TypeSize::Fixed(64);
+ case nxv64i1:
case nxv8i8:
case nxv4i16:
case nxv2i32:
case nxv1i64:
case nxv4f16:
+ case nxv4bf16:
case nxv2f32:
case nxv1f64: return TypeSize::Scalable(64);
case f80 : return TypeSize::Fixed(80);
@@ -762,6 +844,7 @@ namespace llvm {
case v2i64:
case v1i128:
case v8f16:
+ case v8bf16:
case v4f32:
case v2f64: return TypeSize::Fixed(128);
case nxv16i8:
@@ -769,6 +852,7 @@ namespace llvm {
case nxv4i32:
case nxv2i64:
case nxv8f16:
+ case nxv8bf16:
case nxv4f32:
case nxv2f64: return TypeSize::Scalable(128);
case v5i32:
@@ -779,12 +863,14 @@ namespace llvm {
case v8i32:
case v4i64:
case v16f16:
+ case v16bf16:
case v8f32:
case v4f64: return TypeSize::Fixed(256);
case nxv32i8:
case nxv16i16:
case nxv8i32:
case nxv4i64:
+ case nxv16f16:
case nxv8f32:
case nxv4f64: return TypeSize::Scalable(256);
case v512i1:
@@ -793,11 +879,14 @@ namespace llvm {
case v16i32:
case v8i64:
case v32f16:
+ case v32bf16:
case v16f32:
case v8f64: return TypeSize::Fixed(512);
+ case nxv64i8:
case nxv32i16:
case nxv16i32:
case nxv8i64:
+ case nxv32f16:
case nxv16f32:
case nxv8f64: return TypeSize::Scalable(512);
case v1024i1:
@@ -805,14 +894,20 @@ namespace llvm {
case v64i16:
case v32i32:
case v16i64:
- case v32f32: return TypeSize::Fixed(1024);
+ case v64f16:
+ case v64bf16:
+ case v32f32:
+ case v16f64: return TypeSize::Fixed(1024);
case nxv32i32:
case nxv16i64: return TypeSize::Scalable(1024);
case v256i8:
case v128i16:
case v64i32:
case v32i64:
- case v64f32: return TypeSize::Fixed(2048);
+ case v128f16:
+ case v128bf16:
+ case v64f32:
+ case v32f64: return TypeSize::Fixed(2048);
case nxv32i64: return TypeSize::Scalable(2048);
case v128i32:
case v128f32: return TypeSize::Fixed(4096);
@@ -982,12 +1077,24 @@ namespace llvm {
if (NumElements == 1) return MVT::v1i128;
break;
case MVT::f16:
- if (NumElements == 2) return MVT::v2f16;
- if (NumElements == 3) return MVT::v3f16;
- if (NumElements == 4) return MVT::v4f16;
- if (NumElements == 8) return MVT::v8f16;
- if (NumElements == 16) return MVT::v16f16;
- if (NumElements == 32) return MVT::v32f16;
+ if (NumElements == 2) return MVT::v2f16;
+ if (NumElements == 3) return MVT::v3f16;
+ if (NumElements == 4) return MVT::v4f16;
+ if (NumElements == 8) return MVT::v8f16;
+ if (NumElements == 16) return MVT::v16f16;
+ if (NumElements == 32) return MVT::v32f16;
+ if (NumElements == 64) return MVT::v64f16;
+ if (NumElements == 128) return MVT::v128f16;
+ break;
+ case MVT::bf16:
+ if (NumElements == 2) return MVT::v2bf16;
+ if (NumElements == 3) return MVT::v3bf16;
+ if (NumElements == 4) return MVT::v4bf16;
+ if (NumElements == 8) return MVT::v8bf16;
+ if (NumElements == 16) return MVT::v16bf16;
+ if (NumElements == 32) return MVT::v32bf16;
+ if (NumElements == 64) return MVT::v64bf16;
+ if (NumElements == 128) return MVT::v128bf16;
break;
case MVT::f32:
if (NumElements == 1) return MVT::v1f32;
@@ -1010,6 +1117,8 @@ namespace llvm {
if (NumElements == 2) return MVT::v2f64;
if (NumElements == 4) return MVT::v4f64;
if (NumElements == 8) return MVT::v8f64;
+ if (NumElements == 16) return MVT::v16f64;
+ if (NumElements == 32) return MVT::v32f64;
break;
}
return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE);
@@ -1026,6 +1135,7 @@ namespace llvm {
if (NumElements == 8) return MVT::nxv8i1;
if (NumElements == 16) return MVT::nxv16i1;
if (NumElements == 32) return MVT::nxv32i1;
+ if (NumElements == 64) return MVT::nxv64i1;
break;
case MVT::i8:
if (NumElements == 1) return MVT::nxv1i8;
@@ -1034,6 +1144,7 @@ namespace llvm {
if (NumElements == 8) return MVT::nxv8i8;
if (NumElements == 16) return MVT::nxv16i8;
if (NumElements == 32) return MVT::nxv32i8;
+ if (NumElements == 64) return MVT::nxv64i8;
break;
case MVT::i16:
if (NumElements == 1) return MVT::nxv1i16;
@@ -1060,9 +1171,17 @@ namespace llvm {
if (NumElements == 32) return MVT::nxv32i64;
break;
case MVT::f16:
+ if (NumElements == 1) return MVT::nxv1f16;
if (NumElements == 2) return MVT::nxv2f16;
if (NumElements == 4) return MVT::nxv4f16;
if (NumElements == 8) return MVT::nxv8f16;
+ if (NumElements == 16) return MVT::nxv16f16;
+ if (NumElements == 32) return MVT::nxv32f16;
+ break;
+ case MVT::bf16:
+ if (NumElements == 2) return MVT::nxv2bf16;
+ if (NumElements == 4) return MVT::nxv4bf16;
+ if (NumElements == 8) return MVT::nxv8bf16;
break;
case MVT::f32:
if (NumElements == 1) return MVT::nxv1f32;
diff --git a/llvm/include/llvm/Support/ManagedStatic.h b/llvm/include/llvm/Support/ManagedStatic.h
index e65bb051f1818..f2b41422f1315 100644
--- a/llvm/include/llvm/Support/ManagedStatic.h
+++ b/llvm/include/llvm/Support/ManagedStatic.h
@@ -40,8 +40,8 @@ template <typename T, size_t N> struct object_deleter<T[N]> {
// constexpr, a dynamic initializer may be emitted depending on optimization
// settings. For the affected versions of MSVC, use the old linker
// initialization pattern of not providing a constructor and leaving the fields
-// uninitialized.
-#if !defined(_MSC_VER) || defined(__clang__)
+// uninitialized. See http://llvm.org/PR41367 for details.
+#if !defined(_MSC_VER) || (_MSC_VER >= 1925) || defined(__clang__)
#define LLVM_USE_CONSTEXPR_CTOR
#endif
@@ -102,6 +102,12 @@ public:
}
const C *operator->() const { return &**this; }
+
+ // Extract the instance, leaving the ManagedStatic uninitialized. The
+ // user is then responsible for the lifetime of the returned instance.
+ C *claim() {
+ return static_cast<C *>(Ptr.exchange(nullptr));
+ }
};
/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index 37b9669cbeed9..16da3046c8ced 100644
--- a/llvm/include/llvm/Support/MathExtras.h
+++ b/llvm/include/llvm/Support/MathExtras.h
@@ -14,10 +14,11 @@
#define LLVM_SUPPORT_MATHEXTRAS_H
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/SwapByteOrder.h"
#include <algorithm>
#include <cassert>
#include <climits>
+#include <cmath>
+#include <cstdint>
#include <cstring>
#include <limits>
#include <type_traits>
@@ -312,6 +313,34 @@ T reverseBits(T Val) {
return Val;
}
+#if __has_builtin(__builtin_bitreverse8)
+template<>
+inline uint8_t reverseBits<uint8_t>(uint8_t Val) {
+ return __builtin_bitreverse8(Val);
+}
+#endif
+
+#if __has_builtin(__builtin_bitreverse16)
+template<>
+inline uint16_t reverseBits<uint16_t>(uint16_t Val) {
+ return __builtin_bitreverse16(Val);
+}
+#endif
+
+#if __has_builtin(__builtin_bitreverse32)
+template<>
+inline uint32_t reverseBits<uint32_t>(uint32_t Val) {
+ return __builtin_bitreverse32(Val);
+}
+#endif
+
+#if __has_builtin(__builtin_bitreverse64)
+template<>
+inline uint64_t reverseBits<uint64_t>(uint64_t Val) {
+ return __builtin_bitreverse64(Val);
+}
+#endif
+
// NOTE: The following support functions use the _32/_64 extensions instead of
// type overloading so that signed and unsigned integers can be used without
// ambiguity.
@@ -364,14 +393,12 @@ constexpr inline bool isShiftedInt(int64_t x) {
/// to keep MSVC from (incorrectly) warning on isUInt<64> that we're shifting
/// left too many places.
template <unsigned N>
-constexpr inline typename std::enable_if<(N < 64), bool>::type
-isUInt(uint64_t X) {
+constexpr inline std::enable_if_t<(N < 64), bool> isUInt(uint64_t X) {
static_assert(N > 0, "isUInt<0> doesn't make sense");
return X < (UINT64_C(1) << (N));
}
template <unsigned N>
-constexpr inline typename std::enable_if<N >= 64, bool>::type
-isUInt(uint64_t X) {
+constexpr inline std::enable_if_t<N >= 64, bool> isUInt(uint64_t X) {
return true;
}
@@ -471,21 +498,6 @@ 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.
///
@@ -780,8 +792,7 @@ inline int64_t SignExtend64(uint64_t X, unsigned 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) {
+std::enable_if_t<std::is_unsigned<T>::value, T> AbsoluteDifference(T X, T Y) {
return std::max(X, Y) - std::min(X, Y);
}
@@ -789,7 +800,7 @@ AbsoluteDifference(T X, T Y) {
/// maximum representable value of T on overflow. ResultOverflowed indicates if
/// the result is larger than the maximum representable value of type T.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, T>::type
+std::enable_if_t<std::is_unsigned<T>::value, T>
SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
bool Dummy;
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
@@ -806,7 +817,7 @@ SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
/// maximum representable value of T on overflow. ResultOverflowed indicates if
/// the result is larger than the maximum representable value of type T.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, T>::type
+std::enable_if_t<std::is_unsigned<T>::value, T>
SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
bool Dummy;
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
@@ -852,7 +863,7 @@ SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
/// overflow. ResultOverflowed indicates if the result is larger than the
/// maximum representable value of type T.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, T>::type
+std::enable_if_t<std::is_unsigned<T>::value, T>
SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
bool Dummy;
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
@@ -871,13 +882,12 @@ 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) {
+std::enable_if_t<std::is_signed<T>::value, T> AddOverflow(T X, T Y, T &Result) {
#if __has_builtin(__builtin_add_overflow)
return __builtin_add_overflow(X, Y, &Result);
#else
// Perform the unsigned addition.
- using U = typename std::make_unsigned<T>::type;
+ using U = std::make_unsigned_t<T>;
const U UX = static_cast<U>(X);
const U UY = static_cast<U>(Y);
const U UResult = UX + UY;
@@ -898,13 +908,12 @@ AddOverflow(T X, T Y, T &Result) {
/// 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) {
+std::enable_if_t<std::is_signed<T>::value, T> SubOverflow(T X, T Y, T &Result) {
#if __has_builtin(__builtin_sub_overflow)
return __builtin_sub_overflow(X, Y, &Result);
#else
// Perform the unsigned addition.
- using U = typename std::make_unsigned<T>::type;
+ using U = std::make_unsigned_t<T>;
const U UX = static_cast<U>(X);
const U UY = static_cast<U>(Y);
const U UResult = UX - UY;
@@ -922,14 +931,12 @@ SubOverflow(T X, T Y, T &Result) {
#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) {
+std::enable_if_t<std::is_signed<T>::value, T> MulOverflow(T X, T Y, T &Result) {
// Perform the unsigned multiplication on absolute values.
- using U = typename std::make_unsigned<T>::type;
+ using U = std::make_unsigned_t<T>;
const U UX = X < 0 ? (0 - static_cast<U>(X)) : static_cast<U>(X);
const U UY = Y < 0 ? (0 - static_cast<U>(Y)) : static_cast<U>(Y);
const U UResult = UX * UY;
diff --git a/llvm/include/llvm/Support/MemAlloc.h b/llvm/include/llvm/Support/MemAlloc.h
index 0e5869141fd3d..d6012bd5a6985 100644
--- a/llvm/include/llvm/Support/MemAlloc.h
+++ b/llvm/include/llvm/Support/MemAlloc.h
@@ -62,5 +62,26 @@ LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_realloc(void *Ptr, size_t Sz) {
return Result;
}
-}
+/// Allocate a buffer of memory with the given size and alignment.
+///
+/// When the compiler supports aligned operator new, this will use it to to
+/// handle even over-aligned allocations.
+///
+/// However, this doesn't make any attempt to leverage the fancier techniques
+/// like posix_memalign due to portability. It is mostly intended to allow
+/// compatibility with platforms that, after aligned allocation was added, use
+/// reduced default alignment.
+LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+allocate_buffer(size_t Size, size_t Alignment);
+
+/// Deallocate a buffer of memory with the given size and alignment.
+///
+/// If supported, this will used the sized delete operator. Also if supported,
+/// this will pass the alignment to the delete operator.
+///
+/// The pointer must have been allocated with the corresponding new operator,
+/// most likely using the above helper.
+void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment);
+
+} // namespace llvm
#endif
diff --git a/llvm/include/llvm/Support/MemoryBuffer.h b/llvm/include/llvm/Support/MemoryBuffer.h
index b5196cd84cb47..f47a8d2d334be 100644
--- a/llvm/include/llvm/Support/MemoryBuffer.h
+++ b/llvm/include/llvm/Support/MemoryBuffer.h
@@ -19,7 +19,6 @@
#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>
@@ -28,6 +27,18 @@ namespace llvm {
class MemoryBufferRef;
+namespace sys {
+namespace fs {
+// Duplicated from FileSystem.h to avoid a dependency.
+#if defined(_WIN32)
+// A Win32 HANDLE is a typedef of void*
+using file_t = void *;
+#else
+using file_t = int;
+#endif
+} // namespace fs
+} // namespace sys
+
/// This interface provides simple read-only access to a block of memory, and
/// provides simple methods for reading files and standard input into a memory
/// buffer. In addition to basic access to the characters in the file, this
@@ -48,9 +59,6 @@ protected:
void init(const char *BufStart, const char *BufEnd,
bool RequiresNullTerminator);
- static constexpr sys::fs::mapped_file_region::mapmode Mapmode =
- sys::fs::mapped_file_region::readonly;
-
public:
MemoryBuffer(const MemoryBuffer &) = delete;
MemoryBuffer &operator=(const MemoryBuffer &) = delete;
@@ -156,9 +164,6 @@ 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;
@@ -218,9 +223,6 @@ 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;
diff --git a/llvm/include/llvm/Support/NativeFormatting.h b/llvm/include/llvm/Support/NativeFormatting.h
index 825a44c77c001..e664d05f24dbd 100644
--- a/llvm/include/llvm/Support/NativeFormatting.h
+++ b/llvm/include/llvm/Support/NativeFormatting.h
@@ -10,11 +10,10 @@
#define LLVM_SUPPORT_NATIVE_FORMATTING_H
#include "llvm/ADT/Optional.h"
-#include "llvm/Support/raw_ostream.h"
-
#include <cstdint>
namespace llvm {
+class raw_ostream;
enum class FloatStyle { Exponent, ExponentUpper, Fixed, Percent };
enum class IntegerStyle {
Integer,
diff --git a/llvm/include/llvm/Support/OptimizedStructLayout.h b/llvm/include/llvm/Support/OptimizedStructLayout.h
new file mode 100644
index 0000000000000..773ddfeaf13a9
--- /dev/null
+++ b/llvm/include/llvm/Support/OptimizedStructLayout.h
@@ -0,0 +1,142 @@
+//===-- OptimizedStructLayout.h - Struct layout algorithm ---------*- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// This file provides an interface for laying out a sequence of fields
+/// as a struct in a way that attempts to minimizes the total space
+/// requirements of the struct while still satisfying the layout
+/// requirements of the individual fields. The resulting layout may be
+/// substantially more compact than simply laying out the fields in their
+/// original order.
+///
+/// Fields may be pre-assigned fixed offsets. They may also be given sizes
+/// that are not multiples of their alignments. There is no currently no
+/// way to describe that a field has interior padding that other fields may
+/// be allocated into.
+///
+/// This algorithm does not claim to be "optimal" for several reasons:
+///
+/// - First, it does not guarantee that the result is minimal in size.
+/// There is no known efficient algoorithm to achieve minimality for
+/// unrestricted inputs. Nonetheless, this algorithm
+///
+/// - Second, there are other ways that a struct layout could be optimized
+/// besides space usage, such as locality. This layout may have a mixed
+/// impact on locality: less overall memory may be used, but adjacent
+/// fields in the original array may be moved further from one another.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_OPTIMIZEDSTRUCTLAYOUT_H
+#define LLVM_SUPPORT_OPTIMIZEDSTRUCTLAYOUT_H
+
+#include "llvm/Support/Alignment.h"
+#include "llvm/ADT/ArrayRef.h"
+#include <utility>
+
+namespace llvm {
+
+/// A field in a structure.
+struct OptimizedStructLayoutField {
+ /// A special value for Offset indicating that the field can be moved
+ /// anywhere.
+ static constexpr uint64_t FlexibleOffset = ~(uint64_t)0;
+
+ OptimizedStructLayoutField(const void *Id, uint64_t Size, Align Alignment,
+ uint64_t FixedOffset = FlexibleOffset)
+ : Offset(FixedOffset), Size(Size), Id(Id), Alignment(Alignment) {
+ assert(Size > 0 && "adding an empty field to the layout");
+ }
+
+ /// The offset of this field in the final layout. If this is
+ /// initialized to FlexibleOffset, layout will overwrite it with
+ /// the assigned offset of the field.
+ uint64_t Offset;
+
+ /// The required size of this field in bytes. Does not have to be
+ /// a multiple of Alignment. Must be non-zero.
+ uint64_t Size;
+
+ /// A opaque value which uniquely identifies this field.
+ const void *Id;
+
+ /// Private scratch space for the algorithm. The implementation
+ /// must treat this as uninitialized memory on entry.
+ void *Scratch;
+
+ /// The required alignment of this field.
+ Align Alignment;
+
+ /// Return true if this field has been assigned a fixed offset.
+ /// After layout, this will be true of all the fields.
+ bool hasFixedOffset() const {
+ return (Offset != FlexibleOffset);
+ }
+
+ /// Given that this field has a fixed offset, return the offset
+ /// of the first byte following it.
+ uint64_t getEndOffset() const {
+ assert(hasFixedOffset());
+ return Offset + Size;
+ }
+};
+
+/// Compute a layout for a struct containing the given fields, making a
+/// best-effort attempt to minimize the amount of space required.
+///
+/// Two features are supported which require a more careful solution
+/// than the well-known "sort by decreasing alignment" solution:
+///
+/// - Fields may be assigned a fixed offset in the layout. If there are
+/// gaps among the fixed-offset fields, the algorithm may attempt
+/// to allocate flexible-offset fields into those gaps. If that's
+/// undesirable, the caller should "block out" those gaps by e.g.
+/// just creating a single fixed-offset field that represents the
+/// entire "header".
+///
+/// - The size of a field is not required to be a multiple of, or even
+/// greater than, the field's required alignment. The only constraint
+/// on fields is that they must not be zero-sized.
+///
+/// To simplify the implementation, any fixed-offset fields in the
+/// layout must appear at the start of the field array, and they must
+/// be ordered by increasing offset.
+///
+/// The algorithm will produce a guaranteed-minimal layout with no
+/// interior padding in the following "C-style" case:
+///
+/// - every field's size is a multiple of its required alignment and
+/// - either no fields have initially fixed offsets, or the fixed-offset
+/// fields have no interior padding and end at an offset that is at
+/// least as aligned as all the flexible-offset fields.
+///
+/// Otherwise, while the algorithm will make a best-effort attempt to
+/// avoid padding, it cannot guarantee a minimal layout, as there is
+/// no known efficient algorithm for doing so.
+///
+/// The layout produced by this algorithm may not be stable across LLVM
+/// releases. Do not use this anywhere where ABI stability is required.
+///
+/// Flexible-offset fields with the same size and alignment will be ordered
+/// the same way they were in the initial array. Otherwise the current
+/// algorithm makes no effort to preserve the initial order of
+/// flexible-offset fields.
+///
+/// On return, all fields will have been assigned a fixed offset, and the
+/// array will be sorted in order of ascending offsets. Note that this
+/// means that the fixed-offset fields may no longer form a strict prefix
+/// if there's any padding before they end.
+///
+/// The return value is the total size of the struct and its required
+/// alignment. Note that the total size is not rounded up to a multiple
+/// of the required alignment; clients which require this can do so easily.
+std::pair<uint64_t, Align> performOptimizedStructLayout(
+ MutableArrayRef<OptimizedStructLayoutField> Fields);
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/Support/Parallel.h b/llvm/include/llvm/Support/Parallel.h
index 3c0ed2c111275..2c0edfbb1db5b 100644
--- a/llvm/include/llvm/Support/Parallel.h
+++ b/llvm/include/llvm/Support/Parallel.h
@@ -12,6 +12,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Threading.h"
#include <algorithm>
#include <condition_variable>
@@ -21,17 +22,11 @@
namespace llvm {
namespace parallel {
-struct sequential_execution_policy {};
-struct parallel_execution_policy {};
-template <typename T>
-struct is_execution_policy
- : public std::integral_constant<
- bool, llvm::is_one_of<T, sequential_execution_policy,
- parallel_execution_policy>::value> {};
-
-constexpr sequential_execution_policy seq{};
-constexpr parallel_execution_policy par{};
+// Strategy for the default executor used by the parallel routines provided by
+// this file. It defaults to using all hardware threads and should be
+// initialized before the first use of parallel routines.
+extern ThreadPoolStrategy strategy;
namespace detail {
@@ -163,61 +158,58 @@ void parallel_for_each_n(IndexTy Begin, IndexTy End, FuncTy Fn) {
#endif
-template <typename Iter>
-using DefComparator =
- std::less<typename std::iterator_traits<Iter>::value_type>;
-
} // namespace detail
+} // namespace parallel
-// sequential algorithm implementations.
-template <class Policy, class RandomAccessIterator,
- class Comparator = detail::DefComparator<RandomAccessIterator>>
-void sort(Policy policy, RandomAccessIterator Start, RandomAccessIterator End,
- const Comparator &Comp = Comparator()) {
- static_assert(is_execution_policy<Policy>::value,
- "Invalid execution policy!");
+template <class RandomAccessIterator,
+ class Comparator = std::less<
+ typename std::iterator_traits<RandomAccessIterator>::value_type>>
+void parallelSort(RandomAccessIterator Start, RandomAccessIterator End,
+ const Comparator &Comp = Comparator()) {
+#if LLVM_ENABLE_THREADS
+ if (parallel::strategy.ThreadsRequested != 1) {
+ parallel::detail::parallel_sort(Start, End, Comp);
+ return;
+ }
+#endif
llvm::sort(Start, End, Comp);
}
-template <class Policy, class IterTy, class FuncTy>
-void for_each(Policy policy, IterTy Begin, IterTy End, FuncTy Fn) {
- static_assert(is_execution_policy<Policy>::value,
- "Invalid execution policy!");
+template <class IterTy, class FuncTy>
+void parallelForEach(IterTy Begin, IterTy End, FuncTy Fn) {
+#if LLVM_ENABLE_THREADS
+ if (parallel::strategy.ThreadsRequested != 1) {
+ parallel::detail::parallel_for_each(Begin, End, Fn);
+ return;
+ }
+#endif
std::for_each(Begin, End, Fn);
}
-template <class Policy, class IndexTy, class FuncTy>
-void for_each_n(Policy policy, IndexTy Begin, IndexTy End, FuncTy Fn) {
- static_assert(is_execution_policy<Policy>::value,
- "Invalid execution policy!");
- for (IndexTy I = Begin; I != End; ++I)
- Fn(I);
-}
-
-// Parallel algorithm implementations, only available when LLVM_ENABLE_THREADS
-// is true.
+template <class FuncTy>
+void parallelForEachN(size_t Begin, size_t End, FuncTy Fn) {
#if LLVM_ENABLE_THREADS
-template <class RandomAccessIterator,
- class Comparator = detail::DefComparator<RandomAccessIterator>>
-void sort(parallel_execution_policy policy, RandomAccessIterator Start,
- RandomAccessIterator End, const Comparator &Comp = Comparator()) {
- detail::parallel_sort(Start, End, Comp);
+ if (parallel::strategy.ThreadsRequested != 1) {
+ parallel::detail::parallel_for_each_n(Begin, End, Fn);
+ return;
+ }
+#endif
+ for (size_t I = Begin; I != End; ++I)
+ Fn(I);
}
-template <class IterTy, class FuncTy>
-void for_each(parallel_execution_policy policy, IterTy Begin, IterTy End,
- FuncTy Fn) {
- detail::parallel_for_each(Begin, End, Fn);
+// Range wrappers.
+template <class RangeTy,
+ class Comparator = std::less<decltype(*std::begin(RangeTy()))>>
+void parallelSort(RangeTy &&R, const Comparator &Comp = Comparator()) {
+ parallelSort(std::begin(R), std::end(R), Comp);
}
-template <class IndexTy, class FuncTy>
-void for_each_n(parallel_execution_policy policy, IndexTy Begin, IndexTy End,
- FuncTy Fn) {
- detail::parallel_for_each_n(Begin, End, Fn);
+template <class RangeTy, class FuncTy>
+void parallelForEach(RangeTy &&R, FuncTy Fn) {
+ parallelForEach(std::begin(R), std::end(R), Fn);
}
-#endif
-} // namespace parallel
} // namespace llvm
#endif // LLVM_SUPPORT_PARALLEL_H
diff --git a/llvm/include/llvm/Support/Path.h b/llvm/include/llvm/Support/Path.h
index 97955f882d51e..83bca5b70bc21 100644
--- a/llvm/include/llvm/Support/Path.h
+++ b/llvm/include/llvm/Support/Path.h
@@ -47,7 +47,7 @@ enum class Style { windows, posix, native };
/// foo/ => foo,.
/// /foo/bar => /,foo,bar
/// ../ => ..,.
-/// C:\foo\bar => C:,/,foo,bar
+/// C:\foo\bar => C:,\,foo,bar
/// @endcode
class const_iterator
: public iterator_facade_base<const_iterator, std::input_iterator_tag,
@@ -153,32 +153,26 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
/// @code
/// /foo, /old, /new => /foo
/// /old, /old, /new => /new
-/// /old, /old/, /new, false => /old
-/// /old, /old/, /new, true => /new
+/// /old, /old/, /new => /old
/// /old/foo, /old, /new => /new/foo
/// /old/foo, /old/, /new => /new/foo
/// /old/foo, /old/, /new/ => /new/foo
/// /oldfoo, /old, /new => /oldfoo
/// /foo, <empty>, /new => /new/foo
/// /foo, <empty>, new => new/foo
-/// /old/foo, /old, <empty>, false => /foo
-/// /old/foo, /old, <empty>, true => 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. Any trailing
-/// path separator is ignored if strict is true.
+/// @param OldPrefix The path prefix to strip from \a Path.
/// @param NewPrefix The path prefix to replace \a NewPrefix with.
-/// @param style The path separator style
-/// @param strict If strict is true, a directory separator following
-/// \a OldPrefix will also be stripped. Otherwise, directory
-/// separators will only be matched and stripped when present
-/// in \a OldPrefix.
+/// @param style The style used to match the prefix. Exact match using
+/// Posix style, case/separator insensitive match for Windows style.
/// @result true if \a Path begins with OldPrefix
-bool replace_path_prefix(SmallVectorImpl<char> &Path,
- const StringRef &OldPrefix, const StringRef &NewPrefix,
- Style style = Style::native, bool strict = false);
+bool replace_path_prefix(SmallVectorImpl<char> &Path, StringRef OldPrefix,
+ StringRef NewPrefix,
+ Style style = Style::native);
/// Append to path.
///
@@ -377,6 +371,20 @@ void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result);
/// @result True if a home directory is set, false otherwise.
bool home_directory(SmallVectorImpl<char> &result);
+/// Get the directory where packages should read user-specific configurations.
+/// e.g. $XDG_CONFIG_HOME.
+///
+/// @param result Holds the resulting path name.
+/// @result True if the appropriate path was determined, it need not exist.
+bool user_config_directory(SmallVectorImpl<char> &result);
+
+/// Get the directory where installed packages should put their
+/// machine-local cache, e.g. $XDG_CACHE_HOME.
+///
+/// @param result Holds the resulting path name.
+/// @result True if the appropriate path was determined, it need not exist.
+bool cache_directory(SmallVectorImpl<char> &result);
+
/// Has root name?
///
/// root_name != ""
@@ -468,10 +476,6 @@ StringRef remove_leading_dotslash(StringRef path, Style style = Style::native);
bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot = false,
Style style = Style::native);
-#if defined(_WIN32)
-std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16);
-#endif
-
} // end namespace path
} // end namespace sys
} // end namespace llvm
diff --git a/llvm/include/llvm/Support/PointerLikeTypeTraits.h b/llvm/include/llvm/Support/PointerLikeTypeTraits.h
index 1e7e5b53ca657..1b15f930bd87d 100644
--- a/llvm/include/llvm/Support/PointerLikeTypeTraits.h
+++ b/llvm/include/llvm/Support/PointerLikeTypeTraits.h
@@ -15,7 +15,7 @@
#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
#include "llvm/Support/DataTypes.h"
-#include <assert.h>
+#include <cassert>
#include <type_traits>
namespace llvm {
@@ -37,8 +37,9 @@ template <typename T, typename U = void> struct HasPointerLikeTypeTraits {
};
// sizeof(T) is valid only for a complete T.
-template <typename T> struct HasPointerLikeTypeTraits<
- T, decltype((sizeof(PointerLikeTypeTraits<T>) + sizeof(T)), void())> {
+template <typename T>
+struct HasPointerLikeTypeTraits<
+ T, decltype((sizeof(PointerLikeTypeTraits<T>) + sizeof(T)), void())> {
static const bool value = true;
};
@@ -56,7 +57,8 @@ 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 };
+ static constexpr int NumLowBitsAvailable =
+ detail::ConstantLog2<alignof(T)>::value;
};
template <> struct PointerLikeTypeTraits<void *> {
@@ -70,7 +72,7 @@ template <> struct PointerLikeTypeTraits<void *> {
///
/// All clients should use assertions to do a run-time check to ensure that
/// this is actually true.
- enum { NumLowBitsAvailable = 2 };
+ static constexpr int NumLowBitsAvailable = 2;
};
// Provide PointerLikeTypeTraits for const things.
@@ -83,7 +85,7 @@ template <typename T> struct PointerLikeTypeTraits<const T> {
static inline const T getFromVoidPointer(const void *P) {
return NonConst::getFromVoidPointer(const_cast<void *>(P));
}
- enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable };
+ static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable;
};
// Provide PointerLikeTypeTraits for const pointers.
@@ -96,7 +98,7 @@ template <typename T> struct PointerLikeTypeTraits<const T *> {
static inline const T *getFromVoidPointer(const void *P) {
return NonConst::getFromVoidPointer(const_cast<void *>(P));
}
- enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable };
+ static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable;
};
// Provide PointerLikeTypeTraits for uintptr_t.
@@ -108,7 +110,7 @@ template <> struct PointerLikeTypeTraits<uintptr_t> {
return reinterpret_cast<uintptr_t>(P);
}
// No bits are available!
- enum { NumLowBitsAvailable = 0 };
+ static constexpr int NumLowBitsAvailable = 0;
};
/// Provide suitable custom traits struct for function pointers.
@@ -121,7 +123,8 @@ template <> struct PointerLikeTypeTraits<uintptr_t> {
/// potentially use alignment attributes on functions to satisfy that.
template <int Alignment, typename FunctionPointerT>
struct FunctionPointerLikeTypeTraits {
- enum { NumLowBitsAvailable = detail::ConstantLog2<Alignment>::value };
+ static constexpr int NumLowBitsAvailable =
+ detail::ConstantLog2<Alignment>::value;
static inline void *getAsVoidPointer(FunctionPointerT P) {
assert((reinterpret_cast<uintptr_t>(P) &
~((uintptr_t)-1 << NumLowBitsAvailable)) == 0 &&
diff --git a/llvm/include/llvm/Support/PrettyStackTrace.h b/llvm/include/llvm/Support/PrettyStackTrace.h
index 6eb070b2297ec..ac25cffde051c 100644
--- a/llvm/include/llvm/Support/PrettyStackTrace.h
+++ b/llvm/include/llvm/Support/PrettyStackTrace.h
@@ -37,6 +37,13 @@ namespace llvm {
/// \see PrettyStackTraceEntry
void EnablePrettyStackTraceOnSigInfoForThisThread(bool ShouldEnable = true);
+ /// Replaces the generic bug report message that is output upon
+ /// a crash.
+ void setBugReportMsg(const char *Msg);
+
+ /// Get the bug report message that will be output upon a crash.
+ const char *getBugReportMsg();
+
/// PrettyStackTraceEntry - This class is used to represent a frame of the
/// "pretty" stack trace that is dumped when a program crashes. You can define
/// subclasses of this and declare them on the program stack: when they are
diff --git a/llvm/include/llvm/Support/Process.h b/llvm/include/llvm/Support/Process.h
index 67e37912519bd..0ba6d58ba287a 100644
--- a/llvm/include/llvm/Support/Process.h
+++ b/llvm/include/llvm/Support/Process.h
@@ -25,7 +25,7 @@
#define LLVM_SUPPORT_PROCESS_H
#include "llvm/ADT/Optional.h"
-#include "llvm/Support/Allocator.h"
+#include "llvm/Support/AllocatorBase.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Error.h"
@@ -42,6 +42,11 @@ namespace sys {
/// current executing process.
class Process {
public:
+ using Pid = int32_t;
+
+ /// Get the process's identifier.
+ static Pid getProcessId();
+
/// Get the process's page size.
/// This may fail if the underlying syscall returns an error. In most cases,
/// page size information is used for optimization, and this error can be
@@ -201,6 +206,12 @@ public:
/// Get the result of a process wide random number generator. The
/// generator will be automatically seeded in non-deterministic fashion.
static unsigned GetRandomNumber();
+
+ /// Equivalent to ::exit(), except when running inside a CrashRecoveryContext.
+ /// In that case, the control flow will resume after RunSafely(), like for a
+ /// crash, rather than exiting the current process.
+ LLVM_ATTRIBUTE_NORETURN
+ static void Exit(int RetCode);
};
}
diff --git a/llvm/include/llvm/Support/Program.h b/llvm/include/llvm/Support/Program.h
index 6b2315c5da8d0..dbda064cda058 100644
--- a/llvm/include/llvm/Support/Program.h
+++ b/llvm/include/llvm/Support/Program.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/ErrorOr.h"
+#include <chrono>
#include <system_error>
namespace llvm {
@@ -52,6 +53,13 @@ namespace sys {
ProcessInfo();
};
+ /// This struct encapsulates information about a process execution.
+ struct ProcessStatistics {
+ std::chrono::microseconds TotalTime;
+ std::chrono::microseconds UserTime;
+ uint64_t PeakMemory = 0; ///< Maximum resident set size in KiB.
+ };
+
/// Find the first executable file \p Name in \p Paths.
///
/// This does not perform hashing as a shell would but instead stats each PATH
@@ -116,10 +124,14 @@ namespace sys {
///< string instance in which error messages will be returned. If the
///< string is non-empty upon return an error occurred while invoking the
///< program.
- bool *ExecutionFailed = nullptr);
+ bool *ExecutionFailed = nullptr,
+ Optional<ProcessStatistics> *ProcStat = nullptr ///< If non-zero, provides
+ /// a pointer to a structure in which process execution statistics will be
+ /// stored.
+ );
/// Similar to ExecuteAndWait, but returns immediately.
- /// @returns The \see ProcessInfo of the newly launced process.
+ /// @returns The \see ProcessInfo of the newly launched process.
/// \note On Microsoft Windows systems, users will need to either call
/// \see Wait until the process finished execution or win32 CloseHandle() API
/// on ProcessInfo.ProcessHandle to avoid memory leaks.
@@ -182,18 +194,24 @@ namespace sys {
/// \note Users of this function should always check the ReturnCode member of
/// the \see ProcessInfo returned from this function.
ProcessInfo Wait(
- const ProcessInfo &PI, ///< The child process that should be waited on.
+ const ProcessInfo &PI, ///< The child process that should be waited on.
unsigned SecondsToWait, ///< If non-zero, this specifies the amount of
///< time to wait for the child process to exit. If the time expires, the
///< child is killed and this function returns. If zero, this function
///< will perform a non-blocking wait on the child process.
bool WaitUntilTerminates, ///< If true, ignores \p SecondsToWait and waits
///< until child has terminated.
- std::string *ErrMsg = nullptr ///< If non-zero, provides a pointer to a
+ std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a
///< string instance in which error messages will be returned. If the
///< string is non-empty upon return an error occurred while invoking the
///< program.
- );
+ Optional<ProcessStatistics> *ProcStat = nullptr ///< If non-zero, provides
+ /// a pointer to a structure in which process execution statistics will be
+ /// stored.
+ );
+
+ /// Print a command argument, and optionally quote it.
+ void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote);
#if defined(_WIN32)
/// Given a list of command line arguments, quote and escape them as necessary
diff --git a/llvm/include/llvm/Support/RISCVAttributeParser.h b/llvm/include/llvm/Support/RISCVAttributeParser.h
new file mode 100644
index 0000000000000..3e629419a7e9b
--- /dev/null
+++ b/llvm/include/llvm/Support/RISCVAttributeParser.h
@@ -0,0 +1,37 @@
+//===-- RISCVAttributeParser.h - RISCV Attribute Parser ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_RISCVATTRIBUTEPARSER_H
+#define LLVM_SUPPORT_RISCVATTRIBUTEPARSER_H
+
+#include "llvm/Support/ELFAttributeParser.h"
+#include "llvm/Support/RISCVAttributes.h"
+
+namespace llvm {
+class RISCVAttributeParser : public ELFAttributeParser {
+ struct DisplayHandler {
+ RISCVAttrs::AttrType attribute;
+ Error (RISCVAttributeParser::*routine)(unsigned);
+ };
+ static const DisplayHandler displayRoutines[];
+
+ Error handler(uint64_t tag, bool &handled) override;
+
+ Error unalignedAccess(unsigned tag);
+ Error stackAlign(unsigned tag);
+
+public:
+ RISCVAttributeParser(ScopedPrinter *sw)
+ : ELFAttributeParser(sw, RISCVAttrs::RISCVAttributeTags, "riscv") {}
+ RISCVAttributeParser()
+ : ELFAttributeParser(RISCVAttrs::RISCVAttributeTags, "riscv") {}
+};
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/Support/RISCVAttributes.h b/llvm/include/llvm/Support/RISCVAttributes.h
new file mode 100644
index 0000000000000..caded9519b668
--- /dev/null
+++ b/llvm/include/llvm/Support/RISCVAttributes.h
@@ -0,0 +1,44 @@
+//===-- RISCVAttributes.h - RISCV Attributes --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains enumerations for RISCV attributes as defined in RISC-V
+// ELF psABI specification.
+//
+// RISC-V ELF psABI specification
+//
+// https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_SUPPORT_RISCVATTRIBUTES_H
+#define LLVM_SUPPORT_RISCVATTRIBUTES_H
+
+#include "llvm/Support/ELFAttributes.h"
+
+namespace llvm {
+namespace RISCVAttrs {
+
+extern const TagNameMap RISCVAttributeTags;
+
+enum AttrType : unsigned {
+ // Attribute types in ELF/.riscv.attributes.
+ STACK_ALIGN = 4,
+ ARCH = 5,
+ UNALIGNED_ACCESS = 6,
+ PRIV_SPEC = 8,
+ PRIV_SPEC_MINOR = 10,
+ PRIV_SPEC_REVISION = 12,
+};
+
+enum StackAlign { ALIGN_4 = 4, ALIGN_16 = 16 };
+
+enum { NOT_ALLOWED = 0, ALLOWED = 1 };
+
+} // namespace RISCVAttrs
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/Support/Regex.h b/llvm/include/llvm/Support/Regex.h
index b2620ab4cfc93..ae4b9516f194e 100644
--- a/llvm/include/llvm/Support/Regex.h
+++ b/llvm/include/llvm/Support/Regex.h
@@ -16,6 +16,7 @@
#ifndef LLVM_SUPPORT_REGEX_H
#define LLVM_SUPPORT_REGEX_H
+#include "llvm/ADT/BitmaskEnum.h"
#include <string>
struct llvm_regex;
@@ -26,20 +27,22 @@ namespace llvm {
class Regex {
public:
- enum {
- NoFlags=0,
+ enum RegexFlags : unsigned {
+ NoFlags = 0,
/// Compile for matching that ignores upper/lower case distinctions.
- IgnoreCase=1,
+ IgnoreCase = 1,
/// Compile for newline-sensitive matching. With this flag '[^' bracket
/// expressions and '.' never match newline. A ^ anchor matches the
/// null string after any newline in the string in addition to its normal
/// function, and the $ anchor matches the null string before any
/// newline in the string in addition to its normal function.
- Newline=2,
+ Newline = 2,
/// By default, the POSIX extended regular expression (ERE) syntax is
/// assumed. Pass this flag to turn on basic regular expressions (BRE)
/// instead.
- BasicRegex=4
+ BasicRegex = 4,
+
+ LLVM_MARK_AS_BITMASK_ENUM(BasicRegex)
};
Regex();
@@ -47,7 +50,8 @@ namespace llvm {
///
/// \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(StringRef Regex, RegexFlags Flags = NoFlags);
+ Regex(StringRef Regex, unsigned Flags);
Regex(const Regex &) = delete;
Regex &operator=(Regex regex) {
std::swap(preg, regex.preg);
diff --git a/llvm/include/llvm/Support/SHA1.h b/llvm/include/llvm/Support/SHA1.h
index 2cfbd21793645..efd8513cc201f 100644
--- a/llvm/include/llvm/Support/SHA1.h
+++ b/llvm/include/llvm/Support/SHA1.h
@@ -15,14 +15,12 @@
#ifndef LLVM_SUPPORT_SHA1_H
#define LLVM_SUPPORT_SHA1_H
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-
#include <array>
#include <cstdint>
namespace llvm {
template <typename T> class ArrayRef;
+class StringRef;
/// A class that wrap the SHA1 algorithm.
class SHA1 {
@@ -36,10 +34,7 @@ public:
void update(ArrayRef<uint8_t> Data);
/// Digest more data.
- void update(StringRef Str) {
- update(ArrayRef<uint8_t>((uint8_t *)const_cast<char *>(Str.data()),
- Str.size()));
- }
+ void update(StringRef Str);
/// Return a reference to the current raw 160-bits SHA1 for the digested data
/// since the last call to init(). This call will add data to the internal
diff --git a/llvm/include/llvm/Support/ScaledNumber.h b/llvm/include/llvm/Support/ScaledNumber.h
index 552da34f357b7..a5261e419986f 100644
--- a/llvm/include/llvm/Support/ScaledNumber.h
+++ b/llvm/include/llvm/Support/ScaledNumber.h
@@ -418,7 +418,7 @@ namespace llvm {
class raw_ostream;
class ScaledNumberBase {
public:
- static const int DefaultPrecision = 10;
+ static constexpr int DefaultPrecision = 10;
static void dump(uint64_t D, int16_t E, int Width);
static raw_ostream &print(raw_ostream &OS, uint64_t D, int16_t E, int Width,
@@ -499,7 +499,7 @@ public:
private:
typedef std::numeric_limits<DigitsType> DigitsLimits;
- static const int Width = sizeof(DigitsType) * 8;
+ static constexpr int Width = sizeof(DigitsType) * 8;
static_assert(Width <= 64, "invalid integer width for digits");
private:
diff --git a/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h b/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h
index b63b58e3a8ba9..62900b740b81b 100644
--- a/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h
+++ b/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h
@@ -44,7 +44,7 @@ public:
/// Construct a named SmallVectorMemoryBuffer from the given
/// SmallVector r-value and StringRef.
SmallVectorMemoryBuffer(SmallVectorImpl<char> &&SV, StringRef Name)
- : SV(std::move(SV)), BufferName(Name) {
+ : SV(std::move(SV)), BufferName(std::string(Name)) {
init(this->SV.begin(), this->SV.end(), false);
}
diff --git a/llvm/include/llvm/Support/SourceMgr.h b/llvm/include/llvm/Support/SourceMgr.h
index 1b005519e5d4b..a0bd3ca2e0c19 100644
--- a/llvm/include/llvm/Support/SourceMgr.h
+++ b/llvm/include/llvm/Support/SourceMgr.h
@@ -15,19 +15,9 @@
#ifndef LLVM_SUPPORT_SOURCEMGR_H
#define LLVM_SUPPORT_SOURCEMGR_H
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SMLoc.h"
-#include <algorithm>
-#include <cassert>
-#include <memory>
-#include <string>
-#include <utility>
#include <vector>
namespace llvm {
@@ -57,29 +47,29 @@ private:
/// 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 = PointerUnion<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>
+ ///
+ /// Since we're storing offsets into relatively small files (often smaller
+ /// than 2^8 or 2^16 bytes), we select the offset vector element type
+ /// dynamically based on the size of Buffer.
+ mutable void *OffsetCache = nullptr;
+
+ /// Look up a given \p Ptr in in the buffer, determining which line it came
+ /// from.
unsigned getLineNumber(const char *Ptr) const;
+ template <typename T>
+ unsigned getLineNumberSpecialized(const char *Ptr) const;
+
+ /// Return a pointer to the first character of the specified line number or
+ /// null if the line number is invalid.
+ const char *getPointerForLineNumber(unsigned LineNo) const;
+ template <typename T>
+ const char *getPointerForLineNumberSpecialized(unsigned LineNo) const;
/// This is the location of the parent include, or null if at the top level.
SMLoc IncludeLoc;
@@ -134,9 +124,7 @@ public:
return Buffers[i - 1].Buffer.get();
}
- unsigned getNumBuffers() const {
- return Buffers.size();
- }
+ unsigned getNumBuffers() const { return Buffers.size(); }
unsigned getMainFileID() const {
assert(getNumBuffers());
@@ -184,20 +172,24 @@ public:
std::pair<unsigned, unsigned> getLineAndColumn(SMLoc Loc,
unsigned BufferID = 0) const;
+ /// Given a line and column number in a mapped buffer, turn it into an SMLoc.
+ /// This will return a null SMLoc if the line/column location is invalid.
+ SMLoc FindLocForLineAndColumn(unsigned BufferID, unsigned LineNo,
+ unsigned ColNo);
+
/// Emit a message about the specified location with the specified string.
///
/// \param ShowColors Display colored messages if output is a terminal and
/// the default error handler is used.
- void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind,
- const Twine &Msg,
- ArrayRef<SMRange> Ranges = None,
- ArrayRef<SMFixIt> FixIts = None,
+ void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg,
+ ArrayRef<SMRange> Ranges = {},
+ ArrayRef<SMFixIt> FixIts = {},
bool ShowColors = true) const;
/// Emits a diagnostic to llvm::errs().
void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
- ArrayRef<SMRange> Ranges = None,
- ArrayRef<SMFixIt> FixIts = None,
+ ArrayRef<SMRange> Ranges = {},
+ ArrayRef<SMFixIt> FixIts = {},
bool ShowColors = true) const;
/// Emits a manually-constructed diagnostic to the given output stream.
@@ -213,8 +205,8 @@ public:
/// \param Msg If non-null, the kind of message (e.g., "error") which is
/// prefixed to the message.
SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
- ArrayRef<SMRange> Ranges = None,
- ArrayRef<SMFixIt> FixIts = None) const;
+ ArrayRef<SMRange> Ranges = {},
+ ArrayRef<SMFixIt> FixIts = {}) const;
/// Prints the names of included files and the line of the file they were
/// included from. A diagnostic handler can use this before printing its
@@ -232,17 +224,10 @@ class SMFixIt {
std::string Text;
public:
- // FIXME: Twine.str() is not very efficient.
- SMFixIt(SMLoc Loc, const Twine &Insertion)
- : Range(Loc, Loc), Text(Insertion.str()) {
- assert(Loc.isValid());
- }
+ SMFixIt(SMRange R, const Twine &Replacement);
- // FIXME: Twine.str() is not very efficient.
- SMFixIt(SMRange R, const Twine &Replacement)
- : Range(R), Text(Replacement.str()) {
- assert(R.isValid());
- }
+ SMFixIt(SMLoc Loc, const Twine &Replacement)
+ : SMFixIt(SMRange(Loc, Loc), Replacement) {}
StringRef getText() const { return Text; }
SMRange getRange() const { return Range; }
@@ -274,14 +259,13 @@ public:
SMDiagnostic() = default;
// Diagnostic with no location (e.g. file not found, command line arg error).
SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg)
- : Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {}
+ : Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {}
// Diagnostic with a location.
- SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN,
- int Line, int Col, SourceMgr::DiagKind Kind,
- StringRef Msg, StringRef LineStr,
- ArrayRef<std::pair<unsigned,unsigned>> Ranges,
- ArrayRef<SMFixIt> FixIts = None);
+ SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, int Line, int Col,
+ SourceMgr::DiagKind Kind, StringRef Msg, StringRef LineStr,
+ ArrayRef<std::pair<unsigned, unsigned>> Ranges,
+ ArrayRef<SMFixIt> FixIts = {});
const SourceMgr *getSourceMgr() const { return SM; }
SMLoc getLoc() const { return Loc; }
@@ -293,13 +277,9 @@ public:
StringRef getLineContents() const { return LineContents; }
ArrayRef<std::pair<unsigned, unsigned>> getRanges() const { return Ranges; }
- void addFixIt(const SMFixIt &Hint) {
- FixIts.push_back(Hint);
- }
+ void addFixIt(const SMFixIt &Hint) { FixIts.push_back(Hint); }
- ArrayRef<SMFixIt> getFixIts() const {
- return FixIts;
- }
+ ArrayRef<SMFixIt> getFixIts() const { return FixIts; }
void print(const char *ProgName, raw_ostream &S, bool ShowColors = true,
bool ShowKindLabel = true) const;
diff --git a/llvm/include/llvm/Support/SpecialCaseList.h b/llvm/include/llvm/Support/SpecialCaseList.h
index 5b5b7f6124d68..d022a8f53706a 100644
--- a/llvm/include/llvm/Support/SpecialCaseList.h
+++ b/llvm/include/llvm/Support/SpecialCaseList.h
@@ -7,8 +7,8 @@
//
// This is a utility class used to parse user-provided text files with
// "special case lists" for code sanitizers. Such files are used to
-// define an "ABI list" for DataFlowSanitizer and blacklists for sanitizers
-// like AddressSanitizer or UndefinedBehaviorSanitizer.
+// define an "ABI list" for DataFlowSanitizer and allow/exclusion lists for
+// sanitizers like AddressSanitizer or UndefinedBehaviorSanitizer.
//
// Empty lines and lines starting with "#" are ignored. Sections are defined
// using a '[section_name]' header and can be used to specify sanitizers the
@@ -19,18 +19,18 @@
// prefix:wildcard_expression[=category]
// If category is not specified, it is assumed to be empty string.
// Definitions of "prefix" and "category" are sanitizer-specific. For example,
-// sanitizer blacklists support prefixes "src", "fun" and "global".
+// sanitizer exclusion support prefixes "src", "fun" and "global".
// Wildcard expressions define, respectively, source files, functions or
// globals which shouldn't be instrumented.
// Examples of categories:
// "functional": used in DFSan to list functions with pure functional
// semantics.
-// "init": used in ASan blacklist to disable initialization-order bugs
+// "init": used in ASan exclusion list to disable initialization-order bugs
// detection for certain globals or source files.
// Full special case list file example:
// ---
// [address]
-// # Blacklisted items:
+// # Excluded items:
// fun:*_ZN4base6subtle*
// global:*global_with_bad_access_or_initialization*
// global:*global_with_initialization_issues*=init
@@ -52,18 +52,20 @@
#define LLVM_SUPPORT_SPECIALCASELIST_H
#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/TrigramIndex.h"
-#include "llvm/Support/VirtualFileSystem.h"
+#include <memory>
#include <string>
#include <vector>
namespace llvm {
class MemoryBuffer;
-class Regex;
class StringRef;
+namespace vfs {
+class FileSystem;
+}
+
class SpecialCaseList {
public:
/// Parses the special case list entries from files. On failure, returns
@@ -96,7 +98,7 @@ public:
/// @Prefix:<E>=@Category
/// \endcode
/// where @Query satisfies wildcard expression <E> in a given @Section.
- /// Returns zero if there is no blacklist entry corresponding to this
+ /// Returns zero if there is no exclusion entry corresponding to this
/// expression.
unsigned inSectionBlame(StringRef Section, StringRef Prefix, StringRef Query,
StringRef Category = StringRef()) const;
diff --git a/llvm/include/llvm/Support/StringPool.h b/llvm/include/llvm/Support/StringPool.h
deleted file mode 100644
index a4f45916f53d6..0000000000000
--- a/llvm/include/llvm/Support/StringPool.h
+++ /dev/null
@@ -1,139 +0,0 @@
-//===- StringPool.h - Interned string pool ----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares an interned string pool, which helps reduce the cost of
-// strings by using the same storage for identical strings.
-//
-// To intern a string:
-//
-// StringPool Pool;
-// PooledStringPtr Str = Pool.intern("wakka wakka");
-//
-// To use the value of an interned string, use operator bool and operator*:
-//
-// if (Str)
-// cerr << "the string is" << *Str << "\n";
-//
-// Pooled strings are immutable, but you can change a PooledStringPtr to point
-// to another instance. So that interned strings can eventually be freed,
-// strings in the string pool are reference-counted (automatically).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_STRINGPOOL_H
-#define LLVM_SUPPORT_STRINGPOOL_H
-
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include <cassert>
-
-namespace llvm {
-
- class PooledStringPtr;
-
- /// StringPool - An interned string pool. Use the intern method to add a
- /// string. Strings are removed automatically as PooledStringPtrs are
- /// destroyed.
- class StringPool {
- /// PooledString - This is the value of an entry in the pool's interning
- /// table.
- struct PooledString {
- StringPool *Pool = nullptr; ///< So the string can remove itself.
- unsigned Refcount = 0; ///< Number of referencing PooledStringPtrs.
-
- public:
- PooledString() = default;
- };
-
- friend class PooledStringPtr;
-
- using table_t = StringMap<PooledString>;
- using entry_t = StringMapEntry<PooledString>;
- table_t InternTable;
-
- public:
- StringPool();
- ~StringPool();
-
- /// intern - Adds a string to the pool and returns a reference-counted
- /// pointer to it. No additional memory is allocated if the string already
- /// exists in the pool.
- PooledStringPtr intern(StringRef Str);
-
- /// empty - Checks whether the pool is empty. Returns true if so.
- ///
- inline bool empty() const { return InternTable.empty(); }
- };
-
- /// PooledStringPtr - A pointer to an interned string. Use operator bool to
- /// test whether the pointer is valid, and operator * to get the string if so.
- /// This is a lightweight value class with storage requirements equivalent to
- /// a single pointer, but it does have reference-counting overhead when
- /// copied.
- class PooledStringPtr {
- using entry_t = StringPool::entry_t;
-
- entry_t *S = nullptr;
-
- public:
- PooledStringPtr() = default;
-
- explicit PooledStringPtr(entry_t *E) : S(E) {
- if (S) ++S->getValue().Refcount;
- }
-
- PooledStringPtr(const PooledStringPtr &That) : S(That.S) {
- if (S) ++S->getValue().Refcount;
- }
-
- PooledStringPtr &operator=(const PooledStringPtr &That) {
- if (S != That.S) {
- clear();
- S = That.S;
- if (S) ++S->getValue().Refcount;
- }
- return *this;
- }
-
- void clear() {
- if (!S)
- return;
- if (--S->getValue().Refcount == 0) {
- S->getValue().Pool->InternTable.remove(S);
- S->Destroy();
- }
- S = nullptr;
- }
-
- ~PooledStringPtr() { clear(); }
-
- inline const char *begin() const {
- assert(*this && "Attempt to dereference empty PooledStringPtr!");
- return S->getKeyData();
- }
-
- inline const char *end() const {
- assert(*this && "Attempt to dereference empty PooledStringPtr!");
- return S->getKeyData() + S->getKeyLength();
- }
-
- inline unsigned size() const {
- assert(*this && "Attempt to dereference empty PooledStringPtr!");
- return S->getKeyLength();
- }
-
- inline const char *operator*() const { return begin(); }
- inline explicit operator bool() const { return S != nullptr; }
-
- inline bool operator==(const PooledStringPtr &That) const { return S == That.S; }
- inline bool operator!=(const PooledStringPtr &That) const { return S != That.S; }
- };
-
-} // end namespace llvm
-
-#endif // LLVM_SUPPORT_STRINGPOOL_H
diff --git a/llvm/include/llvm/Support/SuffixTree.h b/llvm/include/llvm/Support/SuffixTree.h
new file mode 100644
index 0000000000000..67d513d032cef
--- /dev/null
+++ b/llvm/include/llvm/Support/SuffixTree.h
@@ -0,0 +1,350 @@
+//===- llvm/ADT/SuffixTree.h - Tree for substrings --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Suffix Tree class and Suffix Tree Node struct.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_SUPPORT_SUFFIXTREE_H
+#define LLVM_SUPPORT_SUFFIXTREE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Allocator.h"
+#include <vector>
+
+namespace llvm {
+
+/// Represents an undefined index in the suffix tree.
+const unsigned EmptyIdx = -1;
+
+/// A node in a suffix tree which represents a substring or suffix.
+///
+/// Each node has either no children or at least two children, with the root
+/// being a exception in the empty tree.
+///
+/// Children are represented as a map between unsigned integers and nodes. If
+/// a node N has a child M on unsigned integer k, then the mapping represented
+/// by N is a proper prefix of the mapping represented by M. Note that this,
+/// although similar to a trie is somewhat different: each node stores a full
+/// substring of the full mapping rather than a single character state.
+///
+/// Each internal node contains a pointer to the internal node representing
+/// the same string, but with the first character chopped off. This is stored
+/// in \p Link. Each leaf node stores the start index of its respective
+/// suffix in \p SuffixIdx.
+struct SuffixTreeNode {
+
+ /// The children of this node.
+ ///
+ /// A child existing on an unsigned integer implies that from the mapping
+ /// represented by the current node, there is a way to reach another
+ /// mapping by tacking that character on the end of the current string.
+ llvm::DenseMap<unsigned, SuffixTreeNode *> Children;
+
+ /// The start index of this node's substring in the main string.
+ unsigned StartIdx = EmptyIdx;
+
+ /// The end index of this node's substring in the main string.
+ ///
+ /// Every leaf node must have its \p EndIdx incremented at the end of every
+ /// step in the construction algorithm. To avoid having to update O(N)
+ /// nodes individually at the end of every step, the end index is stored
+ /// as a pointer.
+ unsigned *EndIdx = nullptr;
+
+ /// For leaves, the start index of the suffix represented by this node.
+ ///
+ /// For all other nodes, this is ignored.
+ unsigned SuffixIdx = EmptyIdx;
+
+ /// For internal nodes, a pointer to the internal node representing
+ /// the same sequence with the first character chopped off.
+ ///
+ /// This acts as a shortcut in Ukkonen's algorithm. One of the things that
+ /// Ukkonen's algorithm does to achieve linear-time construction is
+ /// keep track of which node the next insert should be at. This makes each
+ /// insert O(1), and there are a total of O(N) inserts. The suffix link
+ /// helps with inserting children of internal nodes.
+ ///
+ /// Say we add a child to an internal node with associated mapping S. The
+ /// next insertion must be at the node representing S - its first character.
+ /// This is given by the way that we iteratively build the tree in Ukkonen's
+ /// algorithm. The main idea is to look at the suffixes of each prefix in the
+ /// string, starting with the longest suffix of the prefix, and ending with
+ /// the shortest. Therefore, if we keep pointers between such nodes, we can
+ /// move to the next insertion point in O(1) time. If we don't, then we'd
+ /// have to query from the root, which takes O(N) time. This would make the
+ /// construction algorithm O(N^2) rather than O(N).
+ SuffixTreeNode *Link = nullptr;
+
+ /// The length of the string formed by concatenating the edge labels from the
+ /// root to this node.
+ unsigned ConcatLen = 0;
+
+ /// Returns true if this node is a leaf.
+ bool isLeaf() const { return SuffixIdx != EmptyIdx; }
+
+ /// Returns true if this node is the root of its owning \p SuffixTree.
+ bool isRoot() const { return StartIdx == EmptyIdx; }
+
+ /// Return the number of elements in the substring associated with this node.
+ size_t size() const {
+
+ // Is it the root? If so, it's the empty string so return 0.
+ if (isRoot())
+ return 0;
+
+ assert(*EndIdx != EmptyIdx && "EndIdx is undefined!");
+
+ // Size = the number of elements in the string.
+ // For example, [0 1 2 3] has length 4, not 3. 3-0 = 3, so we have 3-0+1.
+ return *EndIdx - StartIdx + 1;
+ }
+
+ SuffixTreeNode(unsigned StartIdx, unsigned *EndIdx, SuffixTreeNode *Link)
+ : StartIdx(StartIdx), EndIdx(EndIdx), Link(Link) {}
+
+ SuffixTreeNode() {}
+};
+
+/// A data structure for fast substring queries.
+///
+/// Suffix trees represent the suffixes of their input strings in their leaves.
+/// A suffix tree is a type of compressed trie structure where each node
+/// represents an entire substring rather than a single character. Each leaf
+/// of the tree is a suffix.
+///
+/// A suffix tree can be seen as a type of state machine where each state is a
+/// substring of the full string. The tree is structured so that, for a string
+/// of length N, there are exactly N leaves in the tree. This structure allows
+/// us to quickly find repeated substrings of the input string.
+///
+/// In this implementation, a "string" is a vector of unsigned integers.
+/// These integers may result from hashing some data type. A suffix tree can
+/// contain 1 or many strings, which can then be queried as one large string.
+///
+/// The suffix tree is implemented using Ukkonen's algorithm for linear-time
+/// suffix tree construction. Ukkonen's algorithm is explained in more detail
+/// in the paper by Esko Ukkonen "On-line construction of suffix trees. The
+/// paper is available at
+///
+/// https://www.cs.helsinki.fi/u/ukkonen/SuffixT1withFigs.pdf
+class SuffixTree {
+public:
+ /// Each element is an integer representing an instruction in the module.
+ llvm::ArrayRef<unsigned> Str;
+
+ /// A repeated substring in the tree.
+ struct RepeatedSubstring {
+ /// The length of the string.
+ unsigned Length;
+
+ /// The start indices of each occurrence.
+ std::vector<unsigned> StartIndices;
+ };
+
+private:
+ /// Maintains each node in the tree.
+ llvm::SpecificBumpPtrAllocator<SuffixTreeNode> NodeAllocator;
+
+ /// The root of the suffix tree.
+ ///
+ /// The root represents the empty string. It is maintained by the
+ /// \p NodeAllocator like every other node in the tree.
+ SuffixTreeNode *Root = nullptr;
+
+ /// Maintains the end indices of the internal nodes in the tree.
+ ///
+ /// Each internal node is guaranteed to never have its end index change
+ /// during the construction algorithm; however, leaves must be updated at
+ /// every step. Therefore, we need to store leaf end indices by reference
+ /// to avoid updating O(N) leaves at every step of construction. Thus,
+ /// every internal node must be allocated its own end index.
+ llvm::BumpPtrAllocator InternalEndIdxAllocator;
+
+ /// The end index of each leaf in the tree.
+ unsigned LeafEndIdx = -1;
+
+ /// Helper struct which keeps track of the next insertion point in
+ /// Ukkonen's algorithm.
+ struct ActiveState {
+ /// The next node to insert at.
+ SuffixTreeNode *Node = nullptr;
+
+ /// The index of the first character in the substring currently being added.
+ unsigned Idx = EmptyIdx;
+
+ /// The length of the substring we have to add at the current step.
+ unsigned Len = 0;
+ };
+
+ /// The point the next insertion will take place at in the
+ /// construction algorithm.
+ ActiveState Active;
+
+ /// Allocate a leaf node and add it to the tree.
+ ///
+ /// \param Parent The parent of this node.
+ /// \param StartIdx The start index of this node's associated string.
+ /// \param Edge The label on the edge leaving \p Parent to this node.
+ ///
+ /// \returns A pointer to the allocated leaf node.
+ SuffixTreeNode *insertLeaf(SuffixTreeNode &Parent, unsigned StartIdx,
+ unsigned Edge);
+
+ /// Allocate an internal node and add it to the tree.
+ ///
+ /// \param Parent The parent of this node. Only null when allocating the root.
+ /// \param StartIdx The start index of this node's associated string.
+ /// \param EndIdx The end index of this node's associated string.
+ /// \param Edge The label on the edge leaving \p Parent to this node.
+ ///
+ /// \returns A pointer to the allocated internal node.
+ SuffixTreeNode *insertInternalNode(SuffixTreeNode *Parent, unsigned StartIdx,
+ unsigned EndIdx, unsigned Edge);
+
+ /// Set the suffix indices of the leaves to the start indices of their
+ /// respective suffixes.
+ void setSuffixIndices();
+
+ /// Construct the suffix tree for the prefix of the input ending at
+ /// \p EndIdx.
+ ///
+ /// Used to construct the full suffix tree iteratively. At the end of each
+ /// step, the constructed suffix tree is either a valid suffix tree, or a
+ /// suffix tree with implicit suffixes. At the end of the final step, the
+ /// suffix tree is a valid tree.
+ ///
+ /// \param EndIdx The end index of the current prefix in the main string.
+ /// \param SuffixesToAdd The number of suffixes that must be added
+ /// to complete the suffix tree at the current phase.
+ ///
+ /// \returns The number of suffixes that have not been added at the end of
+ /// this step.
+ unsigned extend(unsigned EndIdx, unsigned SuffixesToAdd);
+
+public:
+ /// Construct a suffix tree from a sequence of unsigned integers.
+ ///
+ /// \param Str The string to construct the suffix tree for.
+ SuffixTree(const std::vector<unsigned> &Str);
+
+ /// Iterator for finding all repeated substrings in the suffix tree.
+ struct RepeatedSubstringIterator {
+ private:
+ /// The current node we're visiting.
+ SuffixTreeNode *N = nullptr;
+
+ /// The repeated substring associated with this node.
+ RepeatedSubstring RS;
+
+ /// The nodes left to visit.
+ std::vector<SuffixTreeNode *> ToVisit;
+
+ /// The minimum length of a repeated substring to find.
+ /// Since we're outlining, we want at least two instructions in the range.
+ /// FIXME: This may not be true for targets like X86 which support many
+ /// instruction lengths.
+ const unsigned MinLength = 2;
+
+ /// Move the iterator to the next repeated substring.
+ void advance() {
+ // Clear the current state. If we're at the end of the range, then this
+ // is the state we want to be in.
+ RS = RepeatedSubstring();
+ N = nullptr;
+
+ // Each leaf node represents a repeat of a string.
+ std::vector<SuffixTreeNode *> LeafChildren;
+
+ // Continue visiting nodes until we find one which repeats more than once.
+ while (!ToVisit.empty()) {
+ SuffixTreeNode *Curr = ToVisit.back();
+ ToVisit.pop_back();
+ LeafChildren.clear();
+
+ // Keep track of the length of the string associated with the node. If
+ // it's too short, we'll quit.
+ unsigned Length = Curr->ConcatLen;
+
+ // Iterate over each child, saving internal nodes for visiting, and
+ // leaf nodes in LeafChildren. Internal nodes represent individual
+ // strings, which may repeat.
+ for (auto &ChildPair : Curr->Children) {
+ // Save all of this node's children for processing.
+ if (!ChildPair.second->isLeaf())
+ ToVisit.push_back(ChildPair.second);
+
+ // It's not an internal node, so it must be a leaf. If we have a
+ // long enough string, then save the leaf children.
+ else if (Length >= MinLength)
+ LeafChildren.push_back(ChildPair.second);
+ }
+
+ // The root never represents a repeated substring. If we're looking at
+ // that, then skip it.
+ if (Curr->isRoot())
+ continue;
+
+ // Do we have any repeated substrings?
+ if (LeafChildren.size() >= 2) {
+ // Yes. Update the state to reflect this, and then bail out.
+ N = Curr;
+ RS.Length = Length;
+ for (SuffixTreeNode *Leaf : LeafChildren)
+ RS.StartIndices.push_back(Leaf->SuffixIdx);
+ break;
+ }
+ }
+
+ // At this point, either NewRS is an empty RepeatedSubstring, or it was
+ // set in the above loop. Similarly, N is either nullptr, or the node
+ // associated with NewRS.
+ }
+
+ public:
+ /// Return the current repeated substring.
+ RepeatedSubstring &operator*() { return RS; }
+
+ RepeatedSubstringIterator &operator++() {
+ advance();
+ return *this;
+ }
+
+ RepeatedSubstringIterator operator++(int I) {
+ RepeatedSubstringIterator It(*this);
+ advance();
+ return It;
+ }
+
+ bool operator==(const RepeatedSubstringIterator &Other) {
+ return N == Other.N;
+ }
+ bool operator!=(const RepeatedSubstringIterator &Other) {
+ return !(*this == Other);
+ }
+
+ RepeatedSubstringIterator(SuffixTreeNode *N) : N(N) {
+ // Do we have a non-null node?
+ if (N) {
+ // Yes. At the first step, we need to visit all of N's children.
+ // Note: This means that we visit N last.
+ ToVisit.push_back(N);
+ advance();
+ }
+ }
+ };
+
+ typedef RepeatedSubstringIterator iterator;
+ iterator begin() { return iterator(Root); }
+ iterator end() { return iterator(nullptr); }
+};
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_SUFFIXTREE_H
diff --git a/llvm/include/llvm/Support/SwapByteOrder.h b/llvm/include/llvm/Support/SwapByteOrder.h
index 6cec87006c02c..0e544fc7e71ee 100644
--- a/llvm/include/llvm/Support/SwapByteOrder.h
+++ b/llvm/include/llvm/Support/SwapByteOrder.h
@@ -14,15 +14,15 @@
#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H
#define LLVM_SUPPORT_SWAPBYTEORDER_H
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
#include <cstddef>
+#include <cstdint>
#include <type_traits>
#if defined(_MSC_VER) && !defined(_DEBUG)
#include <stdlib.h>
#endif
-#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__)
+#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \
+ defined(__EMSCRIPTEN__)
#include <endian.h>
#elif defined(_AIX)
#include <sys/machine.h>
@@ -36,6 +36,10 @@
#else
#define BYTE_ORDER LITTLE_ENDIAN
#endif
+#elif defined(__MVS__)
+#define BIG_ENDIAN 4321
+#define LITTLE_ENDIAN 1234
+#define BYTE_ORDER BIG_ENDIAN
#else
#if !defined(BYTE_ORDER) && !defined(_WIN32)
#include <machine/endian.h>
@@ -43,19 +47,10 @@
#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
+/// ByteSwap_16 - This function returns a byte-swapped representation of
/// the 16-bit argument.
-inline uint16_t SwapByteOrder_16(uint16_t value) {
+inline uint16_t ByteSwap_16(uint16_t value) {
#if defined(_MSC_VER) && !defined(_DEBUG)
// The DLL version of the runtime lacks these functions (bug!?), but in a
// release build they're replaced with BSWAP instructions anyway.
@@ -68,7 +63,7 @@ inline uint16_t SwapByteOrder_16(uint16_t value) {
}
/// This function returns a byte-swapped representation of the 32-bit argument.
-inline uint32_t SwapByteOrder_32(uint32_t value) {
+inline uint32_t ByteSwap_32(uint32_t value) {
#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
return __builtin_bswap32(value);
#elif defined(_MSC_VER) && !defined(_DEBUG)
@@ -83,43 +78,54 @@ inline uint32_t SwapByteOrder_32(uint32_t value) {
}
/// This function returns a byte-swapped representation of the 64-bit argument.
-inline uint64_t SwapByteOrder_64(uint64_t value) {
+inline uint64_t ByteSwap_64(uint64_t value) {
#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
return __builtin_bswap64(value);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_uint64(value);
#else
- uint64_t Hi = SwapByteOrder_32(uint32_t(value));
- uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32));
+ uint64_t Hi = ByteSwap_32(uint32_t(value));
+ uint32_t Lo = ByteSwap_32(uint32_t(value >> 32));
return (Hi << 32) | Lo;
#endif
}
+namespace sys {
+
+#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
+constexpr bool IsBigEndianHost = true;
+#else
+constexpr bool IsBigEndianHost = false;
+#endif
+
+static const bool IsLittleEndianHost = !IsBigEndianHost;
+
inline unsigned char getSwappedBytes(unsigned char C) { return C; }
inline signed char getSwappedBytes(signed char C) { return C; }
inline char getSwappedBytes(char C) { return C; }
-inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); }
-inline signed short getSwappedBytes( signed short C) { return SwapByteOrder_16(C); }
+inline unsigned short getSwappedBytes(unsigned short C) { return ByteSwap_16(C); }
+inline signed short getSwappedBytes( signed short C) { return ByteSwap_16(C); }
-inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); }
-inline signed int getSwappedBytes( signed int C) { return SwapByteOrder_32(C); }
+inline unsigned int getSwappedBytes(unsigned int C) { return ByteSwap_32(C); }
+inline signed int getSwappedBytes( signed int C) { return ByteSwap_32(C); }
-#if __LONG_MAX__ == __INT_MAX__
-inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); }
-inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_32(C); }
-#elif __LONG_MAX__ == __LONG_LONG_MAX__
-inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); }
-inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); }
-#else
-#error "Unknown long size!"
-#endif
+inline unsigned long getSwappedBytes(unsigned long C) {
+ // Handle LLP64 and LP64 platforms.
+ return sizeof(long) == sizeof(int) ? ByteSwap_32((uint32_t)C)
+ : ByteSwap_64((uint64_t)C);
+}
+inline signed long getSwappedBytes(signed long C) {
+ // Handle LLP64 and LP64 platforms.
+ return sizeof(long) == sizeof(int) ? ByteSwap_32((uint32_t)C)
+ : ByteSwap_64((uint64_t)C);
+}
inline unsigned long long getSwappedBytes(unsigned long long C) {
- return SwapByteOrder_64(C);
+ return ByteSwap_64(C);
}
inline signed long long getSwappedBytes(signed long long C) {
- return SwapByteOrder_64(C);
+ return ByteSwap_64(C);
}
inline float getSwappedBytes(float C) {
@@ -128,7 +134,7 @@ inline float getSwappedBytes(float C) {
float f;
} in, out;
in.f = C;
- out.i = SwapByteOrder_32(in.i);
+ out.i = ByteSwap_32(in.i);
return out.f;
}
@@ -138,15 +144,14 @@ inline double getSwappedBytes(double C) {
double d;
} in, out;
in.d = C;
- out.i = SwapByteOrder_64(in.i);
+ out.i = ByteSwap_64(in.i);
return out.d;
}
template <typename T>
-inline typename std::enable_if<std::is_enum<T>::value, T>::type
-getSwappedBytes(T C) {
+inline std::enable_if_t<std::is_enum<T>::value, T> getSwappedBytes(T C) {
return static_cast<T>(
- getSwappedBytes(static_cast<typename std::underlying_type<T>::type>(C)));
+ getSwappedBytes(static_cast<std::underlying_type_t<T>>(C)));
}
template<typename T>
diff --git a/llvm/include/llvm/Support/SystemUtils.h b/llvm/include/llvm/Support/SystemUtils.h
index 77deddb9ee1c2..786bea3fcfae6 100644
--- a/llvm/include/llvm/Support/SystemUtils.h
+++ b/llvm/include/llvm/Support/SystemUtils.h
@@ -15,17 +15,16 @@
#define LLVM_SUPPORT_SYSTEMUTILS_H
namespace llvm {
- class raw_ostream;
+class raw_ostream;
/// Determine if the raw_ostream provided is connected to a terminal. If so,
/// generate a warning message to errs() advising against display of bitcode
/// and return true. Otherwise just return false.
/// Check for output written to a console
bool CheckBitcodeOutputToConsole(
- raw_ostream &stream_to_check, ///< The stream to be checked
- bool print_warning = true ///< Control whether warnings are printed
+ raw_ostream &stream_to_check ///< The stream to be checked
);
-} // End llvm namespace
+} // namespace llvm
#endif
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index e004550059d41..c069f5d22ba83 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -127,6 +127,12 @@ HANDLE_TARGET_OPCODE(PATCHPOINT)
/// additionally expand this pseudo after register allocation.
HANDLE_TARGET_OPCODE(LOAD_STACK_GUARD)
+/// These are used to support call sites that must have the stack adjusted
+/// before the call (e.g. to initialize an argument passed by value).
+/// See llvm.call.preallocated.{setup,arg} in the LangRef for more details.
+HANDLE_TARGET_OPCODE(PREALLOCATED_SETUP)
+HANDLE_TARGET_OPCODE(PREALLOCATED_ARG)
+
/// Call instruction with associated vm state for deoptimization and list
/// of live pointers for relocation by the garbage collector. It is
/// intended to support garbage collection with fully precise relocating
@@ -279,6 +285,9 @@ HANDLE_TARGET_OPCODE(G_INTTOPTR)
/// COPY is the relevant instruction.
HANDLE_TARGET_OPCODE(G_BITCAST)
+/// Generic freeze.
+HANDLE_TARGET_OPCODE(G_FREEZE)
+
/// INTRINSIC trunc intrinsic.
HANDLE_TARGET_OPCODE(G_INTRINSIC_TRUNC)
@@ -385,6 +394,12 @@ HANDLE_TARGET_OPCODE(G_LSHR)
// Generic arithmetic right-shift
HANDLE_TARGET_OPCODE(G_ASHR)
+// Generic funnel left shift
+HANDLE_TARGET_OPCODE(G_FSHL)
+
+// Generic funnel right shift
+HANDLE_TARGET_OPCODE(G_FSHR)
+
/// Generic integer-base comparison, also applicable to vectors of integers.
HANDLE_TARGET_OPCODE(G_ICMP)
@@ -442,6 +457,18 @@ HANDLE_TARGET_OPCODE(G_UMULH)
// the high half of the result.
HANDLE_TARGET_OPCODE(G_SMULH)
+/// Generic saturating unsigned addition.
+HANDLE_TARGET_OPCODE(G_UADDSAT)
+
+/// Generic saturating signed addition.
+HANDLE_TARGET_OPCODE(G_SADDSAT)
+
+/// Generic saturating unsigned subtraction.
+HANDLE_TARGET_OPCODE(G_USUBSAT)
+
+/// Generic saturating signed subtraction.
+HANDLE_TARGET_OPCODE(G_SSUBSAT)
+
/// Generic FP addition.
HANDLE_TARGET_OPCODE(G_FADD)
@@ -529,9 +556,8 @@ HANDLE_TARGET_OPCODE(G_FMAXIMUM)
/// Generic pointer offset
HANDLE_TARGET_OPCODE(G_PTR_ADD)
-/// Clear the specified number of low bits in a pointer. This rounds the value
-/// *down* to the given alignment.
-HANDLE_TARGET_OPCODE(G_PTR_MASK)
+/// Clear the specified bits in a pointer.
+HANDLE_TARGET_OPCODE(G_PTRMASK)
/// Generic signed integer minimum.
HANDLE_TARGET_OPCODE(G_SMIN)
@@ -614,6 +640,15 @@ HANDLE_TARGET_OPCODE(G_JUMP_TABLE)
/// Generic dynamic stack allocation.
HANDLE_TARGET_OPCODE(G_DYN_STACKALLOC)
+/// Strict floating point instructions.
+HANDLE_TARGET_OPCODE(G_STRICT_FADD)
+HANDLE_TARGET_OPCODE(G_STRICT_FSUB)
+HANDLE_TARGET_OPCODE(G_STRICT_FMUL)
+HANDLE_TARGET_OPCODE(G_STRICT_FDIV)
+HANDLE_TARGET_OPCODE(G_STRICT_FREM)
+HANDLE_TARGET_OPCODE(G_STRICT_FMA)
+HANDLE_TARGET_OPCODE(G_STRICT_FSQRT)
+
/// read_register intrinsic
HANDLE_TARGET_OPCODE(G_READ_REGISTER)
diff --git a/llvm/include/llvm/Support/TargetParser.h b/llvm/include/llvm/Support/TargetParser.h
index a7e1a752d0810..a0bd88c153b6e 100644
--- a/llvm/include/llvm/Support/TargetParser.h
+++ b/llvm/include/llvm/Support/TargetParser.h
@@ -25,55 +25,12 @@ namespace llvm {
class StringRef;
// Target specific information in their own namespaces.
-// (ARM/AArch64 are declared in ARM/AArch64TargetParser.h)
+// (ARM/AArch64/X86 are declared in ARM/AArch64/X86TargetParser.h)
// These should be generated from TableGen because the information is already
// there, and there is where new information about targets will be added.
// FIXME: To TableGen this we need to make some table generated files available
// even if the back-end is not compiled with LLVM, plus we need to create a new
// back-end to TableGen to create these clean tables.
-namespace X86 {
-
-// This should be kept in sync with libcc/compiler-rt as its included by clang
-// as a proxy for what's in libgcc/compiler-rt.
-enum ProcessorVendors : unsigned {
- VENDOR_DUMMY,
-#define X86_VENDOR(ENUM, STRING) \
- ENUM,
-#include "llvm/Support/X86TargetParser.def"
- VENDOR_OTHER
-};
-
-// This should be kept in sync with libcc/compiler-rt as its included by clang
-// as a proxy for what's in libgcc/compiler-rt.
-enum ProcessorTypes : unsigned {
- CPU_TYPE_DUMMY,
-#define X86_CPU_TYPE(ARCHNAME, ENUM) \
- ENUM,
-#include "llvm/Support/X86TargetParser.def"
- CPU_TYPE_MAX
-};
-
-// This should be kept in sync with libcc/compiler-rt as its included by clang
-// as a proxy for what's in libgcc/compiler-rt.
-enum ProcessorSubtypes : unsigned {
- CPU_SUBTYPE_DUMMY,
-#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \
- ENUM,
-#include "llvm/Support/X86TargetParser.def"
- CPU_SUBTYPE_MAX
-};
-
-// This should be kept in sync with libcc/compiler-rt as it should be used
-// by clang as a proxy for what's in libgcc/compiler-rt.
-enum ProcessorFeatures {
-#define X86_FEATURE(VAL, ENUM) \
- ENUM = VAL,
-#include "llvm/Support/X86TargetParser.def"
-
-};
-
-} // namespace X86
-
namespace AMDGPU {
/// GPU kinds supported by the AMDGPU target.
@@ -127,9 +84,10 @@ enum GPUKind : uint32_t {
GK_GFX1010 = 71,
GK_GFX1011 = 72,
GK_GFX1012 = 73,
+ GK_GFX1030 = 75,
GK_AMDGCN_FIRST = GK_GFX600,
- GK_AMDGCN_LAST = GK_GFX1012,
+ GK_AMDGCN_LAST = GK_GFX1030,
};
/// Instruction set architecture version.
@@ -151,7 +109,10 @@ enum ArchFeatureKind : uint32_t {
// Common features.
FEATURE_FAST_FMA_F32 = 1 << 4,
- FEATURE_FAST_DENORMAL_F32 = 1 << 5
+ FEATURE_FAST_DENORMAL_F32 = 1 << 5,
+
+ // Wavefront 32 is available.
+ FEATURE_WAVE32 = 1 << 6
};
StringRef getArchNameAMDGCN(GPUKind AK);
diff --git a/llvm/include/llvm/Support/TaskQueue.h b/llvm/include/llvm/Support/TaskQueue.h
index df2ffdee2cc24..4ceb056391af0 100644
--- a/llvm/include/llvm/Support/TaskQueue.h
+++ b/llvm/include/llvm/Support/TaskQueue.h
@@ -38,7 +38,7 @@ class TaskQueue {
// type-specialized domain (before type erasure) and then erase this into a
// std::function.
template <typename Callable> struct Task {
- using ResultTy = typename std::result_of<Callable()>::type;
+ using ResultTy = std::result_of_t<Callable()>;
explicit Task(Callable C, TaskQueue &Parent)
: C(std::move(C)), P(std::make_shared<std::promise<ResultTy>>()),
Parent(&Parent) {}
@@ -78,13 +78,13 @@ public:
/// used to wait for the task (and all previous tasks that have not yet
/// completed) to finish.
template <typename Callable>
- std::future<typename std::result_of<Callable()>::type> async(Callable &&C) {
+ std::future<std::result_of_t<Callable()>> async(Callable &&C) {
#if !LLVM_ENABLE_THREADS
static_assert(false,
"TaskQueue requires building with LLVM_ENABLE_THREADS!");
#endif
Task<Callable> T{std::move(C), *this};
- using ResultTy = typename std::result_of<Callable()>::type;
+ using ResultTy = std::result_of_t<Callable()>;
std::future<ResultTy> F = T.P->get_future();
{
std::lock_guard<std::mutex> Lock(QueueLock);
diff --git a/llvm/include/llvm/Support/ThreadPool.h b/llvm/include/llvm/Support/ThreadPool.h
index 4bcbaa3142fd4..528fb32525eb2 100644
--- a/llvm/include/llvm/Support/ThreadPool.h
+++ b/llvm/include/llvm/Support/ThreadPool.h
@@ -14,6 +14,7 @@
#define LLVM_SUPPORT_THREAD_POOL_H
#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Threading.h"
#include "llvm/Support/thread.h"
#include <future>
@@ -38,12 +39,11 @@ public:
using TaskTy = std::function<void()>;
using PackagedTaskTy = std::packaged_task<void()>;
- /// Construct a pool with the number of threads found by
- /// hardware_concurrency().
- ThreadPool();
-
- /// Construct a pool of \p ThreadCount threads
- ThreadPool(unsigned ThreadCount);
+ /// Construct a pool using the hardware strategy \p S for mapping hardware
+ /// execution resources (threads, cores, CPUs)
+ /// Defaults to using the maximum execution resources in the system, but
+ /// accounting for the affinity mask.
+ ThreadPool(ThreadPoolStrategy S = hardware_concurrency());
/// Blocking destructor: the pool will wait for all the threads to complete.
~ThreadPool();
@@ -68,7 +68,11 @@ public:
/// It is an error to try to add new tasks while blocking on this call.
void wait();
+ unsigned getThreadCount() const { return ThreadCount; }
+
private:
+ bool workCompletedUnlocked() { return !ActiveThreads && Tasks.empty(); }
+
/// Asynchronous submission of a task to the pool. The returned future can be
/// used to wait for the task to finish and is *non-blocking* on destruction.
std::shared_future<void> asyncImpl(TaskTy F);
@@ -83,17 +87,18 @@ private:
std::mutex QueueLock;
std::condition_variable QueueCondition;
- /// Locking and signaling for job completion
- std::mutex CompletionLock;
+ /// Signaling for job completion
std::condition_variable CompletionCondition;
/// Keep track of the number of thread actually busy
- std::atomic<unsigned> ActiveThreads;
+ unsigned ActiveThreads = 0;
#if LLVM_ENABLE_THREADS // avoids warning for unused variable
/// Signal for the destruction of the pool, asking thread to exit.
- bool EnableFlag;
+ bool EnableFlag = true;
#endif
+
+ unsigned ThreadCount;
};
}
diff --git a/llvm/include/llvm/Support/Threading.h b/llvm/include/llvm/Support/Threading.h
index bacab8fa23b6d..13000575f270e 100644
--- a/llvm/include/llvm/Support/Threading.h
+++ b/llvm/include/llvm/Support/Threading.h
@@ -14,6 +14,7 @@
#ifndef LLVM_SUPPORT_THREADING_H
#define LLVM_SUPPORT_THREADING_H
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
@@ -143,20 +144,81 @@ void llvm_execute_on_thread_async(
#endif
}
- /// Get the amount of currency to use for tasks requiring significant
- /// memory or other resources. Currently based on physical cores, if
- /// available for the host system, otherwise falls back to
- /// thread::hardware_concurrency().
- /// Returns 1 when LLVM is configured with LLVM_ENABLE_THREADS=OFF
- unsigned heavyweight_hardware_concurrency();
-
- /// Get the number of threads that the current program can execute
- /// concurrently. On some systems std::thread::hardware_concurrency() returns
- /// the total number of cores, without taking affinity into consideration.
- /// Returns 1 when LLVM is configured with LLVM_ENABLE_THREADS=OFF.
- /// Fallback to std::thread::hardware_concurrency() if sched_getaffinity is
- /// not available.
- unsigned hardware_concurrency();
+ /// This tells how a thread pool will be used
+ class ThreadPoolStrategy {
+ public:
+ // The default value (0) means all available threads should be used,
+ // taking the affinity mask into account. If set, this value only represents
+ // a suggested high bound, the runtime might choose a lower value (not
+ // higher).
+ unsigned ThreadsRequested = 0;
+
+ // If SMT is active, use hyper threads. If false, there will be only one
+ // std::thread per core.
+ bool UseHyperThreads = true;
+
+ // If set, will constrain 'ThreadsRequested' to the number of hardware
+ // threads, or hardware cores.
+ bool Limit = false;
+
+ /// Retrieves the max available threads for the current strategy. This
+ /// accounts for affinity masks and takes advantage of all CPU sockets.
+ unsigned compute_thread_count() const;
+
+ /// Assign the current thread to an ideal hardware CPU or NUMA node. In a
+ /// multi-socket system, this ensures threads are assigned to all CPU
+ /// sockets. \p ThreadPoolNum represents a number bounded by [0,
+ /// compute_thread_count()).
+ void apply_thread_strategy(unsigned ThreadPoolNum) const;
+
+ /// Finds the CPU socket where a thread should go. Returns 'None' if the
+ /// thread shall remain on the actual CPU socket.
+ Optional<unsigned> compute_cpu_socket(unsigned ThreadPoolNum) const;
+ };
+
+ /// Build a strategy from a number of threads as a string provided in \p Num.
+ /// When Num is above the max number of threads specified by the \p Default
+ /// strategy, we attempt to equally allocate the threads on all CPU sockets.
+ /// "0" or an empty string will return the \p Default strategy.
+ /// "all" for using all hardware threads.
+ Optional<ThreadPoolStrategy>
+ get_threadpool_strategy(StringRef Num, ThreadPoolStrategy Default = {});
+
+ /// Returns a thread strategy for tasks requiring significant memory or other
+ /// resources. To be used for workloads where hardware_concurrency() proves to
+ /// be less efficient. Avoid this strategy if doing lots of I/O. Currently
+ /// based on physical cores, if available for the host system, otherwise falls
+ /// back to hardware_concurrency(). Returns 1 when LLVM is configured with
+ /// LLVM_ENABLE_THREADS = OFF.
+ inline ThreadPoolStrategy
+ heavyweight_hardware_concurrency(unsigned ThreadCount = 0) {
+ ThreadPoolStrategy S;
+ S.UseHyperThreads = false;
+ S.ThreadsRequested = ThreadCount;
+ return S;
+ }
+
+ /// Like heavyweight_hardware_concurrency() above, but builds a strategy
+ /// based on the rules described for get_threadpool_strategy().
+ /// If \p Num is invalid, returns a default strategy where one thread per
+ /// hardware core is used.
+ inline ThreadPoolStrategy heavyweight_hardware_concurrency(StringRef Num) {
+ Optional<ThreadPoolStrategy> S =
+ get_threadpool_strategy(Num, heavyweight_hardware_concurrency());
+ if (S)
+ return *S;
+ return heavyweight_hardware_concurrency();
+ }
+
+ /// Returns a default thread strategy where all available hardware ressources
+ /// are to be used, except for those initially excluded by an affinity mask.
+ /// This function takes affinity into consideration. Returns 1 when LLVM is
+ /// configured with LLVM_ENABLE_THREADS=OFF.
+ inline ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount = 0) {
+ ThreadPoolStrategy S;
+ S.ThreadsRequested = ThreadCount;
+ return S;
+ }
/// Return the current thread id, as used in various OS system calls.
/// Note that not all platforms guarantee that the value returned will be
@@ -184,6 +246,14 @@ void llvm_execute_on_thread_async(
/// the operation succeeded or failed is returned.
void get_thread_name(SmallVectorImpl<char> &Name);
+ /// Returns a mask that represents on which hardware thread, core, CPU, NUMA
+ /// group, the calling thread can be executed. On Windows, threads cannot
+ /// cross CPU sockets boundaries.
+ llvm::BitVector get_thread_affinity_mask();
+
+ /// Returns how many physical CPUs or NUMA groups the system has.
+ unsigned get_cpus();
+
enum class ThreadPriority {
Background = 0,
Default = 1,
diff --git a/llvm/include/llvm/Support/TimeProfiler.h b/llvm/include/llvm/Support/TimeProfiler.h
index 678f8c1368111..b6f8a647e3ee8 100644
--- a/llvm/include/llvm/Support/TimeProfiler.h
+++ b/llvm/include/llvm/Support/TimeProfiler.h
@@ -9,12 +9,13 @@
#ifndef LLVM_SUPPORT_TIME_PROFILER_H
#define LLVM_SUPPORT_TIME_PROFILER_H
+#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
struct TimeTraceProfiler;
-extern TimeTraceProfiler *TimeTraceProfilerInstance;
+TimeTraceProfiler *getTimeTraceProfilerInstance();
/// Initialize the time trace profiler.
/// This sets up the global \p TimeTraceProfilerInstance
@@ -25,16 +26,27 @@ void timeTraceProfilerInitialize(unsigned TimeTraceGranularity,
/// Cleanup the time trace profiler, if it was initialized.
void timeTraceProfilerCleanup();
+/// Finish a time trace profiler running on a worker thread.
+void timeTraceProfilerFinishThread();
+
/// Is the time trace profiler enabled, i.e. initialized?
inline bool timeTraceProfilerEnabled() {
- return TimeTraceProfilerInstance != nullptr;
+ return getTimeTraceProfilerInstance() != nullptr;
}
-/// Write profiling data to output file.
+/// Write profiling data to output stream.
/// Data produced is JSON, in Chrome "Trace Event" format, see
/// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
void timeTraceProfilerWrite(raw_pwrite_stream &OS);
+/// Write profiling data to a file.
+/// The function will write to \p PreferredFileName if provided, if not
+/// then will write to \p FallbackFileName appending .time-trace.
+/// Returns a StringError indicating a failure if the function is
+/// unable to open the file for writing.
+Error timeTraceProfilerWrite(StringRef PreferredFileName,
+ StringRef FallbackFileName);
+
/// Manually begin a time section, with the given \p Name and \p Detail.
/// Profiler copies the string data, so the pointers can be given into
/// temporaries. Time sections can be hierarchical; every Begin must have a
@@ -59,19 +71,19 @@ struct TimeTraceScope {
TimeTraceScope &operator=(TimeTraceScope &&) = delete;
TimeTraceScope(StringRef Name) {
- if (TimeTraceProfilerInstance != nullptr)
+ if (getTimeTraceProfilerInstance() != nullptr)
timeTraceProfilerBegin(Name, StringRef(""));
}
TimeTraceScope(StringRef Name, StringRef Detail) {
- if (TimeTraceProfilerInstance != nullptr)
+ if (getTimeTraceProfilerInstance() != nullptr)
timeTraceProfilerBegin(Name, Detail);
}
TimeTraceScope(StringRef Name, llvm::function_ref<std::string()> Detail) {
- if (TimeTraceProfilerInstance != nullptr)
+ if (getTimeTraceProfilerInstance() != nullptr)
timeTraceProfilerBegin(Name, Detail);
}
~TimeTraceScope() {
- if (TimeTraceProfilerInstance != nullptr)
+ if (getTimeTraceProfilerInstance() != nullptr)
timeTraceProfilerEnd();
}
};
diff --git a/llvm/include/llvm/Support/Timer.h b/llvm/include/llvm/Support/Timer.h
index a298ecd904046..045ac448bdb42 100644
--- a/llvm/include/llvm/Support/Timer.h
+++ b/llvm/include/llvm/Support/Timer.h
@@ -230,6 +230,11 @@ public:
/// used by the Statistic code to influence the construction and destruction
/// order of the global timer lists.
static void ConstructTimerLists();
+
+ /// This makes the default group unmanaged, and lets the user manage the
+ /// group's lifetime.
+ static std::unique_ptr<TimerGroup> aquireDefaultGroup();
+
private:
friend class Timer;
friend void PrintStatisticsJSON(raw_ostream &OS);
diff --git a/llvm/include/llvm/Support/ToolOutputFile.h b/llvm/include/llvm/Support/ToolOutputFile.h
index a99e327f8db70..cf01b9ecefc50 100644
--- a/llvm/include/llvm/Support/ToolOutputFile.h
+++ b/llvm/include/llvm/Support/ToolOutputFile.h
@@ -13,6 +13,7 @@
#ifndef LLVM_SUPPORT_TOOLOUTPUTFILE_H
#define LLVM_SUPPORT_TOOLOUTPUTFILE_H
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
@@ -38,8 +39,12 @@ class ToolOutputFile {
~CleanupInstaller();
} Installer;
- /// The contained stream. This is intentionally declared after Installer.
- raw_fd_ostream OS;
+ /// Storage for the stream, if we're owning our own stream. This is
+ /// intentionally declared after Installer.
+ Optional<raw_fd_ostream> OSHolder;
+
+ /// The actual stream to use.
+ raw_fd_ostream *OS;
public:
/// This constructor's arguments are passed to raw_fd_ostream's
@@ -50,7 +55,7 @@ public:
ToolOutputFile(StringRef Filename, int FD);
/// Return the contained raw_fd_ostream.
- raw_fd_ostream &os() { return OS; }
+ raw_fd_ostream &os() { return *OS; }
/// Indicate that the tool's job wrt this output file has been successful and
/// the file should not be deleted.
diff --git a/llvm/include/llvm/Support/TrailingObjects.h b/llvm/include/llvm/Support/TrailingObjects.h
index 49be89613c434..0d9c4503aa9be 100644
--- a/llvm/include/llvm/Support/TrailingObjects.h
+++ b/llvm/include/llvm/Support/TrailingObjects.h
@@ -326,8 +326,8 @@ public:
/// used in the class; they are supplied here redundantly only so
/// that it's clear what the counts are counting in callers.
template <typename... Tys>
- static constexpr typename std::enable_if<
- std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t>::type
+ static constexpr std::enable_if_t<
+ std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t>
additionalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType<
TrailingTys, size_t>::type... Counts) {
return ParentType::additionalSizeToAllocImpl(0, Counts...);
@@ -338,8 +338,8 @@ public:
/// additionalSizeToAlloc, except it *does* include the size of the base
/// object.
template <typename... Tys>
- static constexpr typename std::enable_if<
- std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t>::type
+ static constexpr std::enable_if_t<
+ std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t>
totalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType<
TrailingTys, size_t>::type... Counts) {
return sizeof(BaseTy) + ParentType::additionalSizeToAllocImpl(0, Counts...);
diff --git a/llvm/include/llvm/Support/TrigramIndex.h b/llvm/include/llvm/Support/TrigramIndex.h
index 9351c2db169a7..d635694eb5fd3 100644
--- a/llvm/include/llvm/Support/TrigramIndex.h
+++ b/llvm/include/llvm/Support/TrigramIndex.h
@@ -27,7 +27,6 @@
#define LLVM_SUPPORT_TRIGRAMINDEX_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
#include <string>
#include <unordered_map>
diff --git a/llvm/include/llvm/Support/TypeSize.h b/llvm/include/llvm/Support/TypeSize.h
index 7ea651f0f22cf..76564c401e8ed 100644
--- a/llvm/include/llvm/Support/TypeSize.h
+++ b/llvm/include/llvm/Support/TypeSize.h
@@ -15,17 +15,24 @@
#ifndef LLVM_SUPPORT_TYPESIZE_H
#define LLVM_SUPPORT_TYPESIZE_H
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/WithColor.h"
+
+#include <cstdint>
#include <cassert>
-#include <tuple>
namespace llvm {
+template <typename T> struct DenseMapInfo;
+
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() = default;
+
ElementCount(unsigned Min, bool Scalable)
: Min(Min), Scalable(Scalable) {}
@@ -33,6 +40,7 @@ public:
return { Min * RHS, Scalable };
}
ElementCount operator/(unsigned RHS) {
+ assert(Min % RHS == 0 && "Min is not a multiple of RHS.");
return { Min / RHS, Scalable };
}
@@ -42,6 +50,12 @@ public:
bool operator!=(const ElementCount& RHS) const {
return !(*this == RHS);
}
+ bool operator==(unsigned RHS) const { return Min == RHS && !Scalable; }
+ bool operator!=(unsigned RHS) const { return !(*this == RHS); }
+
+ ElementCount NextPowerOf2() const {
+ return ElementCount(llvm::NextPowerOf2(Min), Scalable);
+ }
};
// This class is used to represent the size of types. If the type is of fixed
@@ -68,8 +82,7 @@ public:
// 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);
+ return LHS.MinSize == RHS.MinSize && LHS.IsScalable == RHS.IsScalable;
}
friend bool operator!=(const TypeSize &LHS, const TypeSize &RHS) {
@@ -143,12 +156,40 @@ public:
return (MinSize & 7) == 0;
}
+ // Returns true if the type size is non-zero.
+ bool isNonZero() const { return MinSize != 0; }
+
+ // Returns true if the type size is zero.
+ bool isZero() const { return MinSize == 0; }
+
// 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.
+ // This interface is deprecated and will be removed in a future version
+ // of LLVM in favour of upgrading uses that rely on this implicit conversion
+ // to uint64_t. Calls to functions that return a TypeSize should use the
+ // proper interfaces to TypeSize.
+ // In practice this is mostly calls to MVT/EVT::getSizeInBits().
+ //
+ // To determine how to upgrade the code:
+ //
+ // if (<algorithm works for both scalable and fixed-width vectors>)
+ // use getKnownMinSize()
+ // else if (<algorithm works only for fixed-width vectors>) {
+ // if <algorithm can be adapted for both scalable and fixed-width vectors>
+ // update the algorithm and use getKnownMinSize()
+ // else
+ // bail out early for scalable vectors and use getFixedSize()
+ // }
operator uint64_t() const {
+#ifdef STRICT_FIXED_SIZE_VECTORS
return getFixedSize();
+#else
+ if (isScalable())
+ WithColor::warning() << "Compiler has made implicit assumption that "
+ "TypeSize is not scalable. This may or may not "
+ "lead to broken code.\n";
+ return getKnownMinSize();
+#endif
}
// Additional convenience operators needed to avoid ambiguous parses.
@@ -188,6 +229,10 @@ public:
TypeSize operator/(int64_t RHS) const {
return { MinSize / RHS, IsScalable };
}
+
+ TypeSize NextPowerOf2() const {
+ return TypeSize(llvm::NextPowerOf2(MinSize), IsScalable);
+ }
};
/// Returns a TypeSize with a known minimum size that is the next integer
@@ -201,6 +246,21 @@ inline TypeSize alignTo(TypeSize Size, uint64_t Align) {
Size.isScalable()};
}
+template <> struct DenseMapInfo<ElementCount> {
+ static inline ElementCount getEmptyKey() { return {~0U, true}; }
+ static inline ElementCount getTombstoneKey() { return {~0U - 1, false}; }
+ static unsigned getHashValue(const ElementCount& EltCnt) {
+ if (EltCnt.Scalable)
+ return (EltCnt.Min * 37U) - 1U;
+
+ return EltCnt.Min * 37U;
+ }
+
+ static bool isEqual(const ElementCount& LHS, const ElementCount& RHS) {
+ return LHS == RHS;
+ }
+};
+
} // end namespace llvm
#endif // LLVM_SUPPORT_TypeSize_H
diff --git a/llvm/include/llvm/Support/VersionTuple.h b/llvm/include/llvm/Support/VersionTuple.h
index f3eeea2f7b446..6f3711f06f1a0 100644
--- a/llvm/include/llvm/Support/VersionTuple.h
+++ b/llvm/include/llvm/Support/VersionTuple.h
@@ -14,13 +14,14 @@
#ifndef LLVM_SUPPORT_VERSIONTUPLE_H
#define LLVM_SUPPORT_VERSIONTUPLE_H
+#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
#include <string>
#include <tuple>
namespace llvm {
+class raw_ostream;
+class StringRef;
/// Represents a version number in the form major[.minor[.subminor[.build]]].
class VersionTuple {
@@ -144,6 +145,10 @@ public:
return !(X < Y);
}
+ friend llvm::hash_code hash_value(const VersionTuple &VT) {
+ return llvm::hash_combine(VT.Major, VT.Minor, VT.Subminor, VT.Build);
+ }
+
/// Retrieve a string representation of the version number.
std::string getAsString() const;
diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h
index e45e6e7567863..af09c21085c5e 100644
--- a/llvm/include/llvm/Support/VirtualFileSystem.h
+++ b/llvm/include/llvm/Support/VirtualFileSystem.h
@@ -19,7 +19,6 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
@@ -38,6 +37,7 @@
namespace llvm {
class MemoryBuffer;
+class Twine;
namespace vfs {
@@ -506,10 +506,12 @@ getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
struct YAMLVFSEntry {
template <typename T1, typename T2>
- YAMLVFSEntry(T1 &&VPath, T2 &&RPath)
- : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)) {}
+ YAMLVFSEntry(T1 &&VPath, T2 &&RPath, bool IsDirectory = false)
+ : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)),
+ IsDirectory(IsDirectory) {}
std::string VPath;
std::string RPath;
+ bool IsDirectory = false;
};
class VFSFromYamlDirIterImpl;
@@ -654,7 +656,7 @@ private:
// In a RedirectingFileSystem, keys can be specified in Posix or Windows
// style (or even a mixture of both), so this comparison helper allows
// slashes (representing a root) to match backslashes (and vice versa). Note
- // that, other than the root, patch components should not contain slashes or
+ // that, other than the root, path components should not contain slashes or
// backslashes.
bool pathComponentMatches(llvm::StringRef lhs, llvm::StringRef rhs) const {
if ((CaseSensitive ? lhs.equals(rhs) : lhs.equals_lower(rhs)))
@@ -705,16 +707,6 @@ private:
bool IsFallthrough = true;
/// @}
- /// Virtual file paths and external files could be canonicalized without "..",
- /// "." and "./" in their paths. FIXME: some unittests currently fail on
- /// win32 when using remove_dots and remove_leading_dotslash on paths.
- bool UseCanonicalizedPaths =
-#ifdef _WIN32
- false;
-#else
- true;
-#endif
-
RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS);
/// Looks up the path <tt>[Start, End)</tt> in \p From, possibly
@@ -781,10 +773,13 @@ class YAMLVFSWriter {
Optional<bool> UseExternalNames;
std::string OverlayDir;
+ void addEntry(StringRef VirtualPath, StringRef RealPath, bool IsDirectory);
+
public:
YAMLVFSWriter() = default;
void addFileMapping(StringRef VirtualPath, StringRef RealPath);
+ void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath);
void setCaseSensitivity(bool CaseSensitive) {
IsCaseSensitive = CaseSensitive;
diff --git a/llvm/include/llvm/Support/Windows/WindowsSupport.h b/llvm/include/llvm/Support/Windows/WindowsSupport.h
new file mode 100644
index 0000000000000..bd5a90c2c3f00
--- /dev/null
+++ b/llvm/include/llvm/Support/Windows/WindowsSupport.h
@@ -0,0 +1,249 @@
+//===- WindowsSupport.h - Common Windows Include File -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines things specific to Windows implementations. In addition to
+// providing some helpers for working with win32 APIs, this header wraps
+// <windows.h> with some portability macros. Always include WindowsSupport.h
+// instead of including <windows.h> directly.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Win32 code that
+//=== is guaranteed to work on *all* Win32 variants.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_WINDOWSSUPPORT_H
+#define LLVM_SUPPORT_WINDOWSSUPPORT_H
+
+// mingw-w64 tends to define it as 0x0502 in its headers.
+#undef _WIN32_WINNT
+#undef _WIN32_IE
+
+// Require at least Windows 7 API.
+#define _WIN32_WINNT 0x0601
+#define _WIN32_IE 0x0800 // MinGW at it again. FIXME: verify if still needed.
+#define WIN32_LEAN_AND_MEAN
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Config/config.h" // Get build system configuration settings
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/VersionTuple.h"
+#include <cassert>
+#include <string>
+#include <system_error>
+#include <windows.h>
+
+// Must be included after windows.h
+#include <wincrypt.h>
+
+namespace llvm {
+
+/// Determines if the program is running on Windows 8 or newer. This
+/// reimplements one of the helpers in the Windows 8.1 SDK, which are intended
+/// to supercede raw calls to GetVersionEx. Old SDKs, Cygwin, and MinGW don't
+/// yet have VersionHelpers.h, so we have our own helper.
+bool RunningWindows8OrGreater();
+
+/// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
+/// RtlGetVersion or GetVersionEx under the hood depending on what is available.
+/// GetVersionEx is deprecated, but this API exposes the build number which can
+/// be useful for working around certain kernel bugs.
+llvm::VersionTuple GetWindowsOSVersion();
+
+bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix);
+
+// Include GetLastError() in a fatal error message.
+LLVM_ATTRIBUTE_NORETURN inline void ReportLastErrorFatal(const char *Msg) {
+ std::string ErrMsg;
+ MakeErrMsg(&ErrMsg, Msg);
+ llvm::report_fatal_error(ErrMsg);
+}
+
+template <typename HandleTraits>
+class ScopedHandle {
+ typedef typename HandleTraits::handle_type handle_type;
+ handle_type Handle;
+
+ ScopedHandle(const ScopedHandle &other) = delete;
+ void operator=(const ScopedHandle &other) = delete;
+public:
+ ScopedHandle()
+ : Handle(HandleTraits::GetInvalid()) {}
+
+ explicit ScopedHandle(handle_type h)
+ : Handle(h) {}
+
+ ~ScopedHandle() {
+ if (HandleTraits::IsValid(Handle))
+ HandleTraits::Close(Handle);
+ }
+
+ handle_type take() {
+ handle_type t = Handle;
+ Handle = HandleTraits::GetInvalid();
+ return t;
+ }
+
+ ScopedHandle &operator=(handle_type h) {
+ if (HandleTraits::IsValid(Handle))
+ HandleTraits::Close(Handle);
+ Handle = h;
+ return *this;
+ }
+
+ // True if Handle is valid.
+ explicit operator bool() const {
+ return HandleTraits::IsValid(Handle) ? true : false;
+ }
+
+ operator handle_type() const {
+ return Handle;
+ }
+};
+
+struct CommonHandleTraits {
+ typedef HANDLE handle_type;
+
+ static handle_type GetInvalid() {
+ return INVALID_HANDLE_VALUE;
+ }
+
+ static void Close(handle_type h) {
+ ::CloseHandle(h);
+ }
+
+ static bool IsValid(handle_type h) {
+ return h != GetInvalid();
+ }
+};
+
+struct JobHandleTraits : CommonHandleTraits {
+ static handle_type GetInvalid() {
+ return NULL;
+ }
+};
+
+struct CryptContextTraits : CommonHandleTraits {
+ typedef HCRYPTPROV handle_type;
+
+ static handle_type GetInvalid() {
+ return 0;
+ }
+
+ static void Close(handle_type h) {
+ ::CryptReleaseContext(h, 0);
+ }
+
+ static bool IsValid(handle_type h) {
+ return h != GetInvalid();
+ }
+};
+
+struct RegTraits : CommonHandleTraits {
+ typedef HKEY handle_type;
+
+ static handle_type GetInvalid() {
+ return NULL;
+ }
+
+ static void Close(handle_type h) {
+ ::RegCloseKey(h);
+ }
+
+ static bool IsValid(handle_type h) {
+ return h != GetInvalid();
+ }
+};
+
+struct FindHandleTraits : CommonHandleTraits {
+ static void Close(handle_type h) {
+ ::FindClose(h);
+ }
+};
+
+struct FileHandleTraits : CommonHandleTraits {};
+
+typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle;
+typedef ScopedHandle<FileHandleTraits> ScopedFileHandle;
+typedef ScopedHandle<CryptContextTraits> ScopedCryptContext;
+typedef ScopedHandle<RegTraits> ScopedRegHandle;
+typedef ScopedHandle<FindHandleTraits> ScopedFindHandle;
+typedef ScopedHandle<JobHandleTraits> ScopedJobHandle;
+
+template <class T>
+class SmallVectorImpl;
+
+template <class T>
+typename SmallVectorImpl<T>::const_pointer
+c_str(SmallVectorImpl<T> &str) {
+ str.push_back(0);
+ str.pop_back();
+ return str.data();
+}
+
+namespace sys {
+
+inline std::chrono::nanoseconds toDuration(FILETIME Time) {
+ ULARGE_INTEGER TimeInteger;
+ TimeInteger.LowPart = Time.dwLowDateTime;
+ TimeInteger.HighPart = Time.dwHighDateTime;
+
+ // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
+ return std::chrono::nanoseconds(100 * TimeInteger.QuadPart);
+}
+
+inline TimePoint<> toTimePoint(FILETIME Time) {
+ ULARGE_INTEGER TimeInteger;
+ TimeInteger.LowPart = Time.dwLowDateTime;
+ TimeInteger.HighPart = Time.dwHighDateTime;
+
+ // Adjust for different epoch
+ TimeInteger.QuadPart -= 11644473600ll * 10000000;
+
+ // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
+ return TimePoint<>(std::chrono::nanoseconds(100 * TimeInteger.QuadPart));
+}
+
+inline FILETIME toFILETIME(TimePoint<> TP) {
+ ULARGE_INTEGER TimeInteger;
+ TimeInteger.QuadPart = TP.time_since_epoch().count() / 100;
+ TimeInteger.QuadPart += 11644473600ll * 10000000;
+
+ FILETIME Time;
+ Time.dwLowDateTime = TimeInteger.LowPart;
+ Time.dwHighDateTime = TimeInteger.HighPart;
+ return Time;
+}
+
+namespace windows {
+// Returns command line arguments. Unlike arguments given to main(),
+// this function guarantees that the returned arguments are encoded in
+// UTF-8 regardless of the current code page setting.
+std::error_code GetCommandLineArguments(SmallVectorImpl<const char *> &Args,
+ BumpPtrAllocator &Alloc);
+
+/// Convert UTF-8 path to a suitable UTF-16 path for use with the Win32 Unicode
+/// File API.
+std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16,
+ size_t MaxPathLen = MAX_PATH);
+
+} // end namespace windows
+} // end namespace sys
+} // end namespace llvm.
+
+#endif
diff --git a/llvm/include/llvm/Support/WithColor.h b/llvm/include/llvm/Support/WithColor.h
index f4e1075811794..eea4a72293392 100644
--- a/llvm/include/llvm/Support/WithColor.h
+++ b/llvm/include/llvm/Support/WithColor.h
@@ -9,14 +9,18 @@
#ifndef LLVM_SUPPORT_WITHCOLOR_H
#define LLVM_SUPPORT_WITHCOLOR_H
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
namespace llvm {
-extern cl::OptionCategory ColorCategory;
+class Error;
+class StringRef;
+
+namespace cl {
+class OptionCategory;
+}
-class raw_ostream;
+extern cl::OptionCategory ColorCategory;
// Symbolic names for various syntax elements.
enum class HighlightColor {
@@ -32,31 +36,43 @@ enum class HighlightColor {
Remark
};
+enum class ColorMode {
+ /// Determine whether to use color based on the command line argument and the
+ /// raw_ostream.
+ Auto,
+ /// Enable colors. Because raw_ostream is the one implementing colors, this
+ /// has no effect if the stream does not support colors or has colors
+ /// disabled.
+ Enable,
+ /// Disable colors.
+ Disable,
+};
+
/// An RAII object that temporarily switches an output stream to a specific
/// color.
class WithColor {
raw_ostream &OS;
- bool DisableColors;
+ ColorMode Mode;
public:
/// To be used like this: WithColor(OS, HighlightColor::String) << "text";
/// @param OS The output stream
/// @param S Symbolic name for syntax element to color
- /// @param DisableColors Whether to ignore color changes regardless of -color
- /// and support in OS
- WithColor(raw_ostream &OS, HighlightColor S, bool DisableColors = false);
+ /// @param Mode Enable, disable or compute whether to use colors.
+ WithColor(raw_ostream &OS, HighlightColor S,
+ ColorMode Mode = ColorMode::Auto);
/// To be used like this: WithColor(OS, raw_ostream::Black) << "text";
/// @param OS The output stream
/// @param Color ANSI color to use, the special SAVEDCOLOR can be used to
/// change only the bold attribute, and keep colors untouched
/// @param Bold Bold/brighter text, default false
/// @param BG If true, change the background, default: change foreground
- /// @param DisableColors Whether to ignore color changes regardless of -color
- /// and support in OS
+ /// @param Mode Enable, disable or compute whether to use colors.
WithColor(raw_ostream &OS,
raw_ostream::Colors Color = raw_ostream::SAVEDCOLOR,
- bool Bold = false, bool BG = false, bool DisableColors = false)
- : OS(OS), DisableColors(DisableColors) {
+ bool Bold = false, bool BG = false,
+ ColorMode Mode = ColorMode::Auto)
+ : OS(OS), Mode(Mode) {
changeColor(Color, Bold, BG);
}
~WithColor();
@@ -108,6 +124,14 @@ public:
/// Reset the colors to terminal defaults. Call this when you are done
/// outputting colored text, or before program exit.
WithColor &resetColor();
+
+ /// Implement default handling for Error.
+ /// Print "error: " to stderr.
+ static void defaultErrorHandler(Error Err);
+
+ /// Implement default handling for Warning.
+ /// Print "warning: " to stderr.
+ static void defaultWarningHandler(Error Warning);
};
} // end namespace llvm
diff --git a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
index baf842b12a27b..5697ff9a01dc1 100644
--- a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
+++ b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
@@ -361,6 +361,7 @@ enum ModRMDecisionType {
ENUM_ENTRY(ENCODING_RM_CD16,"R/M operand with CDisp scaling of 16") \
ENUM_ENTRY(ENCODING_RM_CD32,"R/M operand with CDisp scaling of 32") \
ENUM_ENTRY(ENCODING_RM_CD64,"R/M operand with CDisp scaling of 64") \
+ ENUM_ENTRY(ENCODING_SIB, "Force SIB operand in ModR/M byte.") \
ENUM_ENTRY(ENCODING_VSIB, "VSIB operand in ModR/M byte.") \
ENUM_ENTRY(ENCODING_VSIB_CD2, "VSIB operand with CDisp scaling of 2") \
ENUM_ENTRY(ENCODING_VSIB_CD4, "VSIB operand with CDisp scaling of 4") \
@@ -374,7 +375,7 @@ enum ModRMDecisionType {
ENUM_ENTRY(ENCODING_IW, "2-byte") \
ENUM_ENTRY(ENCODING_ID, "4-byte") \
ENUM_ENTRY(ENCODING_IO, "8-byte") \
- ENUM_ENTRY(ENCODING_RB, "(AL..DIL, R8L..R15L) Register code added to " \
+ ENUM_ENTRY(ENCODING_RB, "(AL..DIL, R8B..R15B) Register code added to " \
"the opcode byte") \
ENUM_ENTRY(ENCODING_RW, "(AX..DI, R8W..R15W)") \
ENUM_ENTRY(ENCODING_RD, "(EAX..EDI, R8D..R15D)") \
@@ -411,6 +412,7 @@ enum OperandEncoding {
ENUM_ENTRY(TYPE_IMM, "immediate operand") \
ENUM_ENTRY(TYPE_UIMM8, "1-byte unsigned immediate operand") \
ENUM_ENTRY(TYPE_M, "Memory operand") \
+ ENUM_ENTRY(TYPE_MSIB, "Memory operand force sib encoding") \
ENUM_ENTRY(TYPE_MVSIBX, "Memory operand using XMM index") \
ENUM_ENTRY(TYPE_MVSIBY, "Memory operand using YMM index") \
ENUM_ENTRY(TYPE_MVSIBZ, "Memory operand using ZMM index") \
@@ -424,6 +426,7 @@ enum OperandEncoding {
ENUM_ENTRY(TYPE_ZMM, "64-byte") \
ENUM_ENTRY(TYPE_VK, "mask register") \
ENUM_ENTRY(TYPE_VK_PAIR, "mask register pair") \
+ ENUM_ENTRY(TYPE_TMM, "tile") \
ENUM_ENTRY(TYPE_SEGMENTREG, "Segment register operand") \
ENUM_ENTRY(TYPE_DEBUGREG, "Debug register operand") \
ENUM_ENTRY(TYPE_CONTROLREG, "Control register operand") \
diff --git a/llvm/include/llvm/Support/X86TargetParser.def b/llvm/include/llvm/Support/X86TargetParser.def
index 4ebf2d79cb8d6..697f8c70f962d 100644
--- a/llvm/include/llvm/Support/X86TargetParser.def
+++ b/llvm/include/llvm/Support/X86TargetParser.def
@@ -19,155 +19,176 @@ 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)
+#ifndef X86_CPU_TYPE
+#define X86_CPU_TYPE(ENUM, STR)
#endif
-#ifndef X86_CPU_TYPE
-#define X86_CPU_TYPE(ARCHNAME, ENUM)
+#ifndef X86_CPU_TYPE_ALIAS
+#define X86_CPU_TYPE_ALIAS(ENUM, STR)
#endif
-// The first part of this list must match what is implemented in libgcc and
-// compilert-rt. Clang uses this to know how to implement __builtin_cpu_is.
-X86_CPU_TYPE_COMPAT_WITH_ALIAS("bonnell", INTEL_BONNELL, "bonnell", "atom")
-X86_CPU_TYPE_COMPAT ("core2", INTEL_CORE2, "core2")
-X86_CPU_TYPE_COMPAT ("nehalem", INTEL_COREI7, "corei7")
-X86_CPU_TYPE_COMPAT_WITH_ALIAS("amdfam10", AMDFAM10H, "amdfam10h", "amdfam10")
-X86_CPU_TYPE_COMPAT_WITH_ALIAS("bdver1", AMDFAM15H, "amdfam15h", "amdfam15")
-X86_CPU_TYPE_COMPAT_WITH_ALIAS("silvermont", INTEL_SILVERMONT, "silvermont", "slm")
-X86_CPU_TYPE_COMPAT ("knl", INTEL_KNL, "knl")
-X86_CPU_TYPE_COMPAT ("btver1", AMD_BTVER1, "btver1")
-X86_CPU_TYPE_COMPAT ("btver2", AMD_BTVER2, "btver2")
-X86_CPU_TYPE_COMPAT ("znver1", AMDFAM17H, "amdfam17h")
-X86_CPU_TYPE_COMPAT ("knm", INTEL_KNM, "knm")
-X86_CPU_TYPE_COMPAT ("goldmont", INTEL_GOLDMONT, "goldmont")
-X86_CPU_TYPE_COMPAT ("goldmont-plus", INTEL_GOLDMONT_PLUS, "goldmont-plus")
-X86_CPU_TYPE_COMPAT ("tremont", INTEL_TREMONT, "tremont")
-// Entries below this are not in libgcc/compiler-rt.
-X86_CPU_TYPE ("i386", INTEL_i386)
-X86_CPU_TYPE ("i486", INTEL_i486)
-X86_CPU_TYPE ("pentium", INTEL_PENTIUM)
-X86_CPU_TYPE ("pentium-mmx", INTEL_PENTIUM_MMX)
-X86_CPU_TYPE ("pentiumpro", INTEL_PENTIUM_PRO)
-X86_CPU_TYPE ("pentium2", INTEL_PENTIUM_II)
-X86_CPU_TYPE ("pentium3", INTEL_PENTIUM_III)
-X86_CPU_TYPE ("pentium4", INTEL_PENTIUM_IV)
-X86_CPU_TYPE ("pentium-m", INTEL_PENTIUM_M)
-X86_CPU_TYPE ("yonah", INTEL_CORE_DUO)
-X86_CPU_TYPE ("nocona", INTEL_NOCONA)
-X86_CPU_TYPE ("prescott", INTEL_PRESCOTT)
-X86_CPU_TYPE ("i486", AMD_i486)
-X86_CPU_TYPE ("pentium", AMDPENTIUM)
-X86_CPU_TYPE ("athlon", AMD_ATHLON)
-X86_CPU_TYPE ("athlon-xp", AMD_ATHLON_XP)
-X86_CPU_TYPE ("k8", AMD_K8)
-X86_CPU_TYPE ("k8-sse3", AMD_K8SSE3)
-#undef X86_CPU_TYPE_COMPAT_WITH_ALIAS
-#undef X86_CPU_TYPE_COMPAT
+
+// This list must match what is implemented in libgcc and compilert-rt. Clang
+// uses this to know how to implement __builtin_cpu_is.
+X86_CPU_TYPE(INTEL_BONNELL, "bonnell")
+X86_CPU_TYPE(INTEL_CORE2, "core2")
+X86_CPU_TYPE(INTEL_COREI7, "corei7")
+X86_CPU_TYPE(AMDFAM10H, "amdfam10h")
+X86_CPU_TYPE(AMDFAM15H, "amdfam15h")
+X86_CPU_TYPE(INTEL_SILVERMONT, "silvermont")
+X86_CPU_TYPE(INTEL_KNL, "knl")
+X86_CPU_TYPE(AMD_BTVER1, "btver1")
+X86_CPU_TYPE(AMD_BTVER2, "btver2")
+X86_CPU_TYPE(AMDFAM17H, "amdfam17h")
+X86_CPU_TYPE(INTEL_KNM, "knm")
+X86_CPU_TYPE(INTEL_GOLDMONT, "goldmont")
+X86_CPU_TYPE(INTEL_GOLDMONT_PLUS, "goldmont-plus")
+X86_CPU_TYPE(INTEL_TREMONT, "tremont")
+
+// Alternate names supported by __builtin_cpu_is and target multiversioning.
+X86_CPU_TYPE_ALIAS(INTEL_BONNELL, "atom")
+X86_CPU_TYPE_ALIAS(AMDFAM10H, "amdfam10")
+X86_CPU_TYPE_ALIAS(AMDFAM15H, "amdfam15")
+X86_CPU_TYPE_ALIAS(INTEL_SILVERMONT, "slm")
+
+#undef X86_CPU_TYPE_ALIAS
#undef X86_CPU_TYPE
// This macro is used for cpu subtypes present in compiler-rt/libgcc.
-#ifndef X86_CPU_SUBTYPE_COMPAT
-#define X86_CPU_SUBTYPE_COMPAT(ARCHNAME, ENUM, STR) X86_CPU_SUBTYPE(ARCHNAME, ENUM)
-#endif
-
#ifndef X86_CPU_SUBTYPE
-#define X86_CPU_SUBTYPE(ARCHNAME, ENUM)
+#define X86_CPU_SUBTYPE(ENUM, STR)
#endif
-// The first part of this list must match what is implemented in libgcc and
-// compilert-rt. Clang uses this to know how to implement __builtin_cpu_is.
-X86_CPU_SUBTYPE_COMPAT("nehalem", INTEL_COREI7_NEHALEM, "nehalem")
-X86_CPU_SUBTYPE_COMPAT("westmere", INTEL_COREI7_WESTMERE, "westmere")
-X86_CPU_SUBTYPE_COMPAT("sandybridge", INTEL_COREI7_SANDYBRIDGE, "sandybridge")
-X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_BARCELONA, "barcelona")
-X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_SHANGHAI, "shanghai")
-X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_ISTANBUL, "istanbul")
-X86_CPU_SUBTYPE_COMPAT("bdver1", AMDFAM15H_BDVER1, "bdver1")
-X86_CPU_SUBTYPE_COMPAT("bdver2", AMDFAM15H_BDVER2, "bdver2")
-X86_CPU_SUBTYPE_COMPAT("bdver3", AMDFAM15H_BDVER3, "bdver3")
-X86_CPU_SUBTYPE_COMPAT("bdver4", AMDFAM15H_BDVER4, "bdver4")
-X86_CPU_SUBTYPE_COMPAT("znver1", AMDFAM17H_ZNVER1, "znver1")
-X86_CPU_SUBTYPE_COMPAT("ivybridge", INTEL_COREI7_IVYBRIDGE, "ivybridge")
-X86_CPU_SUBTYPE_COMPAT("haswell", INTEL_COREI7_HASWELL, "haswell")
-X86_CPU_SUBTYPE_COMPAT("broadwell", INTEL_COREI7_BROADWELL, "broadwell")
-X86_CPU_SUBTYPE_COMPAT("skylake", INTEL_COREI7_SKYLAKE, "skylake")
-X86_CPU_SUBTYPE_COMPAT("skylake-avx512", INTEL_COREI7_SKYLAKE_AVX512, "skylake-avx512")
-X86_CPU_SUBTYPE_COMPAT("cannonlake", INTEL_COREI7_CANNONLAKE, "cannonlake")
-X86_CPU_SUBTYPE_COMPAT("icelake-client", INTEL_COREI7_ICELAKE_CLIENT, "icelake-client")
-X86_CPU_SUBTYPE_COMPAT("icelake-server", INTEL_COREI7_ICELAKE_SERVER, "icelake-server")
-X86_CPU_SUBTYPE_COMPAT("znver2", AMDFAM17H_ZNVER2, "znver2")
-X86_CPU_SUBTYPE_COMPAT("cascadelake", INTEL_COREI7_CASCADELAKE, "cascadelake")
-// Entries below this are not in libgcc/compiler-rt.
-X86_CPU_SUBTYPE ("core2", INTEL_CORE2_65)
-X86_CPU_SUBTYPE ("penryn", INTEL_CORE2_45)
-X86_CPU_SUBTYPE ("k6", AMDPENTIUM_K6)
-X86_CPU_SUBTYPE ("k6-2", AMDPENTIUM_K62)
-X86_CPU_SUBTYPE ("k6-3", AMDPENTIUM_K63)
-X86_CPU_SUBTYPE ("geode", AMDPENTIUM_GEODE)
-X86_CPU_SUBTYPE ("cooperlake", INTEL_COREI7_COOPERLAKE)
-X86_CPU_SUBTYPE ("tigerlake", INTEL_COREI7_TIGERLAKE)
-#undef X86_CPU_SUBTYPE_COMPAT
+// This list must match what is implemented in libgcc and compilert-rt. Clang
+// uses this to know how to implement __builtin_cpu_is.
+X86_CPU_SUBTYPE(INTEL_COREI7_NEHALEM, "nehalem")
+X86_CPU_SUBTYPE(INTEL_COREI7_WESTMERE, "westmere")
+X86_CPU_SUBTYPE(INTEL_COREI7_SANDYBRIDGE, "sandybridge")
+X86_CPU_SUBTYPE(AMDFAM10H_BARCELONA, "barcelona")
+X86_CPU_SUBTYPE(AMDFAM10H_SHANGHAI, "shanghai")
+X86_CPU_SUBTYPE(AMDFAM10H_ISTANBUL, "istanbul")
+X86_CPU_SUBTYPE(AMDFAM15H_BDVER1, "bdver1")
+X86_CPU_SUBTYPE(AMDFAM15H_BDVER2, "bdver2")
+X86_CPU_SUBTYPE(AMDFAM15H_BDVER3, "bdver3")
+X86_CPU_SUBTYPE(AMDFAM15H_BDVER4, "bdver4")
+X86_CPU_SUBTYPE(AMDFAM17H_ZNVER1, "znver1")
+X86_CPU_SUBTYPE(INTEL_COREI7_IVYBRIDGE, "ivybridge")
+X86_CPU_SUBTYPE(INTEL_COREI7_HASWELL, "haswell")
+X86_CPU_SUBTYPE(INTEL_COREI7_BROADWELL, "broadwell")
+X86_CPU_SUBTYPE(INTEL_COREI7_SKYLAKE, "skylake")
+X86_CPU_SUBTYPE(INTEL_COREI7_SKYLAKE_AVX512, "skylake-avx512")
+X86_CPU_SUBTYPE(INTEL_COREI7_CANNONLAKE, "cannonlake")
+X86_CPU_SUBTYPE(INTEL_COREI7_ICELAKE_CLIENT, "icelake-client")
+X86_CPU_SUBTYPE(INTEL_COREI7_ICELAKE_SERVER, "icelake-server")
+X86_CPU_SUBTYPE(AMDFAM17H_ZNVER2, "znver2")
+X86_CPU_SUBTYPE(INTEL_COREI7_CASCADELAKE, "cascadelake")
+X86_CPU_SUBTYPE(INTEL_COREI7_TIGERLAKE, "tigerlake")
+X86_CPU_SUBTYPE(INTEL_COREI7_COOPERLAKE, "cooperlake")
#undef X86_CPU_SUBTYPE
// This macro is used for cpu types present in compiler-rt/libgcc.
#ifndef X86_FEATURE_COMPAT
-#define X86_FEATURE_COMPAT(VAL, ENUM, STR) X86_FEATURE(VAL, ENUM)
+#define X86_FEATURE_COMPAT(ENUM, STR) X86_FEATURE(ENUM, STR)
#endif
#ifndef X86_FEATURE
-#define X86_FEATURE(VAL, ENUM)
+#define X86_FEATURE(ENUM, STR)
#endif
-X86_FEATURE_COMPAT( 0, FEATURE_CMOV, "cmov")
-X86_FEATURE_COMPAT( 1, FEATURE_MMX, "mmx")
-X86_FEATURE_COMPAT( 2, FEATURE_POPCNT, "popcnt")
-X86_FEATURE_COMPAT( 3, FEATURE_SSE, "sse")
-X86_FEATURE_COMPAT( 4, FEATURE_SSE2, "sse2")
-X86_FEATURE_COMPAT( 5, FEATURE_SSE3, "sse3")
-X86_FEATURE_COMPAT( 6, FEATURE_SSSE3, "ssse3")
-X86_FEATURE_COMPAT( 7, FEATURE_SSE4_1, "sse4.1")
-X86_FEATURE_COMPAT( 8, FEATURE_SSE4_2, "sse4.2")
-X86_FEATURE_COMPAT( 9, FEATURE_AVX, "avx")
-X86_FEATURE_COMPAT(10, FEATURE_AVX2, "avx2")
-X86_FEATURE_COMPAT(11, FEATURE_SSE4_A, "sse4a")
-X86_FEATURE_COMPAT(12, FEATURE_FMA4, "fma4")
-X86_FEATURE_COMPAT(13, FEATURE_XOP, "xop")
-X86_FEATURE_COMPAT(14, FEATURE_FMA, "fma")
-X86_FEATURE_COMPAT(15, FEATURE_AVX512F, "avx512f")
-X86_FEATURE_COMPAT(16, FEATURE_BMI, "bmi")
-X86_FEATURE_COMPAT(17, FEATURE_BMI2, "bmi2")
-X86_FEATURE_COMPAT(18, FEATURE_AES, "aes")
-X86_FEATURE_COMPAT(19, FEATURE_PCLMUL, "pclmul")
-X86_FEATURE_COMPAT(20, FEATURE_AVX512VL, "avx512vl")
-X86_FEATURE_COMPAT(21, FEATURE_AVX512BW, "avx512bw")
-X86_FEATURE_COMPAT(22, FEATURE_AVX512DQ, "avx512dq")
-X86_FEATURE_COMPAT(23, FEATURE_AVX512CD, "avx512cd")
-X86_FEATURE_COMPAT(24, FEATURE_AVX512ER, "avx512er")
-X86_FEATURE_COMPAT(25, FEATURE_AVX512PF, "avx512pf")
-X86_FEATURE_COMPAT(26, FEATURE_AVX512VBMI, "avx512vbmi")
-X86_FEATURE_COMPAT(27, FEATURE_AVX512IFMA, "avx512ifma")
-X86_FEATURE_COMPAT(28, FEATURE_AVX5124VNNIW, "avx5124vnniw")
-X86_FEATURE_COMPAT(29, FEATURE_AVX5124FMAPS, "avx5124fmaps")
-X86_FEATURE_COMPAT(30, FEATURE_AVX512VPOPCNTDQ, "avx512vpopcntdq")
-X86_FEATURE_COMPAT(31, FEATURE_AVX512VBMI2, "avx512vbmi2")
-X86_FEATURE_COMPAT(32, FEATURE_GFNI, "gfni")
-X86_FEATURE_COMPAT(33, FEATURE_VPCLMULQDQ, "vpclmulqdq")
-X86_FEATURE_COMPAT(34, FEATURE_AVX512VNNI, "avx512vnni")
-X86_FEATURE_COMPAT(35, FEATURE_AVX512BITALG, "avx512bitalg")
-X86_FEATURE_COMPAT(36, FEATURE_AVX512BF16, "avx512bf16")
+
+X86_FEATURE_COMPAT(CMOV, "cmov")
+X86_FEATURE_COMPAT(MMX, "mmx")
+X86_FEATURE_COMPAT(POPCNT, "popcnt")
+X86_FEATURE_COMPAT(SSE, "sse")
+X86_FEATURE_COMPAT(SSE2, "sse2")
+X86_FEATURE_COMPAT(SSE3, "sse3")
+X86_FEATURE_COMPAT(SSSE3, "ssse3")
+X86_FEATURE_COMPAT(SSE4_1, "sse4.1")
+X86_FEATURE_COMPAT(SSE4_2, "sse4.2")
+X86_FEATURE_COMPAT(AVX, "avx")
+X86_FEATURE_COMPAT(AVX2, "avx2")
+X86_FEATURE_COMPAT(SSE4_A, "sse4a")
+X86_FEATURE_COMPAT(FMA4, "fma4")
+X86_FEATURE_COMPAT(XOP, "xop")
+X86_FEATURE_COMPAT(FMA, "fma")
+X86_FEATURE_COMPAT(AVX512F, "avx512f")
+X86_FEATURE_COMPAT(BMI, "bmi")
+X86_FEATURE_COMPAT(BMI2, "bmi2")
+X86_FEATURE_COMPAT(AES, "aes")
+X86_FEATURE_COMPAT(PCLMUL, "pclmul")
+X86_FEATURE_COMPAT(AVX512VL, "avx512vl")
+X86_FEATURE_COMPAT(AVX512BW, "avx512bw")
+X86_FEATURE_COMPAT(AVX512DQ, "avx512dq")
+X86_FEATURE_COMPAT(AVX512CD, "avx512cd")
+X86_FEATURE_COMPAT(AVX512ER, "avx512er")
+X86_FEATURE_COMPAT(AVX512PF, "avx512pf")
+X86_FEATURE_COMPAT(AVX512VBMI, "avx512vbmi")
+X86_FEATURE_COMPAT(AVX512IFMA, "avx512ifma")
+X86_FEATURE_COMPAT(AVX5124VNNIW, "avx5124vnniw")
+X86_FEATURE_COMPAT(AVX5124FMAPS, "avx5124fmaps")
+X86_FEATURE_COMPAT(AVX512VPOPCNTDQ, "avx512vpopcntdq")
+X86_FEATURE_COMPAT(AVX512VBMI2, "avx512vbmi2")
+X86_FEATURE_COMPAT(GFNI, "gfni")
+X86_FEATURE_COMPAT(VPCLMULQDQ, "vpclmulqdq")
+X86_FEATURE_COMPAT(AVX512VNNI, "avx512vnni")
+X86_FEATURE_COMPAT(AVX512BITALG, "avx512bitalg")
+X86_FEATURE_COMPAT(AVX512BF16, "avx512bf16")
+X86_FEATURE_COMPAT(AVX512VP2INTERSECT, "avx512vp2intersect")
// Features below here are not in libgcc/compiler-rt.
-X86_FEATURE (64, FEATURE_MOVBE)
-X86_FEATURE (65, FEATURE_ADX)
-X86_FEATURE (66, FEATURE_EM64T)
-X86_FEATURE (67, FEATURE_CLFLUSHOPT)
-X86_FEATURE (68, FEATURE_SHA)
-X86_FEATURE (69, FEATURE_AVX512VP2INTERSECT)
+X86_FEATURE (3DNOW, "3dnow")
+X86_FEATURE (3DNOWA, "3dnowa")
+X86_FEATURE (64BIT, "64bit")
+X86_FEATURE (ADX, "adx")
+X86_FEATURE (AMX_BF16, "amx-bf16")
+X86_FEATURE (AMX_INT8, "amx-int8")
+X86_FEATURE (AMX_TILE, "amx-tile")
+X86_FEATURE (CLDEMOTE, "cldemote")
+X86_FEATURE (CLFLUSHOPT, "clflushopt")
+X86_FEATURE (CLWB, "clwb")
+X86_FEATURE (CLZERO, "clzero")
+X86_FEATURE (CMPXCHG16B, "cx16")
+X86_FEATURE (CMPXCHG8B, "cx8")
+X86_FEATURE (ENQCMD, "enqcmd")
+X86_FEATURE (F16C, "f16c")
+X86_FEATURE (FSGSBASE, "fsgsbase")
+X86_FEATURE (FXSR, "fxsr")
+X86_FEATURE (INVPCID, "invpcid")
+X86_FEATURE (LWP, "lwp")
+X86_FEATURE (LZCNT, "lzcnt")
+X86_FEATURE (MOVBE, "movbe")
+X86_FEATURE (MOVDIR64B, "movdir64b")
+X86_FEATURE (MOVDIRI, "movdiri")
+X86_FEATURE (MWAITX, "mwaitx")
+X86_FEATURE (PCONFIG, "pconfig")
+X86_FEATURE (PKU, "pku")
+X86_FEATURE (PREFETCHWT1, "prefetchwt1")
+X86_FEATURE (PRFCHW, "prfchw")
+X86_FEATURE (PTWRITE, "ptwrite")
+X86_FEATURE (RDPID, "rdpid")
+X86_FEATURE (RDRND, "rdrnd")
+X86_FEATURE (RDSEED, "rdseed")
+X86_FEATURE (RTM, "rtm")
+X86_FEATURE (SAHF, "sahf")
+X86_FEATURE (SERIALIZE, "serialize")
+X86_FEATURE (SGX, "sgx")
+X86_FEATURE (SHA, "sha")
+X86_FEATURE (SHSTK, "shstk")
+X86_FEATURE (TBM, "tbm")
+X86_FEATURE (TSXLDTRK, "tsxldtrk")
+X86_FEATURE (VAES, "vaes")
+X86_FEATURE (VZEROUPPER, "vzeroupper")
+X86_FEATURE (WAITPKG, "waitpkg")
+X86_FEATURE (WBNOINVD, "wbnoinvd")
+X86_FEATURE (X87, "x87")
+X86_FEATURE (XSAVE, "xsave")
+X86_FEATURE (XSAVEC, "xsavec")
+X86_FEATURE (XSAVEOPT, "xsaveopt")
+X86_FEATURE (XSAVES, "xsaves")
+// These features aren't really CPU features, but the frontend can set them.
+X86_FEATURE (RETPOLINE_EXTERNAL_THUNK, "retpoline-external-thunk")
+X86_FEATURE (RETPOLINE_INDIRECT_BRANCHES, "retpoline-indirect-branches")
+X86_FEATURE (RETPOLINE_INDIRECT_CALLS, "retpoline-indirect-calls")
+X86_FEATURE (LVI_CFI, "lvi-cfi")
+X86_FEATURE (LVI_LOAD_HARDENING, "lvi-load-hardening")
#undef X86_FEATURE_COMPAT
#undef X86_FEATURE
diff --git a/llvm/include/llvm/Support/X86TargetParser.h b/llvm/include/llvm/Support/X86TargetParser.h
new file mode 100644
index 0000000000000..66c474b5c2750
--- /dev/null
+++ b/llvm/include/llvm/Support/X86TargetParser.h
@@ -0,0 +1,148 @@
+//===-- X86TargetParser - Parser for X86 features ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise X86 hardware features.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_X86TARGETPARSERCOMMON_H
+#define LLVM_SUPPORT_X86TARGETPARSERCOMMON_H
+
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+class StringRef;
+
+namespace X86 {
+
+// This should be kept in sync with libcc/compiler-rt as its included by clang
+// as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorVendors : unsigned {
+ VENDOR_DUMMY,
+#define X86_VENDOR(ENUM, STRING) \
+ ENUM,
+#include "llvm/Support/X86TargetParser.def"
+ VENDOR_OTHER
+};
+
+// This should be kept in sync with libcc/compiler-rt as its included by clang
+// as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorTypes : unsigned {
+ CPU_TYPE_DUMMY,
+#define X86_CPU_TYPE(ENUM, STRING) \
+ ENUM,
+#include "llvm/Support/X86TargetParser.def"
+ CPU_TYPE_MAX
+};
+
+// This should be kept in sync with libcc/compiler-rt as its included by clang
+// as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorSubtypes : unsigned {
+ CPU_SUBTYPE_DUMMY,
+#define X86_CPU_SUBTYPE(ENUM, STRING) \
+ ENUM,
+#include "llvm/Support/X86TargetParser.def"
+ CPU_SUBTYPE_MAX
+};
+
+// This should be kept in sync with libcc/compiler-rt as it should be used
+// by clang as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorFeatures {
+#define X86_FEATURE(ENUM, STRING) FEATURE_##ENUM,
+#include "llvm/Support/X86TargetParser.def"
+ CPU_FEATURE_MAX
+};
+
+enum CPUKind {
+ CK_None,
+ CK_i386,
+ CK_i486,
+ CK_WinChipC6,
+ CK_WinChip2,
+ CK_C3,
+ CK_i586,
+ CK_Pentium,
+ CK_PentiumMMX,
+ CK_PentiumPro,
+ CK_i686,
+ CK_Pentium2,
+ CK_Pentium3,
+ CK_PentiumM,
+ CK_C3_2,
+ CK_Yonah,
+ CK_Pentium4,
+ CK_Prescott,
+ CK_Nocona,
+ CK_Core2,
+ CK_Penryn,
+ CK_Bonnell,
+ CK_Silvermont,
+ CK_Goldmont,
+ CK_GoldmontPlus,
+ CK_Tremont,
+ CK_Nehalem,
+ CK_Westmere,
+ CK_SandyBridge,
+ CK_IvyBridge,
+ CK_Haswell,
+ CK_Broadwell,
+ CK_SkylakeClient,
+ CK_SkylakeServer,
+ CK_Cascadelake,
+ CK_Cooperlake,
+ CK_Cannonlake,
+ CK_IcelakeClient,
+ CK_IcelakeServer,
+ CK_Tigerlake,
+ CK_KNL,
+ CK_KNM,
+ CK_Lakemont,
+ CK_K6,
+ CK_K6_2,
+ CK_K6_3,
+ CK_Athlon,
+ CK_AthlonXP,
+ CK_K8,
+ CK_K8SSE3,
+ CK_AMDFAM10,
+ CK_BTVER1,
+ CK_BTVER2,
+ CK_BDVER1,
+ CK_BDVER2,
+ CK_BDVER3,
+ CK_BDVER4,
+ CK_ZNVER1,
+ CK_ZNVER2,
+ CK_x86_64,
+ CK_Geode,
+};
+
+/// Parse \p CPU string into a CPUKind. Will only accept 64-bit capable CPUs if
+/// \p Only64Bit is true.
+CPUKind parseArchX86(StringRef CPU, bool Only64Bit = false);
+
+/// Provide a list of valid CPU names. If \p Only64Bit is true, the list will
+/// only contain 64-bit capable CPUs.
+void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values,
+ bool ArchIs32Bit);
+
+/// Get the key feature prioritizing target multiversioning.
+ProcessorFeatures getKeyFeature(CPUKind Kind);
+
+/// Fill in the features that \p CPU supports into \p Features.
+void getFeaturesForCPU(StringRef CPU, SmallVectorImpl<StringRef> &Features);
+
+/// Fill \p Features with the features that are implied to be enabled/disabled
+/// by the provided \p Feature.
+void getImpliedFeatures(StringRef Feature, bool Enabled,
+ SmallVectorImpl<StringRef> &Features);
+
+} // namespace X86
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/Support/YAMLParser.h b/llvm/include/llvm/Support/YAMLParser.h
index 3570119a3bfdb..53009d7ff4aad 100644
--- a/llvm/include/llvm/Support/YAMLParser.h
+++ b/llvm/include/llvm/Support/YAMLParser.h
@@ -139,7 +139,7 @@ public:
void operator delete(void *Ptr, BumpPtrAllocator &Alloc,
size_t Size) noexcept {
- Alloc.Deallocate(Ptr, Size);
+ Alloc.Deallocate(Ptr, Size, 0);
}
void operator delete(void *) noexcept = delete;
diff --git a/llvm/include/llvm/Support/YAMLTraits.h b/llvm/include/llvm/Support/YAMLTraits.h
index 8642069ad540c..44e34a4a09b46 100644
--- a/llvm/include/llvm/Support/YAMLTraits.h
+++ b/llvm/include/llvm/Support/YAMLTraits.h
@@ -649,24 +649,25 @@ inline bool isBool(StringRef S) {
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;
+
+ QuotingType MaxQuotingNeeded = QuotingType::None;
+ if (isSpace(static_cast<unsigned char>(S.front())) ||
+ isSpace(static_cast<unsigned char>(S.back())))
+ MaxQuotingNeeded = QuotingType::Single;
if (isNull(S))
- return QuotingType::Single;
+ MaxQuotingNeeded = QuotingType::Single;
if (isBool(S))
- return QuotingType::Single;
+ MaxQuotingNeeded = QuotingType::Single;
if (isNumeric(S))
- return QuotingType::Single;
+ MaxQuotingNeeded = QuotingType::Single;
// 7.3.3 Plain Style
// Plain scalars must not begin with most indicators, as this would cause
// ambiguity with other YAML constructs.
static constexpr char Indicators[] = R"(-?:\,[]{}#&*!|>'"%@`)";
if (S.find_first_of(Indicators) == 0)
- return QuotingType::Single;
+ MaxQuotingNeeded = QuotingType::Single;
- QuotingType MaxQuotingNeeded = QuotingType::None;
for (unsigned char C : S) {
// Alphanum is safe.
if (isAlnum(C))
@@ -684,11 +685,11 @@ inline QuotingType needsQuotes(StringRef S) {
case 0x9:
continue;
// LF(0xA) and CR(0xD) may delimit values and so require at least single
- // quotes.
+ // quotes. LLVM YAML parser cannot handle single quoted multiline so use
+ // double quoting to produce valid YAML.
case 0xA:
case 0xD:
- MaxQuotingNeeded = QuotingType::Single;
- continue;
+ return QuotingType::Double;
// DEL (0x7F) are excluded from the allowed character range.
case 0x7F:
return QuotingType::Double;
@@ -868,7 +869,7 @@ public:
}
template <typename T, typename Context>
- typename std::enable_if<has_SequenceTraits<T>::value, void>::type
+ std::enable_if_t<has_SequenceTraits<T>::value, void>
mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
// omit key/value instead of outputting empty sequence
if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
@@ -883,7 +884,7 @@ public:
}
template <typename T, typename Context>
- typename std::enable_if<!has_SequenceTraits<T>::value, void>::type
+ std::enable_if_t<!has_SequenceTraits<T>::value, void>
mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
this->processKey(Key, Val, false, Ctx);
}
@@ -965,7 +966,7 @@ template <typename T> void doMapping(IO &io, T &Val, EmptyContext &Ctx) {
} // end namespace detail
template <typename T>
-typename std::enable_if<has_ScalarEnumerationTraits<T>::value, void>::type
+std::enable_if_t<has_ScalarEnumerationTraits<T>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
io.beginEnumScalar();
ScalarEnumerationTraits<T>::enumeration(io, Val);
@@ -973,7 +974,7 @@ yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
}
template <typename T>
-typename std::enable_if<has_ScalarBitSetTraits<T>::value, void>::type
+std::enable_if_t<has_ScalarBitSetTraits<T>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
bool DoClear;
if ( io.beginBitSetScalar(DoClear) ) {
@@ -985,8 +986,8 @@ yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
}
template <typename T>
-typename std::enable_if<has_ScalarTraits<T>::value, void>::type
-yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
+std::enable_if_t<has_ScalarTraits<T>::value, void> yamlize(IO &io, T &Val, bool,
+ EmptyContext &Ctx) {
if ( io.outputting() ) {
std::string Storage;
raw_string_ostream Buffer(Storage);
@@ -1005,7 +1006,7 @@ yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
}
template <typename T>
-typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type
+std::enable_if_t<has_BlockScalarTraits<T>::value, void>
yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
if (YamlIO.outputting()) {
std::string Storage;
@@ -1024,7 +1025,7 @@ yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
}
template <typename T>
-typename std::enable_if<has_TaggedScalarTraits<T>::value, void>::type
+std::enable_if_t<has_TaggedScalarTraits<T>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
if (io.outputting()) {
std::string ScalarStorage, TagStorage;
@@ -1049,7 +1050,7 @@ yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
}
template <typename T, typename Context>
-typename std::enable_if<validatedMappingTraits<T, Context>::value, void>::type
+std::enable_if_t<validatedMappingTraits<T, Context>::value, void>
yamlize(IO &io, T &Val, bool, Context &Ctx) {
if (has_FlowTraits<MappingTraits<T>>::value)
io.beginFlowMapping();
@@ -1075,7 +1076,7 @@ yamlize(IO &io, T &Val, bool, Context &Ctx) {
}
template <typename T, typename Context>
-typename std::enable_if<unvalidatedMappingTraits<T, Context>::value, void>::type
+std::enable_if_t<unvalidatedMappingTraits<T, Context>::value, void>
yamlize(IO &io, T &Val, bool, Context &Ctx) {
if (has_FlowTraits<MappingTraits<T>>::value) {
io.beginFlowMapping();
@@ -1089,7 +1090,7 @@ yamlize(IO &io, T &Val, bool, Context &Ctx) {
}
template <typename T>
-typename std::enable_if<has_CustomMappingTraits<T>::value, void>::type
+std::enable_if_t<has_CustomMappingTraits<T>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
if ( io.outputting() ) {
io.beginMapping();
@@ -1104,7 +1105,7 @@ yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
}
template <typename T>
-typename std::enable_if<has_PolymorphicTraits<T>::value, void>::type
+std::enable_if_t<has_PolymorphicTraits<T>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val)
: io.getNodeKind()) {
@@ -1118,13 +1119,13 @@ yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
}
template <typename T>
-typename std::enable_if<missingTraits<T, EmptyContext>::value, void>::type
+std::enable_if_t<missingTraits<T, EmptyContext>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
}
template <typename T, typename Context>
-typename std::enable_if<has_SequenceTraits<T>::value, void>::type
+std::enable_if_t<has_SequenceTraits<T>::value, void>
yamlize(IO &io, T &Seq, bool, Context &Ctx) {
if ( has_FlowTraits< SequenceTraits<T>>::value ) {
unsigned incnt = io.beginFlowSequence();
@@ -1247,10 +1248,9 @@ struct ScalarTraits<double> {
// type. This way endian aware types are supported whenever the traits are
// defined for the underlying type.
template <typename value_type, support::endianness endian, size_t alignment>
-struct ScalarTraits<
- support::detail::packed_endian_specific_integral<value_type, endian,
- alignment>,
- typename std::enable_if<has_ScalarTraits<value_type>::value>::type> {
+struct ScalarTraits<support::detail::packed_endian_specific_integral<
+ value_type, endian, alignment>,
+ std::enable_if_t<has_ScalarTraits<value_type>::value>> {
using endian_type =
support::detail::packed_endian_specific_integral<value_type, endian,
alignment>;
@@ -1275,8 +1275,7 @@ 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> {
+ std::enable_if_t<has_ScalarEnumerationTraits<value_type>::value>> {
using endian_type =
support::detail::packed_endian_specific_integral<value_type, endian,
alignment>;
@@ -1292,7 +1291,7 @@ 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> {
+ std::enable_if_t<has_ScalarBitSetTraits<value_type>::value>> {
using endian_type =
support::detail::packed_endian_specific_integral<value_type, endian,
alignment>;
@@ -1688,8 +1687,7 @@ struct ScalarTraits<Hex64> {
// Define non-member operator>> so that Input can stream in a document list.
template <typename T>
-inline
-typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type
+inline std::enable_if_t<has_DocumentListTraits<T>::value, Input &>
operator>>(Input &yin, T &docList) {
int i = 0;
EmptyContext Ctx;
@@ -1705,8 +1703,7 @@ operator>>(Input &yin, T &docList) {
// Define non-member operator>> so that Input can stream in a map as a document.
template <typename T>
-inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
- Input &>::type
+inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Input &>
operator>>(Input &yin, T &docMap) {
EmptyContext Ctx;
yin.setCurrentDocument();
@@ -1717,8 +1714,7 @@ operator>>(Input &yin, T &docMap) {
// Define non-member operator>> so that Input can stream in a sequence as
// a document.
template <typename T>
-inline
-typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type
+inline std::enable_if_t<has_SequenceTraits<T>::value, Input &>
operator>>(Input &yin, T &docSeq) {
EmptyContext Ctx;
if (yin.setCurrentDocument())
@@ -1728,8 +1724,7 @@ operator>>(Input &yin, T &docSeq) {
// Define non-member operator>> so that Input can stream in a block scalar.
template <typename T>
-inline
-typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type
+inline std::enable_if_t<has_BlockScalarTraits<T>::value, Input &>
operator>>(Input &In, T &Val) {
EmptyContext Ctx;
if (In.setCurrentDocument())
@@ -1739,8 +1734,7 @@ operator>>(Input &In, T &Val) {
// Define non-member operator>> so that Input can stream in a string map.
template <typename T>
-inline
-typename std::enable_if<has_CustomMappingTraits<T>::value, Input &>::type
+inline std::enable_if_t<has_CustomMappingTraits<T>::value, Input &>
operator>>(Input &In, T &Val) {
EmptyContext Ctx;
if (In.setCurrentDocument())
@@ -1750,7 +1744,7 @@ operator>>(Input &In, T &Val) {
// Define non-member operator>> so that Input can stream in a polymorphic type.
template <typename T>
-inline typename std::enable_if<has_PolymorphicTraits<T>::value, Input &>::type
+inline std::enable_if_t<has_PolymorphicTraits<T>::value, Input &>
operator>>(Input &In, T &Val) {
EmptyContext Ctx;
if (In.setCurrentDocument())
@@ -1760,8 +1754,7 @@ operator>>(Input &In, T &Val) {
// Provide better error message about types missing a trait specialization
template <typename T>
-inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
- Input &>::type
+inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Input &>
operator>>(Input &yin, T &docSeq) {
char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
return yin;
@@ -1769,8 +1762,7 @@ operator>>(Input &yin, T &docSeq) {
// Define non-member operator<< so that Output can stream out document list.
template <typename T>
-inline
-typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type
+inline std::enable_if_t<has_DocumentListTraits<T>::value, Output &>
operator<<(Output &yout, T &docList) {
EmptyContext Ctx;
yout.beginDocuments();
@@ -1788,8 +1780,7 @@ operator<<(Output &yout, T &docList) {
// Define non-member operator<< so that Output can stream out a map.
template <typename T>
-inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
- Output &>::type
+inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Output &>
operator<<(Output &yout, T &map) {
EmptyContext Ctx;
yout.beginDocuments();
@@ -1803,8 +1794,7 @@ operator<<(Output &yout, T &map) {
// Define non-member operator<< so that Output can stream out a sequence.
template <typename T>
-inline
-typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type
+inline std::enable_if_t<has_SequenceTraits<T>::value, Output &>
operator<<(Output &yout, T &seq) {
EmptyContext Ctx;
yout.beginDocuments();
@@ -1818,8 +1808,7 @@ operator<<(Output &yout, T &seq) {
// Define non-member operator<< so that Output can stream out a block scalar.
template <typename T>
-inline
-typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type
+inline std::enable_if_t<has_BlockScalarTraits<T>::value, Output &>
operator<<(Output &Out, T &Val) {
EmptyContext Ctx;
Out.beginDocuments();
@@ -1833,8 +1822,7 @@ operator<<(Output &Out, T &Val) {
// Define non-member operator<< so that Output can stream out a string map.
template <typename T>
-inline
-typename std::enable_if<has_CustomMappingTraits<T>::value, Output &>::type
+inline std::enable_if_t<has_CustomMappingTraits<T>::value, Output &>
operator<<(Output &Out, T &Val) {
EmptyContext Ctx;
Out.beginDocuments();
@@ -1849,7 +1837,7 @@ operator<<(Output &Out, T &Val) {
// Define non-member operator<< so that Output can stream out a polymorphic
// type.
template <typename T>
-inline typename std::enable_if<has_PolymorphicTraits<T>::value, Output &>::type
+inline std::enable_if_t<has_PolymorphicTraits<T>::value, Output &>
operator<<(Output &Out, T &Val) {
EmptyContext Ctx;
Out.beginDocuments();
@@ -1866,8 +1854,7 @@ operator<<(Output &Out, T &Val) {
// Provide better error message about types missing a trait specialization
template <typename T>
-inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
- Output &>::type
+inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Output &>
operator<<(Output &yout, T &seq) {
char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
return yout;
@@ -1898,25 +1885,25 @@ 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>
+struct SequenceTraits<
+ std::vector<T>,
+ std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
: SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
template <typename T, unsigned N>
-struct SequenceTraits<SmallVector<T, N>,
- typename std::enable_if<CheckIsBool<
- SequenceElementTraits<T>::flow>::value>::type>
+struct SequenceTraits<
+ SmallVector<T, N>,
+ std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
: SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
template <typename T>
-struct SequenceTraits<SmallVectorImpl<T>,
- typename std::enable_if<CheckIsBool<
- SequenceElementTraits<T>::flow>::value>::type>
+struct SequenceTraits<
+ SmallVectorImpl<T>,
+ std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
: SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
// Sequences of fundamental types use flow formatting.
template <typename T>
-struct SequenceElementTraits<
- T, typename std::enable_if<std::is_fundamental<T>::value>::type> {
+struct SequenceElementTraits<T,
+ std::enable_if_t<std::is_fundamental<T>::value>> {
static const bool flow = true;
};
@@ -1936,7 +1923,7 @@ 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]);
+ io.mapRequired(key.str().c_str(), v[std::string(key)]);
}
static void output(IO &io, map_type &v) {
diff --git a/llvm/include/llvm/Support/circular_raw_ostream.h b/llvm/include/llvm/Support/circular_raw_ostream.h
index a72acd4fe002a..d2f01ea6a7f29 100644
--- a/llvm/include/llvm/Support/circular_raw_ostream.h
+++ b/llvm/include/llvm/Support/circular_raw_ostream.h
@@ -27,12 +27,12 @@ namespace llvm {
/// stream and is responsible for cleanup, memory management
/// issues, etc.
///
- static const bool TAKE_OWNERSHIP = true;
+ static constexpr bool TAKE_OWNERSHIP = true;
/// REFERENCE_ONLY - Tell this stream it should not manage the
/// held stream.
///
- static const bool REFERENCE_ONLY = false;
+ static constexpr bool REFERENCE_ONLY = false;
private:
/// TheStream - The real stream we output to. We set it to be
diff --git a/llvm/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h
index c8770c3375881..8d289f7c765f9 100644
--- a/llvm/include/llvm/Support/raw_ostream.h
+++ b/llvm/include/llvm/Support/raw_ostream.h
@@ -64,6 +64,11 @@ private:
/// for a \see write_impl() call to handle the data which has been put into
/// this buffer.
char *OutBufStart, *OutBufEnd, *OutBufCur;
+ bool ColorEnabled = false;
+
+ /// Optional stream this stream is tied to. If this stream is written to, the
+ /// tied-to stream will be flushed first.
+ raw_ostream *TiedStream = nullptr;
enum class BufferKind {
Unbuffered = 0,
@@ -86,16 +91,16 @@ public:
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;
+ static constexpr Colors BLACK = Colors::BLACK;
+ static constexpr Colors RED = Colors::RED;
+ static constexpr Colors GREEN = Colors::GREEN;
+ static constexpr Colors YELLOW = Colors::YELLOW;
+ static constexpr Colors BLUE = Colors::BLUE;
+ static constexpr Colors MAGENTA = Colors::MAGENTA;
+ static constexpr Colors CYAN = Colors::CYAN;
+ static constexpr Colors WHITE = Colors::WHITE;
+ static constexpr Colors SAVEDCOLOR = Colors::SAVEDCOLOR;
+ static constexpr Colors RESET = Colors::RESET;
explicit raw_ostream(bool unbuffered = false)
: BufferMode(unbuffered ? BufferKind::Unbuffered
@@ -270,21 +275,15 @@ public:
/// @param Bold bold/brighter text, default false
/// @param BG if true change the background, default: change foreground
/// @returns itself so it can be used within << invocations
- virtual raw_ostream &changeColor(enum Colors Color,
- bool Bold = false,
- bool BG = false) {
- (void)Color;
- (void)Bold;
- (void)BG;
- return *this;
- }
+ virtual raw_ostream &changeColor(enum Colors Color, bool Bold = false,
+ bool BG = false);
/// Resets the colors to terminal defaults. Call this when you are done
/// outputting colored text, or before program exit.
- virtual raw_ostream &resetColor() { return *this; }
+ virtual raw_ostream &resetColor();
/// Reverses the foreground and background colors.
- virtual raw_ostream &reverseColor() { return *this; }
+ virtual raw_ostream &reverseColor();
/// This function determines if this stream is connected to a "tty" or
/// "console" window. That is, the output would be displayed to the user
@@ -292,11 +291,16 @@ public:
virtual bool is_displayed() const { return false; }
/// This function determines if this stream is displayed and supports colors.
+ /// The result is unaffected by calls to enable_color().
virtual bool has_colors() const { return is_displayed(); }
- // Enable or disable colors. Once disable_colors() is called,
- // changeColor() has no effect until enable_colors() is called.
- virtual void enable_colors(bool /*enable*/) {}
+ // Enable or disable colors. Once enable_colors(false) is called,
+ // changeColor() has no effect until enable_colors(true) is called.
+ virtual void enable_colors(bool enable) { ColorEnabled = enable; }
+
+ /// Tie this stream to the specified stream. Replaces any existing tied-to
+ /// stream. Specifying a nullptr unties the stream.
+ void tie(raw_ostream *TieTo) { TiedStream = TieTo; }
//===--------------------------------------------------------------------===//
// Subclass Interface
@@ -352,15 +356,22 @@ private:
/// unused bytes in the buffer.
void copy_to_buffer(const char *Ptr, size_t Size);
+ /// Compute whether colors should be used and do the necessary work such as
+ /// flushing. The result is affected by calls to enable_color().
+ bool prepare_colors();
+
+ /// Flush the tied-to stream (if present) and then write the required data.
+ void flush_tied_then_write(const char *Ptr, size_t Size);
+
virtual void anchor();
};
/// Call the appropriate insertion operator, given an rvalue reference to a
/// raw_ostream object and return a stream of the same type as the argument.
template <typename OStream, typename T>
-typename std::enable_if<!std::is_reference<OStream>::value &&
- std::is_base_of<raw_ostream, OStream>::value,
- OStream &&>::type
+std::enable_if_t<!std::is_reference<OStream>::value &&
+ std::is_base_of<raw_ostream, OStream>::value,
+ OStream &&>
operator<<(OStream &&OS, const T &Value) {
OS << Value;
return std::move(OS);
@@ -398,7 +409,6 @@ 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
@@ -464,18 +474,10 @@ public:
/// 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
@@ -496,13 +498,16 @@ public:
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_fd_ostream for standard output. Use it
+/// like: outs() << "foo" << "bar";
+raw_fd_ostream &outs();
-/// This returns a reference to a raw_ostream for standard error. Use it like:
-/// errs() << "foo" << "bar";
-raw_ostream &errs();
+/// This returns a reference to a raw_ostream for standard error.
+/// Use it like: errs() << "foo" << "bar";
+/// By default, the stream is tied to stdout to ensure stdout is flushed before
+/// stderr is written, to ensure the error messages are written in their
+/// expected place.
+raw_fd_ostream &errs();
/// This returns a reference to a raw_ostream which simply discards output.
raw_ostream &nulls();
@@ -524,7 +529,9 @@ class raw_string_ostream : public raw_ostream {
uint64_t current_pos() const override { return OS.size(); }
public:
- explicit raw_string_ostream(std::string &O) : OS(O) {}
+ explicit raw_string_ostream(std::string &O) : OS(O) {
+ SetUnbuffered();
+ }
~raw_string_ostream() override;
/// Flushes the stream contents to the target string and returns the string's
@@ -565,7 +572,7 @@ public:
void flush() = delete;
/// Return a StringRef for the vector contents.
- StringRef str() { return StringRef(OS.data(), OS.size()); }
+ StringRef str() const { return StringRef(OS.data(), OS.size()); }
};
/// A raw_ostream that discards all output.
diff --git a/llvm/include/llvm/Support/type_traits.h b/llvm/include/llvm/Support/type_traits.h
index b7d48e8e1ade5..7b7d5d991f3f5 100644
--- a/llvm/include/llvm/Support/type_traits.h
+++ b/llvm/include/llvm/Support/type_traits.h
@@ -28,7 +28,7 @@ namespace llvm {
/// Also note that enum classes aren't implicitly convertible to integral types,
/// the value may therefore need to be explicitly converted before being used.
template <typename T> class is_integral_or_enum {
- using UnderlyingT = typename std::remove_reference<T>::type;
+ using UnderlyingT = std::remove_reference_t<T>;
public:
static const bool value =
@@ -45,7 +45,7 @@ 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> {
+ T, std::enable_if_t<std::is_pointer<T>::value>> {
using type = T;
};
@@ -55,9 +55,8 @@ 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 *;
+struct add_const_past_pointer<T, std::enable_if_t<std::is_pointer<T>::value>> {
+ using type = const std::remove_pointer_t<T> *;
};
template <typename T, typename Enable = void>
@@ -65,8 +64,8 @@ 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> {
+struct const_pointer_or_const_ref<T,
+ std::enable_if_t<std::is_pointer<T>::value>> {
using type = typename add_const_past_pointer<T>::type;
};