summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lib/Support
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/lib/Support')
-rw-r--r--gnu/llvm/lib/Support/AArch64TargetParser.cpp206
-rw-r--r--gnu/llvm/lib/Support/AMDGPUMetadata.cpp237
-rw-r--r--gnu/llvm/lib/Support/APFloat.cpp4523
-rw-r--r--gnu/llvm/lib/Support/APInt.cpp2925
-rw-r--r--gnu/llvm/lib/Support/APSInt.cpp43
-rw-r--r--gnu/llvm/lib/Support/ARMAttributeParser.cpp707
-rw-r--r--gnu/llvm/lib/Support/ARMBuildAttrs.cpp102
-rw-r--r--gnu/llvm/lib/Support/ARMTargetParser.cpp577
-rw-r--r--gnu/llvm/lib/Support/ARMWinEH.cpp38
-rw-r--r--gnu/llvm/lib/Support/Allocator.cpp40
-rw-r--r--gnu/llvm/lib/Support/Atomic.cpp60
-rw-r--r--gnu/llvm/lib/Support/BinaryStreamError.cpp56
-rw-r--r--gnu/llvm/lib/Support/BinaryStreamReader.cpp149
-rw-r--r--gnu/llvm/lib/Support/BinaryStreamRef.cpp131
-rw-r--r--gnu/llvm/lib/Support/BinaryStreamWriter.cpp91
-rw-r--r--gnu/llvm/lib/Support/BlockFrequency.cpp83
-rw-r--r--gnu/llvm/lib/Support/BranchProbability.cpp117
-rw-r--r--gnu/llvm/lib/Support/BuryPointer.cpp31
-rw-r--r--gnu/llvm/lib/Support/CMakeLists.txt181
-rw-r--r--gnu/llvm/lib/Support/COM.cpp23
-rw-r--r--gnu/llvm/lib/Support/COPYRIGHT.regex54
-rw-r--r--gnu/llvm/lib/Support/CachePruning.cpp300
-rw-r--r--gnu/llvm/lib/Support/Chrono.cpp94
-rw-r--r--gnu/llvm/lib/Support/CodeGenCoverage.cpp125
-rw-r--r--gnu/llvm/lib/Support/CommandLine.cpp2272
-rw-r--r--gnu/llvm/lib/Support/Compression.cpp107
-rw-r--r--gnu/llvm/lib/Support/ConvertUTF.cpp739
-rw-r--r--gnu/llvm/lib/Support/ConvertUTFWrapper.cpp251
-rw-r--r--gnu/llvm/lib/Support/CrashRecoveryContext.cpp412
-rw-r--r--gnu/llvm/lib/Support/DAGDeltaAlgorithm.cpp362
-rw-r--r--gnu/llvm/lib/Support/DJB.cpp86
-rw-r--r--gnu/llvm/lib/Support/DataExtractor.cpp192
-rw-r--r--gnu/llvm/lib/Support/Debug.cpp166
-rw-r--r--gnu/llvm/lib/Support/DebugCounter.cpp136
-rw-r--r--gnu/llvm/lib/Support/DeltaAlgorithm.cpp115
-rw-r--r--gnu/llvm/lib/Support/DynamicLibrary.cpp216
-rw-r--r--gnu/llvm/lib/Support/Errno.cpp76
-rw-r--r--gnu/llvm/lib/Support/Error.cpp185
-rw-r--r--gnu/llvm/lib/Support/ErrorHandling.cpp311
-rw-r--r--gnu/llvm/lib/Support/FileCheck.cpp1446
-rw-r--r--gnu/llvm/lib/Support/FileOutputBuffer.cpp193
-rw-r--r--gnu/llvm/lib/Support/FileUtilities.cpp267
-rw-r--r--gnu/llvm/lib/Support/FoldingSet.cpp464
-rw-r--r--gnu/llvm/lib/Support/FormatVariadic.cpp156
-rw-r--r--gnu/llvm/lib/Support/FormattedStream.cpp108
-rw-r--r--gnu/llvm/lib/Support/GlobPattern.cpp170
-rw-r--r--gnu/llvm/lib/Support/GraphWriter.cpp299
-rw-r--r--gnu/llvm/lib/Support/Hashing.cpp29
-rw-r--r--gnu/llvm/lib/Support/Host.cpp1440
-rw-r--r--gnu/llvm/lib/Support/InitLLVM.cpp52
-rw-r--r--gnu/llvm/lib/Support/IntEqClasses.cpp77
-rw-r--r--gnu/llvm/lib/Support/IntervalMap.cpp161
-rw-r--r--gnu/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp322
-rw-r--r--gnu/llvm/lib/Support/JSON.cpp699
-rw-r--r--gnu/llvm/lib/Support/JamCRC.cpp97
-rw-r--r--gnu/llvm/lib/Support/KnownBits.cpp65
-rw-r--r--gnu/llvm/lib/Support/LEB128.cpp44
-rw-r--r--gnu/llvm/lib/Support/LLVMBuild.txt22
-rw-r--r--gnu/llvm/lib/Support/LineIterator.cpp94
-rw-r--r--gnu/llvm/lib/Support/Locale.cpp19
-rw-r--r--gnu/llvm/lib/Support/LockFileManager.cpp356
-rw-r--r--gnu/llvm/lib/Support/LowLevelType.cpp56
-rw-r--r--gnu/llvm/lib/Support/MD5.cpp283
-rw-r--r--gnu/llvm/lib/Support/ManagedStatic.cpp85
-rw-r--r--gnu/llvm/lib/Support/MathExtras.cpp32
-rw-r--r--gnu/llvm/lib/Support/Memory.cpp25
-rw-r--r--gnu/llvm/lib/Support/MemoryBuffer.cpp536
-rw-r--r--gnu/llvm/lib/Support/Mutex.cpp124
-rw-r--r--gnu/llvm/lib/Support/NativeFormatting.cpp264
-rw-r--r--gnu/llvm/lib/Support/Options.cpp33
-rw-r--r--gnu/llvm/lib/Support/Parallel.cpp129
-rw-r--r--gnu/llvm/lib/Support/Path.cpp1243
-rw-r--r--gnu/llvm/lib/Support/PluginLoader.cpp47
-rw-r--r--gnu/llvm/lib/Support/PrettyStackTrace.cpp210
-rw-r--r--gnu/llvm/lib/Support/Process.cpp98
-rw-r--r--gnu/llvm/lib/Support/Program.cpp83
-rw-r--r--gnu/llvm/lib/Support/README.txt.system43
-rw-r--r--gnu/llvm/lib/Support/RWMutex.cpp125
-rw-r--r--gnu/llvm/lib/Support/RandomNumberGenerator.cpp89
-rw-r--r--gnu/llvm/lib/Support/Regex.cpp210
-rw-r--r--gnu/llvm/lib/Support/SHA1.cpp281
-rw-r--r--gnu/llvm/lib/Support/ScaledNumber.cpp324
-rw-r--r--gnu/llvm/lib/Support/ScopedPrinter.cpp46
-rw-r--r--gnu/llvm/lib/Support/Signals.cpp225
-rw-r--r--gnu/llvm/lib/Support/SmallPtrSet.cpp271
-rw-r--r--gnu/llvm/lib/Support/SmallVector.cpp66
-rw-r--r--gnu/llvm/lib/Support/SourceMgr.cpp507
-rw-r--r--gnu/llvm/lib/Support/SpecialCaseList.cpp232
-rw-r--r--gnu/llvm/lib/Support/Statistic.cpp268
-rw-r--r--gnu/llvm/lib/Support/StringExtras.cpp91
-rw-r--r--gnu/llvm/lib/Support/StringMap.cpp262
-rw-r--r--gnu/llvm/lib/Support/StringPool.cpp35
-rw-r--r--gnu/llvm/lib/Support/StringRef.cpp600
-rw-r--r--gnu/llvm/lib/Support/StringSaver.cpp27
-rw-r--r--gnu/llvm/lib/Support/SymbolRemappingReader.cpp81
-rw-r--r--gnu/llvm/lib/Support/SystemUtils.cpp31
-rw-r--r--gnu/llvm/lib/Support/TarWriter.cpp201
-rw-r--r--gnu/llvm/lib/Support/TargetParser.cpp199
-rw-r--r--gnu/llvm/lib/Support/TargetRegistry.cpp135
-rw-r--r--gnu/llvm/lib/Support/ThreadLocal.cpp48
-rw-r--r--gnu/llvm/lib/Support/ThreadPool.cpp146
-rw-r--r--gnu/llvm/lib/Support/Threading.cpp96
-rw-r--r--gnu/llvm/lib/Support/Timer.cpp432
-rw-r--r--gnu/llvm/lib/Support/ToolOutputFile.cpp46
-rw-r--r--gnu/llvm/lib/Support/TrigramIndex.cpp111
-rw-r--r--gnu/llvm/lib/Support/Triple.cpp1630
-rw-r--r--gnu/llvm/lib/Support/Twine.cpp185
-rw-r--r--gnu/llvm/lib/Support/Unicode.cpp367
-rw-r--r--gnu/llvm/lib/Support/UnicodeCaseFold.cpp742
-rw-r--r--gnu/llvm/lib/Support/Unix/COM.inc27
-rw-r--r--gnu/llvm/lib/Support/Unix/DynamicLibrary.inc135
-rw-r--r--gnu/llvm/lib/Support/Unix/Host.inc68
-rw-r--r--gnu/llvm/lib/Support/Unix/Memory.inc249
-rw-r--r--gnu/llvm/lib/Support/Unix/Mutex.inc43
-rw-r--r--gnu/llvm/lib/Support/Unix/Path.inc1067
-rw-r--r--gnu/llvm/lib/Support/Unix/Process.inc464
-rw-r--r--gnu/llvm/lib/Support/Unix/Program.inc497
-rw-r--r--gnu/llvm/lib/Support/Unix/README.txt16
-rw-r--r--gnu/llvm/lib/Support/Unix/RWMutex.inc51
-rw-r--r--gnu/llvm/lib/Support/Unix/Signals.inc586
-rw-r--r--gnu/llvm/lib/Support/Unix/ThreadLocal.inc71
-rw-r--r--gnu/llvm/lib/Support/Unix/Threading.inc220
-rw-r--r--gnu/llvm/lib/Support/Unix/Unix.h106
-rw-r--r--gnu/llvm/lib/Support/Unix/Watchdog.inc34
-rw-r--r--gnu/llvm/lib/Support/Valgrind.cpp55
-rw-r--r--gnu/llvm/lib/Support/VersionTuple.cpp110
-rw-r--r--gnu/llvm/lib/Support/VirtualFileSystem.cpp2070
-rw-r--r--gnu/llvm/lib/Support/Watchdog.cpp23
-rw-r--r--gnu/llvm/lib/Support/Windows/COM.inc37
-rw-r--r--gnu/llvm/lib/Support/Windows/DynamicLibrary.inc203
-rw-r--r--gnu/llvm/lib/Support/Windows/Host.inc34
-rw-r--r--gnu/llvm/lib/Support/Windows/Memory.inc164
-rw-r--r--gnu/llvm/lib/Support/Windows/Mutex.inc57
-rw-r--r--gnu/llvm/lib/Support/Windows/Path.inc1439
-rw-r--r--gnu/llvm/lib/Support/Windows/Process.inc486
-rw-r--r--gnu/llvm/lib/Support/Windows/Program.inc524
-rw-r--r--gnu/llvm/lib/Support/Windows/RWMutex.inc129
-rw-r--r--gnu/llvm/lib/Support/Windows/Signals.inc871
-rw-r--r--gnu/llvm/lib/Support/Windows/ThreadLocal.inc52
-rw-r--r--gnu/llvm/lib/Support/Windows/Threading.inc109
-rw-r--r--gnu/llvm/lib/Support/Windows/Watchdog.inc24
-rw-r--r--gnu/llvm/lib/Support/Windows/WindowsSupport.h235
-rw-r--r--gnu/llvm/lib/Support/Windows/explicit_symbols.inc102
-rw-r--r--gnu/llvm/lib/Support/WithColor.cpp121
-rw-r--r--gnu/llvm/lib/Support/YAMLParser.cpp2443
-rw-r--r--gnu/llvm/lib/Support/YAMLTraits.cpp1072
-rw-r--r--gnu/llvm/lib/Support/circular_raw_ostream.cpp45
-rw-r--r--gnu/llvm/lib/Support/raw_os_ostream.cpp30
-rw-r--r--gnu/llvm/lib/Support/raw_ostream.cpp918
-rw-r--r--gnu/llvm/lib/Support/regcomp.c1701
-rw-r--r--gnu/llvm/lib/Support/regengine.inc1034
-rw-r--r--gnu/llvm/lib/Support/regerror.c135
-rw-r--r--gnu/llvm/lib/Support/regex2.h165
-rw-r--r--gnu/llvm/lib/Support/regex_impl.h108
-rw-r--r--gnu/llvm/lib/Support/regexec.c162
-rw-r--r--gnu/llvm/lib/Support/regfree.c72
-rw-r--r--gnu/llvm/lib/Support/regstrlcpy.c52
-rw-r--r--gnu/llvm/lib/Support/regutils.h58
-rw-r--r--gnu/llvm/lib/Support/xxhash.cpp138
159 files changed, 0 insertions, 53111 deletions
diff --git a/gnu/llvm/lib/Support/AArch64TargetParser.cpp b/gnu/llvm/lib/Support/AArch64TargetParser.cpp
deleted file mode 100644
index e897137df68..00000000000
--- a/gnu/llvm/lib/Support/AArch64TargetParser.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-//===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a target parser to recognise AArch64 hardware features
-// such as FPU/CPU/ARCH and extension names.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/AArch64TargetParser.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include <cctype>
-
-using namespace llvm;
-
-static unsigned checkArchVersion(llvm::StringRef Arch) {
- if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1]))
- return (Arch[1] - 48);
- return 0;
-}
-
-unsigned AArch64::getDefaultFPU(StringRef CPU, AArch64::ArchKind AK) {
- if (CPU == "generic")
- return AArch64ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
-
- return StringSwitch<unsigned>(CPU)
-#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
- .Case(NAME, ARM::DEFAULT_FPU)
-#include "../../include/llvm/Support/AArch64TargetParser.def"
- .Default(ARM::FK_INVALID);
-}
-
-unsigned AArch64::getDefaultExtensions(StringRef CPU, AArch64::ArchKind AK) {
- if (CPU == "generic")
- return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
-
- return StringSwitch<unsigned>(CPU)
-#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
- .Case(NAME, AArch64ARCHNames[static_cast<unsigned>(ArchKind::ID)] \
- .ArchBaseExtensions | \
- DEFAULT_EXT)
-#include "../../include/llvm/Support/AArch64TargetParser.def"
- .Default(AArch64::AEK_INVALID);
-}
-
-AArch64::ArchKind AArch64::getCPUArchKind(StringRef CPU) {
- if (CPU == "generic")
- return ArchKind::ARMV8A;
-
- return StringSwitch<AArch64::ArchKind>(CPU)
-#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
- .Case(NAME, ArchKind::ID)
-#include "../../include/llvm/Support/AArch64TargetParser.def"
- .Default(ArchKind::INVALID);
-}
-
-bool AArch64::getExtensionFeatures(unsigned Extensions,
- std::vector<StringRef> &Features) {
- if (Extensions == AArch64::AEK_INVALID)
- return false;
-
- if (Extensions & AEK_FP)
- Features.push_back("+fp-armv8");
- if (Extensions & AEK_SIMD)
- Features.push_back("+neon");
- if (Extensions & AEK_CRC)
- Features.push_back("+crc");
- if (Extensions & AEK_CRYPTO)
- Features.push_back("+crypto");
- if (Extensions & AEK_DOTPROD)
- Features.push_back("+dotprod");
- if (Extensions & AEK_FP16FML)
- Features.push_back("+fp16fml");
- if (Extensions & AEK_FP16)
- Features.push_back("+fullfp16");
- if (Extensions & AEK_PROFILE)
- Features.push_back("+spe");
- if (Extensions & AEK_RAS)
- Features.push_back("+ras");
- if (Extensions & AEK_LSE)
- Features.push_back("+lse");
- if (Extensions & AEK_RDM)
- Features.push_back("+rdm");
- if (Extensions & AEK_SVE)
- Features.push_back("+sve");
- if (Extensions & AEK_RCPC)
- Features.push_back("+rcpc");
-
- return true;
-}
-
-bool AArch64::getArchFeatures(AArch64::ArchKind AK,
- std::vector<StringRef> &Features) {
- if (AK == ArchKind::ARMV8_1A)
- Features.push_back("+v8.1a");
- if (AK == ArchKind::ARMV8_2A)
- Features.push_back("+v8.2a");
- if (AK == ArchKind::ARMV8_3A)
- Features.push_back("+v8.3a");
- if (AK == ArchKind::ARMV8_4A)
- Features.push_back("+v8.4a");
- if (AK == ArchKind::ARMV8_5A)
- Features.push_back("+v8.5a");
-
- return AK != ArchKind::INVALID;
-}
-
-StringRef AArch64::getArchName(AArch64::ArchKind AK) {
- return AArch64ARCHNames[static_cast<unsigned>(AK)].getName();
-}
-
-StringRef AArch64::getCPUAttr(AArch64::ArchKind AK) {
- return AArch64ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
-}
-
-StringRef AArch64::getSubArch(AArch64::ArchKind AK) {
- return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch();
-}
-
-unsigned AArch64::getArchAttr(AArch64::ArchKind AK) {
- return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
-}
-
-StringRef AArch64::getArchExtName(unsigned ArchExtKind) {
- for (const auto &AE : AArch64ARCHExtNames)
- if (ArchExtKind == AE.ID)
- return AE.getName();
- return StringRef();
-}
-
-StringRef AArch64::getArchExtFeature(StringRef ArchExt) {
- if (ArchExt.startswith("no")) {
- StringRef ArchExtBase(ArchExt.substr(2));
- for (const auto &AE : AArch64ARCHExtNames) {
- if (AE.NegFeature && ArchExtBase == AE.getName())
- return StringRef(AE.NegFeature);
- }
- }
-
- for (const auto &AE : AArch64ARCHExtNames)
- if (AE.Feature && ArchExt == AE.getName())
- return StringRef(AE.Feature);
- return StringRef();
-}
-
-StringRef AArch64::getDefaultCPU(StringRef Arch) {
- ArchKind AK = parseArch(Arch);
- if (AK == ArchKind::INVALID)
- return StringRef();
-
- // Look for multiple AKs to find the default for pair AK+Name.
- for (const auto &CPU : AArch64CPUNames)
- if (CPU.ArchID == AK && CPU.Default)
- return CPU.getName();
-
- // If we can't find a default then target the architecture instead
- return "generic";
-}
-
-void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
- for (const auto &Arch : AArch64CPUNames) {
- if (Arch.ArchID != ArchKind::INVALID)
- Values.push_back(Arch.getName());
- }
-}
-
-bool AArch64::isX18ReservedByDefault(const Triple &TT) {
- return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() ||
- TT.isOSWindows();
-}
-
-// Allows partial match, ex. "v8a" matches "armv8a".
-AArch64::ArchKind AArch64::parseArch(StringRef Arch) {
- Arch = ARM::getCanonicalArchName(Arch);
- if (checkArchVersion(Arch) < 8)
- return ArchKind::INVALID;
-
- StringRef Syn = ARM::getArchSynonym(Arch);
- for (const auto A : AArch64ARCHNames) {
- if (A.getName().endswith(Syn))
- return A.ID;
- }
- return ArchKind::INVALID;
-}
-
-AArch64::ArchExtKind AArch64::parseArchExt(StringRef ArchExt) {
- for (const auto A : AArch64ARCHExtNames) {
- if (ArchExt == A.getName())
- return static_cast<ArchExtKind>(A.ID);
- }
- return AArch64::AEK_INVALID;
-}
-
-AArch64::ArchKind AArch64::parseCPUArch(StringRef CPU) {
- for (const auto C : AArch64CPUNames) {
- if (CPU == C.getName())
- return C.ArchID;
- }
- return ArchKind::INVALID;
-}
diff --git a/gnu/llvm/lib/Support/AMDGPUMetadata.cpp b/gnu/llvm/lib/Support/AMDGPUMetadata.cpp
deleted file mode 100644
index a04bfc2ea29..00000000000
--- a/gnu/llvm/lib/Support/AMDGPUMetadata.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-//===--- AMDGPUMetadata.cpp -------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file
-/// AMDGPU metadata definitions and in-memory representations.
-///
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/AMDGPUMetadata.h"
-#include "llvm/Support/YAMLTraits.h"
-
-using namespace llvm::AMDGPU;
-using namespace llvm::AMDGPU::HSAMD;
-
-LLVM_YAML_IS_SEQUENCE_VECTOR(Kernel::Arg::Metadata)
-LLVM_YAML_IS_SEQUENCE_VECTOR(Kernel::Metadata)
-
-namespace llvm {
-namespace yaml {
-
-template <>
-struct ScalarEnumerationTraits<AccessQualifier> {
- static void enumeration(IO &YIO, AccessQualifier &EN) {
- YIO.enumCase(EN, "Default", AccessQualifier::Default);
- YIO.enumCase(EN, "ReadOnly", AccessQualifier::ReadOnly);
- YIO.enumCase(EN, "WriteOnly", AccessQualifier::WriteOnly);
- YIO.enumCase(EN, "ReadWrite", AccessQualifier::ReadWrite);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<AddressSpaceQualifier> {
- static void enumeration(IO &YIO, AddressSpaceQualifier &EN) {
- YIO.enumCase(EN, "Private", AddressSpaceQualifier::Private);
- YIO.enumCase(EN, "Global", AddressSpaceQualifier::Global);
- YIO.enumCase(EN, "Constant", AddressSpaceQualifier::Constant);
- YIO.enumCase(EN, "Local", AddressSpaceQualifier::Local);
- YIO.enumCase(EN, "Generic", AddressSpaceQualifier::Generic);
- YIO.enumCase(EN, "Region", AddressSpaceQualifier::Region);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<ValueKind> {
- static void enumeration(IO &YIO, ValueKind &EN) {
- YIO.enumCase(EN, "ByValue", ValueKind::ByValue);
- YIO.enumCase(EN, "GlobalBuffer", ValueKind::GlobalBuffer);
- YIO.enumCase(EN, "DynamicSharedPointer", ValueKind::DynamicSharedPointer);
- YIO.enumCase(EN, "Sampler", ValueKind::Sampler);
- YIO.enumCase(EN, "Image", ValueKind::Image);
- YIO.enumCase(EN, "Pipe", ValueKind::Pipe);
- YIO.enumCase(EN, "Queue", ValueKind::Queue);
- YIO.enumCase(EN, "HiddenGlobalOffsetX", ValueKind::HiddenGlobalOffsetX);
- YIO.enumCase(EN, "HiddenGlobalOffsetY", ValueKind::HiddenGlobalOffsetY);
- YIO.enumCase(EN, "HiddenGlobalOffsetZ", ValueKind::HiddenGlobalOffsetZ);
- YIO.enumCase(EN, "HiddenNone", ValueKind::HiddenNone);
- YIO.enumCase(EN, "HiddenPrintfBuffer", ValueKind::HiddenPrintfBuffer);
- YIO.enumCase(EN, "HiddenDefaultQueue", ValueKind::HiddenDefaultQueue);
- YIO.enumCase(EN, "HiddenCompletionAction",
- ValueKind::HiddenCompletionAction);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<ValueType> {
- static void enumeration(IO &YIO, ValueType &EN) {
- YIO.enumCase(EN, "Struct", ValueType::Struct);
- YIO.enumCase(EN, "I8", ValueType::I8);
- YIO.enumCase(EN, "U8", ValueType::U8);
- YIO.enumCase(EN, "I16", ValueType::I16);
- YIO.enumCase(EN, "U16", ValueType::U16);
- YIO.enumCase(EN, "F16", ValueType::F16);
- YIO.enumCase(EN, "I32", ValueType::I32);
- YIO.enumCase(EN, "U32", ValueType::U32);
- YIO.enumCase(EN, "F32", ValueType::F32);
- YIO.enumCase(EN, "I64", ValueType::I64);
- YIO.enumCase(EN, "U64", ValueType::U64);
- YIO.enumCase(EN, "F64", ValueType::F64);
- }
-};
-
-template <>
-struct MappingTraits<Kernel::Attrs::Metadata> {
- static void mapping(IO &YIO, Kernel::Attrs::Metadata &MD) {
- YIO.mapOptional(Kernel::Attrs::Key::ReqdWorkGroupSize,
- MD.mReqdWorkGroupSize, std::vector<uint32_t>());
- YIO.mapOptional(Kernel::Attrs::Key::WorkGroupSizeHint,
- MD.mWorkGroupSizeHint, std::vector<uint32_t>());
- YIO.mapOptional(Kernel::Attrs::Key::VecTypeHint,
- MD.mVecTypeHint, std::string());
- YIO.mapOptional(Kernel::Attrs::Key::RuntimeHandle, MD.mRuntimeHandle,
- std::string());
- }
-};
-
-template <>
-struct MappingTraits<Kernel::Arg::Metadata> {
- static void mapping(IO &YIO, Kernel::Arg::Metadata &MD) {
- YIO.mapOptional(Kernel::Arg::Key::Name, MD.mName, std::string());
- YIO.mapOptional(Kernel::Arg::Key::TypeName, MD.mTypeName, std::string());
- YIO.mapRequired(Kernel::Arg::Key::Size, MD.mSize);
- YIO.mapRequired(Kernel::Arg::Key::Align, MD.mAlign);
- YIO.mapRequired(Kernel::Arg::Key::ValueKind, MD.mValueKind);
- YIO.mapRequired(Kernel::Arg::Key::ValueType, MD.mValueType);
- YIO.mapOptional(Kernel::Arg::Key::PointeeAlign, MD.mPointeeAlign,
- uint32_t(0));
- YIO.mapOptional(Kernel::Arg::Key::AddrSpaceQual, MD.mAddrSpaceQual,
- AddressSpaceQualifier::Unknown);
- YIO.mapOptional(Kernel::Arg::Key::AccQual, MD.mAccQual,
- AccessQualifier::Unknown);
- YIO.mapOptional(Kernel::Arg::Key::ActualAccQual, MD.mActualAccQual,
- AccessQualifier::Unknown);
- YIO.mapOptional(Kernel::Arg::Key::IsConst, MD.mIsConst, false);
- YIO.mapOptional(Kernel::Arg::Key::IsRestrict, MD.mIsRestrict, false);
- YIO.mapOptional(Kernel::Arg::Key::IsVolatile, MD.mIsVolatile, false);
- YIO.mapOptional(Kernel::Arg::Key::IsPipe, MD.mIsPipe, false);
- }
-};
-
-template <>
-struct MappingTraits<Kernel::CodeProps::Metadata> {
- static void mapping(IO &YIO, Kernel::CodeProps::Metadata &MD) {
- YIO.mapRequired(Kernel::CodeProps::Key::KernargSegmentSize,
- MD.mKernargSegmentSize);
- YIO.mapRequired(Kernel::CodeProps::Key::GroupSegmentFixedSize,
- MD.mGroupSegmentFixedSize);
- YIO.mapRequired(Kernel::CodeProps::Key::PrivateSegmentFixedSize,
- MD.mPrivateSegmentFixedSize);
- YIO.mapRequired(Kernel::CodeProps::Key::KernargSegmentAlign,
- MD.mKernargSegmentAlign);
- YIO.mapRequired(Kernel::CodeProps::Key::WavefrontSize,
- MD.mWavefrontSize);
- YIO.mapOptional(Kernel::CodeProps::Key::NumSGPRs,
- MD.mNumSGPRs, uint16_t(0));
- YIO.mapOptional(Kernel::CodeProps::Key::NumVGPRs,
- MD.mNumVGPRs, uint16_t(0));
- YIO.mapOptional(Kernel::CodeProps::Key::MaxFlatWorkGroupSize,
- MD.mMaxFlatWorkGroupSize, uint32_t(0));
- YIO.mapOptional(Kernel::CodeProps::Key::IsDynamicCallStack,
- MD.mIsDynamicCallStack, false);
- YIO.mapOptional(Kernel::CodeProps::Key::IsXNACKEnabled,
- MD.mIsXNACKEnabled, false);
- YIO.mapOptional(Kernel::CodeProps::Key::NumSpilledSGPRs,
- MD.mNumSpilledSGPRs, uint16_t(0));
- YIO.mapOptional(Kernel::CodeProps::Key::NumSpilledVGPRs,
- MD.mNumSpilledVGPRs, uint16_t(0));
- }
-};
-
-template <>
-struct MappingTraits<Kernel::DebugProps::Metadata> {
- static void mapping(IO &YIO, Kernel::DebugProps::Metadata &MD) {
- YIO.mapOptional(Kernel::DebugProps::Key::DebuggerABIVersion,
- MD.mDebuggerABIVersion, std::vector<uint32_t>());
- YIO.mapOptional(Kernel::DebugProps::Key::ReservedNumVGPRs,
- MD.mReservedNumVGPRs, uint16_t(0));
- YIO.mapOptional(Kernel::DebugProps::Key::ReservedFirstVGPR,
- MD.mReservedFirstVGPR, uint16_t(-1));
- YIO.mapOptional(Kernel::DebugProps::Key::PrivateSegmentBufferSGPR,
- MD.mPrivateSegmentBufferSGPR, uint16_t(-1));
- YIO.mapOptional(Kernel::DebugProps::Key::WavefrontPrivateSegmentOffsetSGPR,
- MD.mWavefrontPrivateSegmentOffsetSGPR, uint16_t(-1));
- }
-};
-
-template <>
-struct MappingTraits<Kernel::Metadata> {
- static void mapping(IO &YIO, Kernel::Metadata &MD) {
- YIO.mapRequired(Kernel::Key::Name, MD.mName);
- YIO.mapRequired(Kernel::Key::SymbolName, MD.mSymbolName);
- YIO.mapOptional(Kernel::Key::Language, MD.mLanguage, std::string());
- YIO.mapOptional(Kernel::Key::LanguageVersion, MD.mLanguageVersion,
- std::vector<uint32_t>());
- if (!MD.mAttrs.empty() || !YIO.outputting())
- YIO.mapOptional(Kernel::Key::Attrs, MD.mAttrs);
- if (!MD.mArgs.empty() || !YIO.outputting())
- YIO.mapOptional(Kernel::Key::Args, MD.mArgs);
- if (!MD.mCodeProps.empty() || !YIO.outputting())
- YIO.mapOptional(Kernel::Key::CodeProps, MD.mCodeProps);
- if (!MD.mDebugProps.empty() || !YIO.outputting())
- YIO.mapOptional(Kernel::Key::DebugProps, MD.mDebugProps);
- }
-};
-
-template <>
-struct MappingTraits<HSAMD::Metadata> {
- static void mapping(IO &YIO, HSAMD::Metadata &MD) {
- YIO.mapRequired(Key::Version, MD.mVersion);
- YIO.mapOptional(Key::Printf, MD.mPrintf, std::vector<std::string>());
- if (!MD.mKernels.empty() || !YIO.outputting())
- YIO.mapOptional(Key::Kernels, MD.mKernels);
- }
-};
-
-} // end namespace yaml
-
-namespace AMDGPU {
-namespace HSAMD {
-
-std::error_code fromString(std::string String, Metadata &HSAMetadata) {
- yaml::Input YamlInput(String);
- YamlInput >> HSAMetadata;
- return YamlInput.error();
-}
-
-std::error_code toString(Metadata HSAMetadata, std::string &String) {
- raw_string_ostream YamlStream(String);
- yaml::Output YamlOutput(YamlStream, nullptr, std::numeric_limits<int>::max());
- YamlOutput << HSAMetadata;
- return std::error_code();
-}
-
-} // end namespace HSAMD
-
-namespace PALMD {
-
-std::error_code toString(const Metadata &PALMetadata, std::string &String) {
- raw_string_ostream Stream(String);
- for (auto I = PALMetadata.begin(), E = PALMetadata.end(); I != E; ++I) {
- Stream << Twine(I == PALMetadata.begin() ? " 0x" : ",0x");
- Stream << Twine::utohexstr(*I);
- }
- Stream.flush();
- return std::error_code();
-}
-
-} // end namespace PALMD
-} // end namespace AMDGPU
-} // end namespace llvm
diff --git a/gnu/llvm/lib/Support/APFloat.cpp b/gnu/llvm/lib/Support/APFloat.cpp
deleted file mode 100644
index e9e429c8031..00000000000
--- a/gnu/llvm/lib/Support/APFloat.cpp
+++ /dev/null
@@ -1,4523 +0,0 @@
-//===-- APFloat.cpp - Implement APFloat class -----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a class to represent arbitrary precision floating
-// point values and provide a variety of arithmetic operations on them.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstring>
-#include <limits.h>
-
-#define APFLOAT_DISPATCH_ON_SEMANTICS(METHOD_CALL) \
- do { \
- if (usesLayout<IEEEFloat>(getSemantics())) \
- return U.IEEE.METHOD_CALL; \
- if (usesLayout<DoubleAPFloat>(getSemantics())) \
- return U.Double.METHOD_CALL; \
- llvm_unreachable("Unexpected semantics"); \
- } while (false)
-
-using namespace llvm;
-
-/// A macro used to combine two fcCategory enums into one key which can be used
-/// in a switch statement to classify how the interaction of two APFloat's
-/// categories affects an operation.
-///
-/// TODO: If clang source code is ever allowed to use constexpr in its own
-/// codebase, change this into a static inline function.
-#define PackCategoriesIntoKey(_lhs, _rhs) ((_lhs) * 4 + (_rhs))
-
-/* Assumed in hexadecimal significand parsing, and conversion to
- hexadecimal strings. */
-static_assert(APFloatBase::integerPartWidth % 4 == 0, "Part width must be divisible by 4!");
-
-namespace llvm {
- /* Represents floating point arithmetic semantics. */
- struct fltSemantics {
- /* The largest E such that 2^E is representable; this matches the
- definition of IEEE 754. */
- APFloatBase::ExponentType maxExponent;
-
- /* The smallest E such that 2^E is a normalized number; this
- matches the definition of IEEE 754. */
- APFloatBase::ExponentType minExponent;
-
- /* Number of bits in the significand. This includes the integer
- bit. */
- unsigned int precision;
-
- /* Number of bits actually used in the semantics. */
- unsigned int sizeInBits;
- };
-
- static const fltSemantics semIEEEhalf = {15, -14, 11, 16};
- static const fltSemantics semIEEEsingle = {127, -126, 24, 32};
- static const fltSemantics semIEEEdouble = {1023, -1022, 53, 64};
- static const fltSemantics semIEEEquad = {16383, -16382, 113, 128};
- static const fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80};
- static const fltSemantics semBogus = {0, 0, 0, 0};
-
- /* The IBM double-double semantics. Such a number consists of a pair of IEEE
- 64-bit doubles (Hi, Lo), where |Hi| > |Lo|, and if normal,
- (double)(Hi + Lo) == Hi. The numeric value it's modeling is Hi + Lo.
- Therefore it has two 53-bit mantissa parts that aren't necessarily adjacent
- to each other, and two 11-bit exponents.
-
- Note: we need to make the value different from semBogus as otherwise
- an unsafe optimization may collapse both values to a single address,
- and we heavily rely on them having distinct addresses. */
- static const fltSemantics semPPCDoubleDouble = {-1, 0, 0, 0};
-
- /* These are legacy semantics for the fallback, inaccrurate implementation of
- IBM double-double, if the accurate semPPCDoubleDouble doesn't handle the
- operation. It's equivalent to having an IEEE number with consecutive 106
- bits of mantissa and 11 bits of exponent.
-
- It's not equivalent to IBM double-double. For example, a legit IBM
- double-double, 1 + epsilon:
-
- 1 + epsilon = 1 + (1 >> 1076)
-
- is not representable by a consecutive 106 bits of mantissa.
-
- Currently, these semantics are used in the following way:
-
- semPPCDoubleDouble -> (IEEEdouble, IEEEdouble) ->
- (64-bit APInt, 64-bit APInt) -> (128-bit APInt) ->
- semPPCDoubleDoubleLegacy -> IEEE operations
-
- We use bitcastToAPInt() to get the bit representation (in APInt) of the
- underlying IEEEdouble, then use the APInt constructor to construct the
- legacy IEEE float.
-
- TODO: Implement all operations in semPPCDoubleDouble, and delete these
- semantics. */
- static const fltSemantics semPPCDoubleDoubleLegacy = {1023, -1022 + 53,
- 53 + 53, 128};
-
- const fltSemantics &APFloatBase::IEEEhalf() {
- return semIEEEhalf;
- }
- const fltSemantics &APFloatBase::IEEEsingle() {
- return semIEEEsingle;
- }
- const fltSemantics &APFloatBase::IEEEdouble() {
- return semIEEEdouble;
- }
- const fltSemantics &APFloatBase::IEEEquad() {
- return semIEEEquad;
- }
- const fltSemantics &APFloatBase::x87DoubleExtended() {
- return semX87DoubleExtended;
- }
- const fltSemantics &APFloatBase::Bogus() {
- return semBogus;
- }
- const fltSemantics &APFloatBase::PPCDoubleDouble() {
- return semPPCDoubleDouble;
- }
-
- /* A tight upper bound on number of parts required to hold the value
- pow(5, power) is
-
- power * 815 / (351 * integerPartWidth) + 1
-
- However, whilst the result may require only this many parts,
- because we are multiplying two values to get it, the
- multiplication may require an extra part with the excess part
- being zero (consider the trivial case of 1 * 1, tcFullMultiply
- requires two parts to hold the single-part result). So we add an
- extra one to guarantee enough space whilst multiplying. */
- const unsigned int maxExponent = 16383;
- const unsigned int maxPrecision = 113;
- const unsigned int maxPowerOfFiveExponent = maxExponent + maxPrecision - 1;
- const unsigned int maxPowerOfFiveParts = 2 + ((maxPowerOfFiveExponent * 815) / (351 * APFloatBase::integerPartWidth));
-
- unsigned int APFloatBase::semanticsPrecision(const fltSemantics &semantics) {
- return semantics.precision;
- }
- APFloatBase::ExponentType
- APFloatBase::semanticsMaxExponent(const fltSemantics &semantics) {
- return semantics.maxExponent;
- }
- APFloatBase::ExponentType
- APFloatBase::semanticsMinExponent(const fltSemantics &semantics) {
- return semantics.minExponent;
- }
- unsigned int APFloatBase::semanticsSizeInBits(const fltSemantics &semantics) {
- return semantics.sizeInBits;
- }
-
- unsigned APFloatBase::getSizeInBits(const fltSemantics &Sem) {
- return Sem.sizeInBits;
-}
-
-/* A bunch of private, handy routines. */
-
-static inline unsigned int
-partCountForBits(unsigned int bits)
-{
- return ((bits) + APFloatBase::integerPartWidth - 1) / APFloatBase::integerPartWidth;
-}
-
-/* Returns 0U-9U. Return values >= 10U are not digits. */
-static inline unsigned int
-decDigitValue(unsigned int c)
-{
- return c - '0';
-}
-
-/* Return the value of a decimal exponent of the form
- [+-]ddddddd.
-
- If the exponent overflows, returns a large exponent with the
- appropriate sign. */
-static int
-readExponent(StringRef::iterator begin, StringRef::iterator end)
-{
- bool isNegative;
- unsigned int absExponent;
- const unsigned int overlargeExponent = 24000; /* FIXME. */
- StringRef::iterator p = begin;
-
- assert(p != end && "Exponent has no digits");
-
- isNegative = (*p == '-');
- if (*p == '-' || *p == '+') {
- p++;
- assert(p != end && "Exponent has no digits");
- }
-
- absExponent = decDigitValue(*p++);
- assert(absExponent < 10U && "Invalid character in exponent");
-
- for (; p != end; ++p) {
- unsigned int value;
-
- value = decDigitValue(*p);
- assert(value < 10U && "Invalid character in exponent");
-
- value += absExponent * 10;
- if (absExponent >= overlargeExponent) {
- absExponent = overlargeExponent;
- p = end; /* outwit assert below */
- break;
- }
- absExponent = value;
- }
-
- assert(p == end && "Invalid exponent in exponent");
-
- if (isNegative)
- return -(int) absExponent;
- else
- return (int) absExponent;
-}
-
-/* This is ugly and needs cleaning up, but I don't immediately see
- how whilst remaining safe. */
-static int
-totalExponent(StringRef::iterator p, StringRef::iterator end,
- int exponentAdjustment)
-{
- int unsignedExponent;
- bool negative, overflow;
- int exponent = 0;
-
- assert(p != end && "Exponent has no digits");
-
- negative = *p == '-';
- if (*p == '-' || *p == '+') {
- p++;
- assert(p != end && "Exponent has no digits");
- }
-
- unsignedExponent = 0;
- overflow = false;
- for (; p != end; ++p) {
- unsigned int value;
-
- value = decDigitValue(*p);
- assert(value < 10U && "Invalid character in exponent");
-
- unsignedExponent = unsignedExponent * 10 + value;
- if (unsignedExponent > 32767) {
- overflow = true;
- break;
- }
- }
-
- if (exponentAdjustment > 32767 || exponentAdjustment < -32768)
- overflow = true;
-
- if (!overflow) {
- exponent = unsignedExponent;
- if (negative)
- exponent = -exponent;
- exponent += exponentAdjustment;
- if (exponent > 32767 || exponent < -32768)
- overflow = true;
- }
-
- if (overflow)
- exponent = negative ? -32768: 32767;
-
- return exponent;
-}
-
-static StringRef::iterator
-skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end,
- StringRef::iterator *dot)
-{
- StringRef::iterator p = begin;
- *dot = end;
- while (p != end && *p == '0')
- p++;
-
- if (p != end && *p == '.') {
- *dot = p++;
-
- assert(end - begin != 1 && "Significand has no digits");
-
- while (p != end && *p == '0')
- p++;
- }
-
- return p;
-}
-
-/* Given a normal decimal floating point number of the form
-
- dddd.dddd[eE][+-]ddd
-
- where the decimal point and exponent are optional, fill out the
- structure D. Exponent is appropriate if the significand is
- treated as an integer, and normalizedExponent if the significand
- is taken to have the decimal point after a single leading
- non-zero digit.
-
- If the value is zero, V->firstSigDigit points to a non-digit, and
- the return exponent is zero.
-*/
-struct decimalInfo {
- const char *firstSigDigit;
- const char *lastSigDigit;
- int exponent;
- int normalizedExponent;
-};
-
-static void
-interpretDecimal(StringRef::iterator begin, StringRef::iterator end,
- decimalInfo *D)
-{
- StringRef::iterator dot = end;
- StringRef::iterator p = skipLeadingZeroesAndAnyDot (begin, end, &dot);
-
- D->firstSigDigit = p;
- D->exponent = 0;
- D->normalizedExponent = 0;
-
- for (; p != end; ++p) {
- if (*p == '.') {
- assert(dot == end && "String contains multiple dots");
- dot = p++;
- if (p == end)
- break;
- }
- if (decDigitValue(*p) >= 10U)
- break;
- }
-
- if (p != end) {
- assert((*p == 'e' || *p == 'E') && "Invalid character in significand");
- assert(p != begin && "Significand has no digits");
- assert((dot == end || p - begin != 1) && "Significand has no digits");
-
- /* p points to the first non-digit in the string */
- D->exponent = readExponent(p + 1, end);
-
- /* Implied decimal point? */
- if (dot == end)
- dot = p;
- }
-
- /* If number is all zeroes accept any exponent. */
- if (p != D->firstSigDigit) {
- /* Drop insignificant trailing zeroes. */
- if (p != begin) {
- do
- do
- p--;
- while (p != begin && *p == '0');
- while (p != begin && *p == '.');
- }
-
- /* Adjust the exponents for any decimal point. */
- D->exponent += static_cast<APFloat::ExponentType>((dot - p) - (dot > p));
- D->normalizedExponent = (D->exponent +
- static_cast<APFloat::ExponentType>((p - D->firstSigDigit)
- - (dot > D->firstSigDigit && dot < p)));
- }
-
- D->lastSigDigit = p;
-}
-
-/* Return the trailing fraction of a hexadecimal number.
- DIGITVALUE is the first hex digit of the fraction, P points to
- the next digit. */
-static lostFraction
-trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end,
- unsigned int digitValue)
-{
- unsigned int hexDigit;
-
- /* If the first trailing digit isn't 0 or 8 we can work out the
- fraction immediately. */
- if (digitValue > 8)
- return lfMoreThanHalf;
- else if (digitValue < 8 && digitValue > 0)
- return lfLessThanHalf;
-
- // Otherwise we need to find the first non-zero digit.
- while (p != end && (*p == '0' || *p == '.'))
- p++;
-
- assert(p != end && "Invalid trailing hexadecimal fraction!");
-
- hexDigit = hexDigitValue(*p);
-
- /* If we ran off the end it is exactly zero or one-half, otherwise
- a little more. */
- if (hexDigit == -1U)
- return digitValue == 0 ? lfExactlyZero: lfExactlyHalf;
- else
- return digitValue == 0 ? lfLessThanHalf: lfMoreThanHalf;
-}
-
-/* Return the fraction lost were a bignum truncated losing the least
- significant BITS bits. */
-static lostFraction
-lostFractionThroughTruncation(const APFloatBase::integerPart *parts,
- unsigned int partCount,
- unsigned int bits)
-{
- unsigned int lsb;
-
- lsb = APInt::tcLSB(parts, partCount);
-
- /* Note this is guaranteed true if bits == 0, or LSB == -1U. */
- if (bits <= lsb)
- return lfExactlyZero;
- if (bits == lsb + 1)
- return lfExactlyHalf;
- if (bits <= partCount * APFloatBase::integerPartWidth &&
- APInt::tcExtractBit(parts, bits - 1))
- return lfMoreThanHalf;
-
- return lfLessThanHalf;
-}
-
-/* Shift DST right BITS bits noting lost fraction. */
-static lostFraction
-shiftRight(APFloatBase::integerPart *dst, unsigned int parts, unsigned int bits)
-{
- lostFraction lost_fraction;
-
- lost_fraction = lostFractionThroughTruncation(dst, parts, bits);
-
- APInt::tcShiftRight(dst, parts, bits);
-
- return lost_fraction;
-}
-
-/* Combine the effect of two lost fractions. */
-static lostFraction
-combineLostFractions(lostFraction moreSignificant,
- lostFraction lessSignificant)
-{
- if (lessSignificant != lfExactlyZero) {
- if (moreSignificant == lfExactlyZero)
- moreSignificant = lfLessThanHalf;
- else if (moreSignificant == lfExactlyHalf)
- moreSignificant = lfMoreThanHalf;
- }
-
- return moreSignificant;
-}
-
-/* The error from the true value, in half-ulps, on multiplying two
- floating point numbers, which differ from the value they
- approximate by at most HUE1 and HUE2 half-ulps, is strictly less
- than the returned value.
-
- See "How to Read Floating Point Numbers Accurately" by William D
- Clinger. */
-static unsigned int
-HUerrBound(bool inexactMultiply, unsigned int HUerr1, unsigned int HUerr2)
-{
- assert(HUerr1 < 2 || HUerr2 < 2 || (HUerr1 + HUerr2 < 8));
-
- if (HUerr1 + HUerr2 == 0)
- return inexactMultiply * 2; /* <= inexactMultiply half-ulps. */
- else
- return inexactMultiply + 2 * (HUerr1 + HUerr2);
-}
-
-/* The number of ulps from the boundary (zero, or half if ISNEAREST)
- when the least significant BITS are truncated. BITS cannot be
- zero. */
-static APFloatBase::integerPart
-ulpsFromBoundary(const APFloatBase::integerPart *parts, unsigned int bits,
- bool isNearest) {
- unsigned int count, partBits;
- APFloatBase::integerPart part, boundary;
-
- assert(bits != 0);
-
- bits--;
- count = bits / APFloatBase::integerPartWidth;
- partBits = bits % APFloatBase::integerPartWidth + 1;
-
- part = parts[count] & (~(APFloatBase::integerPart) 0 >> (APFloatBase::integerPartWidth - partBits));
-
- if (isNearest)
- boundary = (APFloatBase::integerPart) 1 << (partBits - 1);
- else
- boundary = 0;
-
- if (count == 0) {
- if (part - boundary <= boundary - part)
- return part - boundary;
- else
- return boundary - part;
- }
-
- if (part == boundary) {
- while (--count)
- if (parts[count])
- return ~(APFloatBase::integerPart) 0; /* A lot. */
-
- return parts[0];
- } else if (part == boundary - 1) {
- while (--count)
- if (~parts[count])
- return ~(APFloatBase::integerPart) 0; /* A lot. */
-
- return -parts[0];
- }
-
- return ~(APFloatBase::integerPart) 0; /* A lot. */
-}
-
-/* Place pow(5, power) in DST, and return the number of parts used.
- DST must be at least one part larger than size of the answer. */
-static unsigned int
-powerOf5(APFloatBase::integerPart *dst, unsigned int power) {
- static const APFloatBase::integerPart firstEightPowers[] = { 1, 5, 25, 125, 625, 3125, 15625, 78125 };
- APFloatBase::integerPart pow5s[maxPowerOfFiveParts * 2 + 5];
- pow5s[0] = 78125 * 5;
-
- unsigned int partsCount[16] = { 1 };
- APFloatBase::integerPart scratch[maxPowerOfFiveParts], *p1, *p2, *pow5;
- unsigned int result;
- assert(power <= maxExponent);
-
- p1 = dst;
- p2 = scratch;
-
- *p1 = firstEightPowers[power & 7];
- power >>= 3;
-
- result = 1;
- pow5 = pow5s;
-
- for (unsigned int n = 0; power; power >>= 1, n++) {
- unsigned int pc;
-
- pc = partsCount[n];
-
- /* Calculate pow(5,pow(2,n+3)) if we haven't yet. */
- if (pc == 0) {
- pc = partsCount[n - 1];
- APInt::tcFullMultiply(pow5, pow5 - pc, pow5 - pc, pc, pc);
- pc *= 2;
- if (pow5[pc - 1] == 0)
- pc--;
- partsCount[n] = pc;
- }
-
- if (power & 1) {
- APFloatBase::integerPart *tmp;
-
- APInt::tcFullMultiply(p2, p1, pow5, result, pc);
- result += pc;
- if (p2[result - 1] == 0)
- result--;
-
- /* Now result is in p1 with partsCount parts and p2 is scratch
- space. */
- tmp = p1;
- p1 = p2;
- p2 = tmp;
- }
-
- pow5 += pc;
- }
-
- if (p1 != dst)
- APInt::tcAssign(dst, p1, result);
-
- return result;
-}
-
-/* Zero at the end to avoid modular arithmetic when adding one; used
- when rounding up during hexadecimal output. */
-static const char hexDigitsLower[] = "0123456789abcdef0";
-static const char hexDigitsUpper[] = "0123456789ABCDEF0";
-static const char infinityL[] = "infinity";
-static const char infinityU[] = "INFINITY";
-static const char NaNL[] = "nan";
-static const char NaNU[] = "NAN";
-
-/* Write out an integerPart in hexadecimal, starting with the most
- significant nibble. Write out exactly COUNT hexdigits, return
- COUNT. */
-static unsigned int
-partAsHex (char *dst, APFloatBase::integerPart part, unsigned int count,
- const char *hexDigitChars)
-{
- unsigned int result = count;
-
- assert(count != 0 && count <= APFloatBase::integerPartWidth / 4);
-
- part >>= (APFloatBase::integerPartWidth - 4 * count);
- while (count--) {
- dst[count] = hexDigitChars[part & 0xf];
- part >>= 4;
- }
-
- return result;
-}
-
-/* Write out an unsigned decimal integer. */
-static char *
-writeUnsignedDecimal (char *dst, unsigned int n)
-{
- char buff[40], *p;
-
- p = buff;
- do
- *p++ = '0' + n % 10;
- while (n /= 10);
-
- do
- *dst++ = *--p;
- while (p != buff);
-
- return dst;
-}
-
-/* Write out a signed decimal integer. */
-static char *
-writeSignedDecimal (char *dst, int value)
-{
- if (value < 0) {
- *dst++ = '-';
- dst = writeUnsignedDecimal(dst, -(unsigned) value);
- } else
- dst = writeUnsignedDecimal(dst, value);
-
- return dst;
-}
-
-namespace detail {
-/* Constructors. */
-void IEEEFloat::initialize(const fltSemantics *ourSemantics) {
- unsigned int count;
-
- semantics = ourSemantics;
- count = partCount();
- if (count > 1)
- significand.parts = new integerPart[count];
-}
-
-void IEEEFloat::freeSignificand() {
- if (needsCleanup())
- delete [] significand.parts;
-}
-
-void IEEEFloat::assign(const IEEEFloat &rhs) {
- assert(semantics == rhs.semantics);
-
- sign = rhs.sign;
- category = rhs.category;
- exponent = rhs.exponent;
- if (isFiniteNonZero() || category == fcNaN)
- copySignificand(rhs);
-}
-
-void IEEEFloat::copySignificand(const IEEEFloat &rhs) {
- assert(isFiniteNonZero() || category == fcNaN);
- assert(rhs.partCount() >= partCount());
-
- APInt::tcAssign(significandParts(), rhs.significandParts(),
- partCount());
-}
-
-/* Make this number a NaN, with an arbitrary but deterministic value
- for the significand. If double or longer, this is a signalling NaN,
- which may not be ideal. If float, this is QNaN(0). */
-void IEEEFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) {
- category = fcNaN;
- sign = Negative;
-
- integerPart *significand = significandParts();
- unsigned numParts = partCount();
-
- // Set the significand bits to the fill.
- if (!fill || fill->getNumWords() < numParts)
- APInt::tcSet(significand, 0, numParts);
- if (fill) {
- APInt::tcAssign(significand, fill->getRawData(),
- std::min(fill->getNumWords(), numParts));
-
- // Zero out the excess bits of the significand.
- unsigned bitsToPreserve = semantics->precision - 1;
- unsigned part = bitsToPreserve / 64;
- bitsToPreserve %= 64;
- significand[part] &= ((1ULL << bitsToPreserve) - 1);
- for (part++; part != numParts; ++part)
- significand[part] = 0;
- }
-
- unsigned QNaNBit = semantics->precision - 2;
-
- if (SNaN) {
- // We always have to clear the QNaN bit to make it an SNaN.
- APInt::tcClearBit(significand, QNaNBit);
-
- // If there are no bits set in the payload, we have to set
- // *something* to make it a NaN instead of an infinity;
- // conventionally, this is the next bit down from the QNaN bit.
- if (APInt::tcIsZero(significand, numParts))
- APInt::tcSetBit(significand, QNaNBit - 1);
- } else {
- // We always have to set the QNaN bit to make it a QNaN.
- APInt::tcSetBit(significand, QNaNBit);
- }
-
- // For x87 extended precision, we want to make a NaN, not a
- // pseudo-NaN. Maybe we should expose the ability to make
- // pseudo-NaNs?
- if (semantics == &semX87DoubleExtended)
- APInt::tcSetBit(significand, QNaNBit + 1);
-}
-
-IEEEFloat &IEEEFloat::operator=(const IEEEFloat &rhs) {
- if (this != &rhs) {
- if (semantics != rhs.semantics) {
- freeSignificand();
- initialize(rhs.semantics);
- }
- assign(rhs);
- }
-
- return *this;
-}
-
-IEEEFloat &IEEEFloat::operator=(IEEEFloat &&rhs) {
- freeSignificand();
-
- semantics = rhs.semantics;
- significand = rhs.significand;
- exponent = rhs.exponent;
- category = rhs.category;
- sign = rhs.sign;
-
- rhs.semantics = &semBogus;
- return *this;
-}
-
-bool IEEEFloat::isDenormal() const {
- return isFiniteNonZero() && (exponent == semantics->minExponent) &&
- (APInt::tcExtractBit(significandParts(),
- semantics->precision - 1) == 0);
-}
-
-bool IEEEFloat::isSmallest() const {
- // The smallest number by magnitude in our format will be the smallest
- // denormal, i.e. the floating point number with exponent being minimum
- // exponent and significand bitwise equal to 1 (i.e. with MSB equal to 0).
- return isFiniteNonZero() && exponent == semantics->minExponent &&
- significandMSB() == 0;
-}
-
-bool IEEEFloat::isSignificandAllOnes() const {
- // Test if the significand excluding the integral bit is all ones. This allows
- // us to test for binade boundaries.
- const integerPart *Parts = significandParts();
- const unsigned PartCount = partCount();
- for (unsigned i = 0; i < PartCount - 1; i++)
- if (~Parts[i])
- return false;
-
- // Set the unused high bits to all ones when we compare.
- const unsigned NumHighBits =
- PartCount*integerPartWidth - semantics->precision + 1;
- assert(NumHighBits <= integerPartWidth && "Can not have more high bits to "
- "fill than integerPartWidth");
- const integerPart HighBitFill =
- ~integerPart(0) << (integerPartWidth - NumHighBits);
- if (~(Parts[PartCount - 1] | HighBitFill))
- return false;
-
- return true;
-}
-
-bool IEEEFloat::isSignificandAllZeros() const {
- // Test if the significand excluding the integral bit is all zeros. This
- // allows us to test for binade boundaries.
- const integerPart *Parts = significandParts();
- const unsigned PartCount = partCount();
-
- for (unsigned i = 0; i < PartCount - 1; i++)
- if (Parts[i])
- return false;
-
- const unsigned NumHighBits =
- PartCount*integerPartWidth - semantics->precision + 1;
- assert(NumHighBits <= integerPartWidth && "Can not have more high bits to "
- "clear than integerPartWidth");
- const integerPart HighBitMask = ~integerPart(0) >> NumHighBits;
-
- if (Parts[PartCount - 1] & HighBitMask)
- return false;
-
- return true;
-}
-
-bool IEEEFloat::isLargest() const {
- // The largest number by magnitude in our format will be the floating point
- // number with maximum exponent and with significand that is all ones.
- return isFiniteNonZero() && exponent == semantics->maxExponent
- && isSignificandAllOnes();
-}
-
-bool IEEEFloat::isInteger() const {
- // This could be made more efficient; I'm going for obviously correct.
- if (!isFinite()) return false;
- IEEEFloat truncated = *this;
- truncated.roundToIntegral(rmTowardZero);
- return compare(truncated) == cmpEqual;
-}
-
-bool IEEEFloat::bitwiseIsEqual(const IEEEFloat &rhs) const {
- if (this == &rhs)
- return true;
- if (semantics != rhs.semantics ||
- category != rhs.category ||
- sign != rhs.sign)
- return false;
- if (category==fcZero || category==fcInfinity)
- return true;
-
- if (isFiniteNonZero() && exponent != rhs.exponent)
- return false;
-
- return std::equal(significandParts(), significandParts() + partCount(),
- rhs.significandParts());
-}
-
-IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, integerPart value) {
- initialize(&ourSemantics);
- sign = 0;
- category = fcNormal;
- zeroSignificand();
- exponent = ourSemantics.precision - 1;
- significandParts()[0] = value;
- normalize(rmNearestTiesToEven, lfExactlyZero);
-}
-
-IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics) {
- initialize(&ourSemantics);
- category = fcZero;
- sign = false;
-}
-
-// Delegate to the previous constructor, because later copy constructor may
-// actually inspects category, which can't be garbage.
-IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, uninitializedTag tag)
- : IEEEFloat(ourSemantics) {}
-
-IEEEFloat::IEEEFloat(const IEEEFloat &rhs) {
- initialize(rhs.semantics);
- assign(rhs);
-}
-
-IEEEFloat::IEEEFloat(IEEEFloat &&rhs) : semantics(&semBogus) {
- *this = std::move(rhs);
-}
-
-IEEEFloat::~IEEEFloat() { freeSignificand(); }
-
-unsigned int IEEEFloat::partCount() const {
- return partCountForBits(semantics->precision + 1);
-}
-
-const IEEEFloat::integerPart *IEEEFloat::significandParts() const {
- return const_cast<IEEEFloat *>(this)->significandParts();
-}
-
-IEEEFloat::integerPart *IEEEFloat::significandParts() {
- if (partCount() > 1)
- return significand.parts;
- else
- return &significand.part;
-}
-
-void IEEEFloat::zeroSignificand() {
- APInt::tcSet(significandParts(), 0, partCount());
-}
-
-/* Increment an fcNormal floating point number's significand. */
-void IEEEFloat::incrementSignificand() {
- integerPart carry;
-
- carry = APInt::tcIncrement(significandParts(), partCount());
-
- /* Our callers should never cause us to overflow. */
- assert(carry == 0);
- (void)carry;
-}
-
-/* Add the significand of the RHS. Returns the carry flag. */
-IEEEFloat::integerPart IEEEFloat::addSignificand(const IEEEFloat &rhs) {
- integerPart *parts;
-
- parts = significandParts();
-
- assert(semantics == rhs.semantics);
- assert(exponent == rhs.exponent);
-
- return APInt::tcAdd(parts, rhs.significandParts(), 0, partCount());
-}
-
-/* Subtract the significand of the RHS with a borrow flag. Returns
- the borrow flag. */
-IEEEFloat::integerPart IEEEFloat::subtractSignificand(const IEEEFloat &rhs,
- integerPart borrow) {
- integerPart *parts;
-
- parts = significandParts();
-
- assert(semantics == rhs.semantics);
- assert(exponent == rhs.exponent);
-
- return APInt::tcSubtract(parts, rhs.significandParts(), borrow,
- partCount());
-}
-
-/* Multiply the significand of the RHS. If ADDEND is non-NULL, add it
- on to the full-precision result of the multiplication. Returns the
- lost fraction. */
-lostFraction IEEEFloat::multiplySignificand(const IEEEFloat &rhs,
- const IEEEFloat *addend) {
- unsigned int omsb; // One, not zero, based MSB.
- unsigned int partsCount, newPartsCount, precision;
- integerPart *lhsSignificand;
- integerPart scratch[4];
- integerPart *fullSignificand;
- lostFraction lost_fraction;
- bool ignored;
-
- assert(semantics == rhs.semantics);
-
- precision = semantics->precision;
-
- // Allocate space for twice as many bits as the original significand, plus one
- // extra bit for the addition to overflow into.
- newPartsCount = partCountForBits(precision * 2 + 1);
-
- if (newPartsCount > 4)
- fullSignificand = new integerPart[newPartsCount];
- else
- fullSignificand = scratch;
-
- lhsSignificand = significandParts();
- partsCount = partCount();
-
- APInt::tcFullMultiply(fullSignificand, lhsSignificand,
- rhs.significandParts(), partsCount, partsCount);
-
- lost_fraction = lfExactlyZero;
- omsb = APInt::tcMSB(fullSignificand, newPartsCount) + 1;
- exponent += rhs.exponent;
-
- // Assume the operands involved in the multiplication are single-precision
- // FP, and the two multiplicants are:
- // *this = a23 . a22 ... a0 * 2^e1
- // rhs = b23 . b22 ... b0 * 2^e2
- // the result of multiplication is:
- // *this = c48 c47 c46 . c45 ... c0 * 2^(e1+e2)
- // Note that there are three significant bits at the left-hand side of the
- // radix point: two for the multiplication, and an overflow bit for the
- // addition (that will always be zero at this point). Move the radix point
- // toward left by two bits, and adjust exponent accordingly.
- exponent += 2;
-
- if (addend && addend->isNonZero()) {
- // The intermediate result of the multiplication has "2 * precision"
- // signicant bit; adjust the addend to be consistent with mul result.
- //
- Significand savedSignificand = significand;
- const fltSemantics *savedSemantics = semantics;
- fltSemantics extendedSemantics;
- opStatus status;
- unsigned int extendedPrecision;
-
- // Normalize our MSB to one below the top bit to allow for overflow.
- extendedPrecision = 2 * precision + 1;
- if (omsb != extendedPrecision - 1) {
- assert(extendedPrecision > omsb);
- APInt::tcShiftLeft(fullSignificand, newPartsCount,
- (extendedPrecision - 1) - omsb);
- exponent -= (extendedPrecision - 1) - omsb;
- }
-
- /* Create new semantics. */
- extendedSemantics = *semantics;
- extendedSemantics.precision = extendedPrecision;
-
- if (newPartsCount == 1)
- significand.part = fullSignificand[0];
- else
- significand.parts = fullSignificand;
- semantics = &extendedSemantics;
-
- IEEEFloat extendedAddend(*addend);
- status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored);
- assert(status == opOK);
- (void)status;
-
- // Shift the significand of the addend right by one bit. This guarantees
- // that the high bit of the significand is zero (same as fullSignificand),
- // so the addition will overflow (if it does overflow at all) into the top bit.
- lost_fraction = extendedAddend.shiftSignificandRight(1);
- assert(lost_fraction == lfExactlyZero &&
- "Lost precision while shifting addend for fused-multiply-add.");
-
- lost_fraction = addOrSubtractSignificand(extendedAddend, false);
-
- /* Restore our state. */
- if (newPartsCount == 1)
- fullSignificand[0] = significand.part;
- significand = savedSignificand;
- semantics = savedSemantics;
-
- omsb = APInt::tcMSB(fullSignificand, newPartsCount) + 1;
- }
-
- // Convert the result having "2 * precision" significant-bits back to the one
- // having "precision" significant-bits. First, move the radix point from
- // poision "2*precision - 1" to "precision - 1". The exponent need to be
- // adjusted by "2*precision - 1" - "precision - 1" = "precision".
- exponent -= precision + 1;
-
- // In case MSB resides at the left-hand side of radix point, shift the
- // mantissa right by some amount to make sure the MSB reside right before
- // the radix point (i.e. "MSB . rest-significant-bits").
- //
- // Note that the result is not normalized when "omsb < precision". So, the
- // caller needs to call IEEEFloat::normalize() if normalized value is
- // expected.
- if (omsb > precision) {
- unsigned int bits, significantParts;
- lostFraction lf;
-
- bits = omsb - precision;
- significantParts = partCountForBits(omsb);
- lf = shiftRight(fullSignificand, significantParts, bits);
- lost_fraction = combineLostFractions(lf, lost_fraction);
- exponent += bits;
- }
-
- APInt::tcAssign(lhsSignificand, fullSignificand, partsCount);
-
- if (newPartsCount > 4)
- delete [] fullSignificand;
-
- return lost_fraction;
-}
-
-/* Multiply the significands of LHS and RHS to DST. */
-lostFraction IEEEFloat::divideSignificand(const IEEEFloat &rhs) {
- unsigned int bit, i, partsCount;
- const integerPart *rhsSignificand;
- integerPart *lhsSignificand, *dividend, *divisor;
- integerPart scratch[4];
- lostFraction lost_fraction;
-
- assert(semantics == rhs.semantics);
-
- lhsSignificand = significandParts();
- rhsSignificand = rhs.significandParts();
- partsCount = partCount();
-
- if (partsCount > 2)
- dividend = new integerPart[partsCount * 2];
- else
- dividend = scratch;
-
- divisor = dividend + partsCount;
-
- /* Copy the dividend and divisor as they will be modified in-place. */
- for (i = 0; i < partsCount; i++) {
- dividend[i] = lhsSignificand[i];
- divisor[i] = rhsSignificand[i];
- lhsSignificand[i] = 0;
- }
-
- exponent -= rhs.exponent;
-
- unsigned int precision = semantics->precision;
-
- /* Normalize the divisor. */
- bit = precision - APInt::tcMSB(divisor, partsCount) - 1;
- if (bit) {
- exponent += bit;
- APInt::tcShiftLeft(divisor, partsCount, bit);
- }
-
- /* Normalize the dividend. */
- bit = precision - APInt::tcMSB(dividend, partsCount) - 1;
- if (bit) {
- exponent -= bit;
- APInt::tcShiftLeft(dividend, partsCount, bit);
- }
-
- /* Ensure the dividend >= divisor initially for the loop below.
- Incidentally, this means that the division loop below is
- guaranteed to set the integer bit to one. */
- if (APInt::tcCompare(dividend, divisor, partsCount) < 0) {
- exponent--;
- APInt::tcShiftLeft(dividend, partsCount, 1);
- assert(APInt::tcCompare(dividend, divisor, partsCount) >= 0);
- }
-
- /* Long division. */
- for (bit = precision; bit; bit -= 1) {
- if (APInt::tcCompare(dividend, divisor, partsCount) >= 0) {
- APInt::tcSubtract(dividend, divisor, 0, partsCount);
- APInt::tcSetBit(lhsSignificand, bit - 1);
- }
-
- APInt::tcShiftLeft(dividend, partsCount, 1);
- }
-
- /* Figure out the lost fraction. */
- int cmp = APInt::tcCompare(dividend, divisor, partsCount);
-
- if (cmp > 0)
- lost_fraction = lfMoreThanHalf;
- else if (cmp == 0)
- lost_fraction = lfExactlyHalf;
- else if (APInt::tcIsZero(dividend, partsCount))
- lost_fraction = lfExactlyZero;
- else
- lost_fraction = lfLessThanHalf;
-
- if (partsCount > 2)
- delete [] dividend;
-
- return lost_fraction;
-}
-
-unsigned int IEEEFloat::significandMSB() const {
- return APInt::tcMSB(significandParts(), partCount());
-}
-
-unsigned int IEEEFloat::significandLSB() const {
- return APInt::tcLSB(significandParts(), partCount());
-}
-
-/* Note that a zero result is NOT normalized to fcZero. */
-lostFraction IEEEFloat::shiftSignificandRight(unsigned int bits) {
- /* Our exponent should not overflow. */
- assert((ExponentType) (exponent + bits) >= exponent);
-
- exponent += bits;
-
- return shiftRight(significandParts(), partCount(), bits);
-}
-
-/* Shift the significand left BITS bits, subtract BITS from its exponent. */
-void IEEEFloat::shiftSignificandLeft(unsigned int bits) {
- assert(bits < semantics->precision);
-
- if (bits) {
- unsigned int partsCount = partCount();
-
- APInt::tcShiftLeft(significandParts(), partsCount, bits);
- exponent -= bits;
-
- assert(!APInt::tcIsZero(significandParts(), partsCount));
- }
-}
-
-IEEEFloat::cmpResult
-IEEEFloat::compareAbsoluteValue(const IEEEFloat &rhs) const {
- int compare;
-
- assert(semantics == rhs.semantics);
- assert(isFiniteNonZero());
- assert(rhs.isFiniteNonZero());
-
- compare = exponent - rhs.exponent;
-
- /* If exponents are equal, do an unsigned bignum comparison of the
- significands. */
- if (compare == 0)
- compare = APInt::tcCompare(significandParts(), rhs.significandParts(),
- partCount());
-
- if (compare > 0)
- return cmpGreaterThan;
- else if (compare < 0)
- return cmpLessThan;
- else
- return cmpEqual;
-}
-
-/* Handle overflow. Sign is preserved. We either become infinity or
- the largest finite number. */
-IEEEFloat::opStatus IEEEFloat::handleOverflow(roundingMode rounding_mode) {
- /* Infinity? */
- if (rounding_mode == rmNearestTiesToEven ||
- rounding_mode == rmNearestTiesToAway ||
- (rounding_mode == rmTowardPositive && !sign) ||
- (rounding_mode == rmTowardNegative && sign)) {
- category = fcInfinity;
- return (opStatus) (opOverflow | opInexact);
- }
-
- /* Otherwise we become the largest finite number. */
- category = fcNormal;
- exponent = semantics->maxExponent;
- APInt::tcSetLeastSignificantBits(significandParts(), partCount(),
- semantics->precision);
-
- return opInexact;
-}
-
-/* Returns TRUE if, when truncating the current number, with BIT the
- new LSB, with the given lost fraction and rounding mode, the result
- would need to be rounded away from zero (i.e., by increasing the
- signficand). This routine must work for fcZero of both signs, and
- fcNormal numbers. */
-bool IEEEFloat::roundAwayFromZero(roundingMode rounding_mode,
- lostFraction lost_fraction,
- unsigned int bit) const {
- /* NaNs and infinities should not have lost fractions. */
- assert(isFiniteNonZero() || category == fcZero);
-
- /* Current callers never pass this so we don't handle it. */
- assert(lost_fraction != lfExactlyZero);
-
- switch (rounding_mode) {
- case rmNearestTiesToAway:
- return lost_fraction == lfExactlyHalf || lost_fraction == lfMoreThanHalf;
-
- case rmNearestTiesToEven:
- if (lost_fraction == lfMoreThanHalf)
- return true;
-
- /* Our zeroes don't have a significand to test. */
- if (lost_fraction == lfExactlyHalf && category != fcZero)
- return APInt::tcExtractBit(significandParts(), bit);
-
- return false;
-
- case rmTowardZero:
- return false;
-
- case rmTowardPositive:
- return !sign;
-
- case rmTowardNegative:
- return sign;
- }
- llvm_unreachable("Invalid rounding mode found");
-}
-
-IEEEFloat::opStatus IEEEFloat::normalize(roundingMode rounding_mode,
- lostFraction lost_fraction) {
- unsigned int omsb; /* One, not zero, based MSB. */
- int exponentChange;
-
- if (!isFiniteNonZero())
- return opOK;
-
- /* Before rounding normalize the exponent of fcNormal numbers. */
- omsb = significandMSB() + 1;
-
- if (omsb) {
- /* OMSB is numbered from 1. We want to place it in the integer
- bit numbered PRECISION if possible, with a compensating change in
- the exponent. */
- exponentChange = omsb - semantics->precision;
-
- /* If the resulting exponent is too high, overflow according to
- the rounding mode. */
- if (exponent + exponentChange > semantics->maxExponent)
- return handleOverflow(rounding_mode);
-
- /* Subnormal numbers have exponent minExponent, and their MSB
- is forced based on that. */
- if (exponent + exponentChange < semantics->minExponent)
- exponentChange = semantics->minExponent - exponent;
-
- /* Shifting left is easy as we don't lose precision. */
- if (exponentChange < 0) {
- assert(lost_fraction == lfExactlyZero);
-
- shiftSignificandLeft(-exponentChange);
-
- return opOK;
- }
-
- if (exponentChange > 0) {
- lostFraction lf;
-
- /* Shift right and capture any new lost fraction. */
- lf = shiftSignificandRight(exponentChange);
-
- lost_fraction = combineLostFractions(lf, lost_fraction);
-
- /* Keep OMSB up-to-date. */
- if (omsb > (unsigned) exponentChange)
- omsb -= exponentChange;
- else
- omsb = 0;
- }
- }
-
- /* Now round the number according to rounding_mode given the lost
- fraction. */
-
- /* As specified in IEEE 754, since we do not trap we do not report
- underflow for exact results. */
- if (lost_fraction == lfExactlyZero) {
- /* Canonicalize zeroes. */
- if (omsb == 0)
- category = fcZero;
-
- return opOK;
- }
-
- /* Increment the significand if we're rounding away from zero. */
- if (roundAwayFromZero(rounding_mode, lost_fraction, 0)) {
- if (omsb == 0)
- exponent = semantics->minExponent;
-
- incrementSignificand();
- omsb = significandMSB() + 1;
-
- /* Did the significand increment overflow? */
- if (omsb == (unsigned) semantics->precision + 1) {
- /* Renormalize by incrementing the exponent and shifting our
- significand right one. However if we already have the
- maximum exponent we overflow to infinity. */
- if (exponent == semantics->maxExponent) {
- category = fcInfinity;
-
- return (opStatus) (opOverflow | opInexact);
- }
-
- shiftSignificandRight(1);
-
- return opInexact;
- }
- }
-
- /* The normal case - we were and are not denormal, and any
- significand increment above didn't overflow. */
- if (omsb == semantics->precision)
- return opInexact;
-
- /* We have a non-zero denormal. */
- assert(omsb < semantics->precision);
-
- /* Canonicalize zeroes. */
- if (omsb == 0)
- category = fcZero;
-
- /* The fcZero case is a denormal that underflowed to zero. */
- return (opStatus) (opUnderflow | opInexact);
-}
-
-IEEEFloat::opStatus IEEEFloat::addOrSubtractSpecials(const IEEEFloat &rhs,
- bool subtract) {
- switch (PackCategoriesIntoKey(category, rhs.category)) {
- default:
- llvm_unreachable(nullptr);
-
- case PackCategoriesIntoKey(fcNaN, fcZero):
- case PackCategoriesIntoKey(fcNaN, fcNormal):
- case PackCategoriesIntoKey(fcNaN, fcInfinity):
- case PackCategoriesIntoKey(fcNaN, fcNaN):
- case PackCategoriesIntoKey(fcNormal, fcZero):
- case PackCategoriesIntoKey(fcInfinity, fcNormal):
- case PackCategoriesIntoKey(fcInfinity, fcZero):
- return opOK;
-
- case PackCategoriesIntoKey(fcZero, fcNaN):
- case PackCategoriesIntoKey(fcNormal, fcNaN):
- case PackCategoriesIntoKey(fcInfinity, fcNaN):
- // We need to be sure to flip the sign here for subtraction because we
- // don't have a separate negate operation so -NaN becomes 0 - NaN here.
- sign = rhs.sign ^ subtract;
- category = fcNaN;
- copySignificand(rhs);
- return opOK;
-
- case PackCategoriesIntoKey(fcNormal, fcInfinity):
- case PackCategoriesIntoKey(fcZero, fcInfinity):
- category = fcInfinity;
- sign = rhs.sign ^ subtract;
- return opOK;
-
- case PackCategoriesIntoKey(fcZero, fcNormal):
- assign(rhs);
- sign = rhs.sign ^ subtract;
- return opOK;
-
- case PackCategoriesIntoKey(fcZero, fcZero):
- /* Sign depends on rounding mode; handled by caller. */
- return opOK;
-
- case PackCategoriesIntoKey(fcInfinity, fcInfinity):
- /* Differently signed infinities can only be validly
- subtracted. */
- if (((sign ^ rhs.sign)!=0) != subtract) {
- makeNaN();
- return opInvalidOp;
- }
-
- return opOK;
-
- case PackCategoriesIntoKey(fcNormal, fcNormal):
- return opDivByZero;
- }
-}
-
-/* Add or subtract two normal numbers. */
-lostFraction IEEEFloat::addOrSubtractSignificand(const IEEEFloat &rhs,
- bool subtract) {
- integerPart carry;
- lostFraction lost_fraction;
- int bits;
-
- /* Determine if the operation on the absolute values is effectively
- an addition or subtraction. */
- subtract ^= static_cast<bool>(sign ^ rhs.sign);
-
- /* Are we bigger exponent-wise than the RHS? */
- bits = exponent - rhs.exponent;
-
- /* Subtraction is more subtle than one might naively expect. */
- if (subtract) {
- IEEEFloat temp_rhs(rhs);
- bool reverse;
-
- if (bits == 0) {
- reverse = compareAbsoluteValue(temp_rhs) == cmpLessThan;
- lost_fraction = lfExactlyZero;
- } else if (bits > 0) {
- lost_fraction = temp_rhs.shiftSignificandRight(bits - 1);
- shiftSignificandLeft(1);
- reverse = false;
- } else {
- lost_fraction = shiftSignificandRight(-bits - 1);
- temp_rhs.shiftSignificandLeft(1);
- reverse = true;
- }
-
- if (reverse) {
- carry = temp_rhs.subtractSignificand
- (*this, lost_fraction != lfExactlyZero);
- copySignificand(temp_rhs);
- sign = !sign;
- } else {
- carry = subtractSignificand
- (temp_rhs, lost_fraction != lfExactlyZero);
- }
-
- /* Invert the lost fraction - it was on the RHS and
- subtracted. */
- if (lost_fraction == lfLessThanHalf)
- lost_fraction = lfMoreThanHalf;
- else if (lost_fraction == lfMoreThanHalf)
- lost_fraction = lfLessThanHalf;
-
- /* The code above is intended to ensure that no borrow is
- necessary. */
- assert(!carry);
- (void)carry;
- } else {
- if (bits > 0) {
- IEEEFloat temp_rhs(rhs);
-
- lost_fraction = temp_rhs.shiftSignificandRight(bits);
- carry = addSignificand(temp_rhs);
- } else {
- lost_fraction = shiftSignificandRight(-bits);
- carry = addSignificand(rhs);
- }
-
- /* We have a guard bit; generating a carry cannot happen. */
- assert(!carry);
- (void)carry;
- }
-
- return lost_fraction;
-}
-
-IEEEFloat::opStatus IEEEFloat::multiplySpecials(const IEEEFloat &rhs) {
- switch (PackCategoriesIntoKey(category, rhs.category)) {
- default:
- llvm_unreachable(nullptr);
-
- case PackCategoriesIntoKey(fcNaN, fcZero):
- case PackCategoriesIntoKey(fcNaN, fcNormal):
- case PackCategoriesIntoKey(fcNaN, fcInfinity):
- case PackCategoriesIntoKey(fcNaN, fcNaN):
- sign = false;
- return opOK;
-
- case PackCategoriesIntoKey(fcZero, fcNaN):
- case PackCategoriesIntoKey(fcNormal, fcNaN):
- case PackCategoriesIntoKey(fcInfinity, fcNaN):
- sign = false;
- category = fcNaN;
- copySignificand(rhs);
- return opOK;
-
- case PackCategoriesIntoKey(fcNormal, fcInfinity):
- case PackCategoriesIntoKey(fcInfinity, fcNormal):
- case PackCategoriesIntoKey(fcInfinity, fcInfinity):
- category = fcInfinity;
- return opOK;
-
- case PackCategoriesIntoKey(fcZero, fcNormal):
- case PackCategoriesIntoKey(fcNormal, fcZero):
- case PackCategoriesIntoKey(fcZero, fcZero):
- category = fcZero;
- return opOK;
-
- case PackCategoriesIntoKey(fcZero, fcInfinity):
- case PackCategoriesIntoKey(fcInfinity, fcZero):
- makeNaN();
- return opInvalidOp;
-
- case PackCategoriesIntoKey(fcNormal, fcNormal):
- return opOK;
- }
-}
-
-IEEEFloat::opStatus IEEEFloat::divideSpecials(const IEEEFloat &rhs) {
- switch (PackCategoriesIntoKey(category, rhs.category)) {
- default:
- llvm_unreachable(nullptr);
-
- case PackCategoriesIntoKey(fcZero, fcNaN):
- case PackCategoriesIntoKey(fcNormal, fcNaN):
- case PackCategoriesIntoKey(fcInfinity, fcNaN):
- category = fcNaN;
- copySignificand(rhs);
- LLVM_FALLTHROUGH;
- case PackCategoriesIntoKey(fcNaN, fcZero):
- case PackCategoriesIntoKey(fcNaN, fcNormal):
- case PackCategoriesIntoKey(fcNaN, fcInfinity):
- case PackCategoriesIntoKey(fcNaN, fcNaN):
- sign = false;
- LLVM_FALLTHROUGH;
- case PackCategoriesIntoKey(fcInfinity, fcZero):
- case PackCategoriesIntoKey(fcInfinity, fcNormal):
- case PackCategoriesIntoKey(fcZero, fcInfinity):
- case PackCategoriesIntoKey(fcZero, fcNormal):
- return opOK;
-
- case PackCategoriesIntoKey(fcNormal, fcInfinity):
- category = fcZero;
- return opOK;
-
- case PackCategoriesIntoKey(fcNormal, fcZero):
- category = fcInfinity;
- return opDivByZero;
-
- case PackCategoriesIntoKey(fcInfinity, fcInfinity):
- case PackCategoriesIntoKey(fcZero, fcZero):
- makeNaN();
- return opInvalidOp;
-
- case PackCategoriesIntoKey(fcNormal, fcNormal):
- return opOK;
- }
-}
-
-IEEEFloat::opStatus IEEEFloat::modSpecials(const IEEEFloat &rhs) {
- switch (PackCategoriesIntoKey(category, rhs.category)) {
- default:
- llvm_unreachable(nullptr);
-
- case PackCategoriesIntoKey(fcNaN, fcZero):
- case PackCategoriesIntoKey(fcNaN, fcNormal):
- case PackCategoriesIntoKey(fcNaN, fcInfinity):
- case PackCategoriesIntoKey(fcNaN, fcNaN):
- case PackCategoriesIntoKey(fcZero, fcInfinity):
- case PackCategoriesIntoKey(fcZero, fcNormal):
- case PackCategoriesIntoKey(fcNormal, fcInfinity):
- return opOK;
-
- case PackCategoriesIntoKey(fcZero, fcNaN):
- case PackCategoriesIntoKey(fcNormal, fcNaN):
- case PackCategoriesIntoKey(fcInfinity, fcNaN):
- sign = false;
- category = fcNaN;
- copySignificand(rhs);
- return opOK;
-
- case PackCategoriesIntoKey(fcNormal, fcZero):
- case PackCategoriesIntoKey(fcInfinity, fcZero):
- case PackCategoriesIntoKey(fcInfinity, fcNormal):
- case PackCategoriesIntoKey(fcInfinity, fcInfinity):
- case PackCategoriesIntoKey(fcZero, fcZero):
- makeNaN();
- return opInvalidOp;
-
- case PackCategoriesIntoKey(fcNormal, fcNormal):
- return opOK;
- }
-}
-
-/* Change sign. */
-void IEEEFloat::changeSign() {
- /* Look mummy, this one's easy. */
- sign = !sign;
-}
-
-/* Normalized addition or subtraction. */
-IEEEFloat::opStatus IEEEFloat::addOrSubtract(const IEEEFloat &rhs,
- roundingMode rounding_mode,
- bool subtract) {
- opStatus fs;
-
- fs = addOrSubtractSpecials(rhs, subtract);
-
- /* This return code means it was not a simple case. */
- if (fs == opDivByZero) {
- lostFraction lost_fraction;
-
- lost_fraction = addOrSubtractSignificand(rhs, subtract);
- fs = normalize(rounding_mode, lost_fraction);
-
- /* Can only be zero if we lost no fraction. */
- assert(category != fcZero || lost_fraction == lfExactlyZero);
- }
-
- /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a
- positive zero unless rounding to minus infinity, except that
- adding two like-signed zeroes gives that zero. */
- if (category == fcZero) {
- if (rhs.category != fcZero || (sign == rhs.sign) == subtract)
- sign = (rounding_mode == rmTowardNegative);
- }
-
- return fs;
-}
-
-/* Normalized addition. */
-IEEEFloat::opStatus IEEEFloat::add(const IEEEFloat &rhs,
- roundingMode rounding_mode) {
- return addOrSubtract(rhs, rounding_mode, false);
-}
-
-/* Normalized subtraction. */
-IEEEFloat::opStatus IEEEFloat::subtract(const IEEEFloat &rhs,
- roundingMode rounding_mode) {
- return addOrSubtract(rhs, rounding_mode, true);
-}
-
-/* Normalized multiply. */
-IEEEFloat::opStatus IEEEFloat::multiply(const IEEEFloat &rhs,
- roundingMode rounding_mode) {
- opStatus fs;
-
- sign ^= rhs.sign;
- fs = multiplySpecials(rhs);
-
- if (isFiniteNonZero()) {
- lostFraction lost_fraction = multiplySignificand(rhs, nullptr);
- fs = normalize(rounding_mode, lost_fraction);
- if (lost_fraction != lfExactlyZero)
- fs = (opStatus) (fs | opInexact);
- }
-
- return fs;
-}
-
-/* Normalized divide. */
-IEEEFloat::opStatus IEEEFloat::divide(const IEEEFloat &rhs,
- roundingMode rounding_mode) {
- opStatus fs;
-
- sign ^= rhs.sign;
- fs = divideSpecials(rhs);
-
- if (isFiniteNonZero()) {
- lostFraction lost_fraction = divideSignificand(rhs);
- fs = normalize(rounding_mode, lost_fraction);
- if (lost_fraction != lfExactlyZero)
- fs = (opStatus) (fs | opInexact);
- }
-
- return fs;
-}
-
-/* Normalized remainder. This is not currently correct in all cases. */
-IEEEFloat::opStatus IEEEFloat::remainder(const IEEEFloat &rhs) {
- opStatus fs;
- IEEEFloat V = *this;
- unsigned int origSign = sign;
-
- fs = V.divide(rhs, rmNearestTiesToEven);
- if (fs == opDivByZero)
- return fs;
-
- int parts = partCount();
- integerPart *x = new integerPart[parts];
- bool ignored;
- fs = V.convertToInteger(makeMutableArrayRef(x, parts),
- parts * integerPartWidth, true, rmNearestTiesToEven,
- &ignored);
- if (fs == opInvalidOp) {
- delete[] x;
- return fs;
- }
-
- fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true,
- rmNearestTiesToEven);
- assert(fs==opOK); // should always work
-
- fs = V.multiply(rhs, rmNearestTiesToEven);
- assert(fs==opOK || fs==opInexact); // should not overflow or underflow
-
- fs = subtract(V, rmNearestTiesToEven);
- assert(fs==opOK || fs==opInexact); // likewise
-
- if (isZero())
- sign = origSign; // IEEE754 requires this
- delete[] x;
- return fs;
-}
-
-/* Normalized llvm frem (C fmod). */
-IEEEFloat::opStatus IEEEFloat::mod(const IEEEFloat &rhs) {
- opStatus fs;
- fs = modSpecials(rhs);
- unsigned int origSign = sign;
-
- while (isFiniteNonZero() && rhs.isFiniteNonZero() &&
- compareAbsoluteValue(rhs) != cmpLessThan) {
- IEEEFloat V = scalbn(rhs, ilogb(*this) - ilogb(rhs), rmNearestTiesToEven);
- if (compareAbsoluteValue(V) == cmpLessThan)
- V = scalbn(V, -1, rmNearestTiesToEven);
- V.sign = sign;
-
- fs = subtract(V, rmNearestTiesToEven);
- assert(fs==opOK);
- }
- if (isZero())
- sign = origSign; // fmod requires this
- return fs;
-}
-
-/* Normalized fused-multiply-add. */
-IEEEFloat::opStatus IEEEFloat::fusedMultiplyAdd(const IEEEFloat &multiplicand,
- const IEEEFloat &addend,
- roundingMode rounding_mode) {
- opStatus fs;
-
- /* Post-multiplication sign, before addition. */
- sign ^= multiplicand.sign;
-
- /* If and only if all arguments are normal do we need to do an
- extended-precision calculation. */
- if (isFiniteNonZero() &&
- multiplicand.isFiniteNonZero() &&
- addend.isFinite()) {
- lostFraction lost_fraction;
-
- lost_fraction = multiplySignificand(multiplicand, &addend);
- fs = normalize(rounding_mode, lost_fraction);
- if (lost_fraction != lfExactlyZero)
- fs = (opStatus) (fs | opInexact);
-
- /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a
- positive zero unless rounding to minus infinity, except that
- adding two like-signed zeroes gives that zero. */
- if (category == fcZero && !(fs & opUnderflow) && sign != addend.sign)
- sign = (rounding_mode == rmTowardNegative);
- } else {
- fs = multiplySpecials(multiplicand);
-
- /* FS can only be opOK or opInvalidOp. There is no more work
- to do in the latter case. The IEEE-754R standard says it is
- implementation-defined in this case whether, if ADDEND is a
- quiet NaN, we raise invalid op; this implementation does so.
-
- If we need to do the addition we can do so with normal
- precision. */
- if (fs == opOK)
- fs = addOrSubtract(addend, rounding_mode, false);
- }
-
- return fs;
-}
-
-/* Rounding-mode corrrect round to integral value. */
-IEEEFloat::opStatus IEEEFloat::roundToIntegral(roundingMode rounding_mode) {
- opStatus fs;
-
- // If the exponent is large enough, we know that this value is already
- // integral, and the arithmetic below would potentially cause it to saturate
- // to +/-Inf. Bail out early instead.
- if (isFiniteNonZero() && exponent+1 >= (int)semanticsPrecision(*semantics))
- return opOK;
-
- // The algorithm here is quite simple: we add 2^(p-1), where p is the
- // precision of our format, and then subtract it back off again. The choice
- // of rounding modes for the addition/subtraction determines the rounding mode
- // for our integral rounding as well.
- // NOTE: When the input value is negative, we do subtraction followed by
- // addition instead.
- APInt IntegerConstant(NextPowerOf2(semanticsPrecision(*semantics)), 1);
- IntegerConstant <<= semanticsPrecision(*semantics)-1;
- IEEEFloat MagicConstant(*semantics);
- fs = MagicConstant.convertFromAPInt(IntegerConstant, false,
- rmNearestTiesToEven);
- MagicConstant.sign = sign;
-
- if (fs != opOK)
- return fs;
-
- // Preserve the input sign so that we can handle 0.0/-0.0 cases correctly.
- bool inputSign = isNegative();
-
- fs = add(MagicConstant, rounding_mode);
- if (fs != opOK && fs != opInexact)
- return fs;
-
- fs = subtract(MagicConstant, rounding_mode);
-
- // Restore the input sign.
- if (inputSign != isNegative())
- changeSign();
-
- return fs;
-}
-
-
-/* Comparison requires normalized numbers. */
-IEEEFloat::cmpResult IEEEFloat::compare(const IEEEFloat &rhs) const {
- cmpResult result;
-
- assert(semantics == rhs.semantics);
-
- switch (PackCategoriesIntoKey(category, rhs.category)) {
- default:
- llvm_unreachable(nullptr);
-
- case PackCategoriesIntoKey(fcNaN, fcZero):
- case PackCategoriesIntoKey(fcNaN, fcNormal):
- case PackCategoriesIntoKey(fcNaN, fcInfinity):
- case PackCategoriesIntoKey(fcNaN, fcNaN):
- case PackCategoriesIntoKey(fcZero, fcNaN):
- case PackCategoriesIntoKey(fcNormal, fcNaN):
- case PackCategoriesIntoKey(fcInfinity, fcNaN):
- return cmpUnordered;
-
- case PackCategoriesIntoKey(fcInfinity, fcNormal):
- case PackCategoriesIntoKey(fcInfinity, fcZero):
- case PackCategoriesIntoKey(fcNormal, fcZero):
- if (sign)
- return cmpLessThan;
- else
- return cmpGreaterThan;
-
- case PackCategoriesIntoKey(fcNormal, fcInfinity):
- case PackCategoriesIntoKey(fcZero, fcInfinity):
- case PackCategoriesIntoKey(fcZero, fcNormal):
- if (rhs.sign)
- return cmpGreaterThan;
- else
- return cmpLessThan;
-
- case PackCategoriesIntoKey(fcInfinity, fcInfinity):
- if (sign == rhs.sign)
- return cmpEqual;
- else if (sign)
- return cmpLessThan;
- else
- return cmpGreaterThan;
-
- case PackCategoriesIntoKey(fcZero, fcZero):
- return cmpEqual;
-
- case PackCategoriesIntoKey(fcNormal, fcNormal):
- break;
- }
-
- /* Two normal numbers. Do they have the same sign? */
- if (sign != rhs.sign) {
- if (sign)
- result = cmpLessThan;
- else
- result = cmpGreaterThan;
- } else {
- /* Compare absolute values; invert result if negative. */
- result = compareAbsoluteValue(rhs);
-
- if (sign) {
- if (result == cmpLessThan)
- result = cmpGreaterThan;
- else if (result == cmpGreaterThan)
- result = cmpLessThan;
- }
- }
-
- return result;
-}
-
-/// IEEEFloat::convert - convert a value of one floating point type to another.
-/// The return value corresponds to the IEEE754 exceptions. *losesInfo
-/// records whether the transformation lost information, i.e. whether
-/// converting the result back to the original type will produce the
-/// original value (this is almost the same as return value==fsOK, but there
-/// are edge cases where this is not so).
-
-IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics,
- roundingMode rounding_mode,
- bool *losesInfo) {
- lostFraction lostFraction;
- unsigned int newPartCount, oldPartCount;
- opStatus fs;
- int shift;
- const fltSemantics &fromSemantics = *semantics;
-
- lostFraction = lfExactlyZero;
- newPartCount = partCountForBits(toSemantics.precision + 1);
- oldPartCount = partCount();
- shift = toSemantics.precision - fromSemantics.precision;
-
- bool X86SpecialNan = false;
- if (&fromSemantics == &semX87DoubleExtended &&
- &toSemantics != &semX87DoubleExtended && category == fcNaN &&
- (!(*significandParts() & 0x8000000000000000ULL) ||
- !(*significandParts() & 0x4000000000000000ULL))) {
- // x86 has some unusual NaNs which cannot be represented in any other
- // format; note them here.
- X86SpecialNan = true;
- }
-
- // If this is a truncation of a denormal number, and the target semantics
- // has larger exponent range than the source semantics (this can happen
- // when truncating from PowerPC double-double to double format), the
- // right shift could lose result mantissa bits. Adjust exponent instead
- // of performing excessive shift.
- if (shift < 0 && isFiniteNonZero()) {
- int exponentChange = significandMSB() + 1 - fromSemantics.precision;
- if (exponent + exponentChange < toSemantics.minExponent)
- exponentChange = toSemantics.minExponent - exponent;
- if (exponentChange < shift)
- exponentChange = shift;
- if (exponentChange < 0) {
- shift -= exponentChange;
- exponent += exponentChange;
- }
- }
-
- // If this is a truncation, perform the shift before we narrow the storage.
- if (shift < 0 && (isFiniteNonZero() || category==fcNaN))
- lostFraction = shiftRight(significandParts(), oldPartCount, -shift);
-
- // Fix the storage so it can hold to new value.
- if (newPartCount > oldPartCount) {
- // The new type requires more storage; make it available.
- integerPart *newParts;
- newParts = new integerPart[newPartCount];
- APInt::tcSet(newParts, 0, newPartCount);
- if (isFiniteNonZero() || category==fcNaN)
- APInt::tcAssign(newParts, significandParts(), oldPartCount);
- freeSignificand();
- significand.parts = newParts;
- } else if (newPartCount == 1 && oldPartCount != 1) {
- // Switch to built-in storage for a single part.
- integerPart newPart = 0;
- if (isFiniteNonZero() || category==fcNaN)
- newPart = significandParts()[0];
- freeSignificand();
- significand.part = newPart;
- }
-
- // Now that we have the right storage, switch the semantics.
- semantics = &toSemantics;
-
- // If this is an extension, perform the shift now that the storage is
- // available.
- if (shift > 0 && (isFiniteNonZero() || category==fcNaN))
- APInt::tcShiftLeft(significandParts(), newPartCount, shift);
-
- if (isFiniteNonZero()) {
- fs = normalize(rounding_mode, lostFraction);
- *losesInfo = (fs != opOK);
- } else if (category == fcNaN) {
- *losesInfo = lostFraction != lfExactlyZero || X86SpecialNan;
-
- // For x87 extended precision, we want to make a NaN, not a special NaN if
- // the input wasn't special either.
- if (!X86SpecialNan && semantics == &semX87DoubleExtended)
- APInt::tcSetBit(significandParts(), semantics->precision - 1);
-
- // gcc forces the Quiet bit on, which means (float)(double)(float_sNan)
- // does not give you back the same bits. This is dubious, and we
- // don't currently do it. You're really supposed to get
- // an invalid operation signal at runtime, but nobody does that.
- fs = opOK;
- } else {
- *losesInfo = false;
- fs = opOK;
- }
-
- return fs;
-}
-
-/* Convert a floating point number to an integer according to the
- rounding mode. If the rounded integer value is out of range this
- returns an invalid operation exception and the contents of the
- destination parts are unspecified. If the rounded value is in
- range but the floating point number is not the exact integer, the C
- standard doesn't require an inexact exception to be raised. IEEE
- 854 does require it so we do that.
-
- Note that for conversions to integer type the C standard requires
- round-to-zero to always be used. */
-IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger(
- MutableArrayRef<integerPart> parts, unsigned int width, bool isSigned,
- roundingMode rounding_mode, bool *isExact) const {
- lostFraction lost_fraction;
- const integerPart *src;
- unsigned int dstPartsCount, truncatedBits;
-
- *isExact = false;
-
- /* Handle the three special cases first. */
- if (category == fcInfinity || category == fcNaN)
- return opInvalidOp;
-
- dstPartsCount = partCountForBits(width);
- assert(dstPartsCount <= parts.size() && "Integer too big");
-
- if (category == fcZero) {
- APInt::tcSet(parts.data(), 0, dstPartsCount);
- // Negative zero can't be represented as an int.
- *isExact = !sign;
- return opOK;
- }
-
- src = significandParts();
-
- /* Step 1: place our absolute value, with any fraction truncated, in
- the destination. */
- if (exponent < 0) {
- /* Our absolute value is less than one; truncate everything. */
- APInt::tcSet(parts.data(), 0, dstPartsCount);
- /* For exponent -1 the integer bit represents .5, look at that.
- For smaller exponents leftmost truncated bit is 0. */
- truncatedBits = semantics->precision -1U - exponent;
- } else {
- /* We want the most significant (exponent + 1) bits; the rest are
- truncated. */
- unsigned int bits = exponent + 1U;
-
- /* Hopelessly large in magnitude? */
- if (bits > width)
- return opInvalidOp;
-
- if (bits < semantics->precision) {
- /* We truncate (semantics->precision - bits) bits. */
- truncatedBits = semantics->precision - bits;
- APInt::tcExtract(parts.data(), dstPartsCount, src, bits, truncatedBits);
- } else {
- /* We want at least as many bits as are available. */
- APInt::tcExtract(parts.data(), dstPartsCount, src, semantics->precision,
- 0);
- APInt::tcShiftLeft(parts.data(), dstPartsCount,
- bits - semantics->precision);
- truncatedBits = 0;
- }
- }
-
- /* Step 2: work out any lost fraction, and increment the absolute
- value if we would round away from zero. */
- if (truncatedBits) {
- lost_fraction = lostFractionThroughTruncation(src, partCount(),
- truncatedBits);
- if (lost_fraction != lfExactlyZero &&
- roundAwayFromZero(rounding_mode, lost_fraction, truncatedBits)) {
- if (APInt::tcIncrement(parts.data(), dstPartsCount))
- return opInvalidOp; /* Overflow. */
- }
- } else {
- lost_fraction = lfExactlyZero;
- }
-
- /* Step 3: check if we fit in the destination. */
- unsigned int omsb = APInt::tcMSB(parts.data(), dstPartsCount) + 1;
-
- if (sign) {
- if (!isSigned) {
- /* Negative numbers cannot be represented as unsigned. */
- if (omsb != 0)
- return opInvalidOp;
- } else {
- /* It takes omsb bits to represent the unsigned integer value.
- We lose a bit for the sign, but care is needed as the
- maximally negative integer is a special case. */
- if (omsb == width &&
- APInt::tcLSB(parts.data(), dstPartsCount) + 1 != omsb)
- return opInvalidOp;
-
- /* This case can happen because of rounding. */
- if (omsb > width)
- return opInvalidOp;
- }
-
- APInt::tcNegate (parts.data(), dstPartsCount);
- } else {
- if (omsb >= width + !isSigned)
- return opInvalidOp;
- }
-
- if (lost_fraction == lfExactlyZero) {
- *isExact = true;
- return opOK;
- } else
- return opInexact;
-}
-
-/* Same as convertToSignExtendedInteger, except we provide
- deterministic values in case of an invalid operation exception,
- namely zero for NaNs and the minimal or maximal value respectively
- for underflow or overflow.
- The *isExact output tells whether the result is exact, in the sense
- that converting it back to the original floating point type produces
- the original value. This is almost equivalent to result==opOK,
- except for negative zeroes.
-*/
-IEEEFloat::opStatus
-IEEEFloat::convertToInteger(MutableArrayRef<integerPart> parts,
- unsigned int width, bool isSigned,
- roundingMode rounding_mode, bool *isExact) const {
- opStatus fs;
-
- fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode,
- isExact);
-
- if (fs == opInvalidOp) {
- unsigned int bits, dstPartsCount;
-
- dstPartsCount = partCountForBits(width);
- assert(dstPartsCount <= parts.size() && "Integer too big");
-
- if (category == fcNaN)
- bits = 0;
- else if (sign)
- bits = isSigned;
- else
- bits = width - isSigned;
-
- APInt::tcSetLeastSignificantBits(parts.data(), dstPartsCount, bits);
- if (sign && isSigned)
- APInt::tcShiftLeft(parts.data(), dstPartsCount, width - 1);
- }
-
- return fs;
-}
-
-/* Convert an unsigned integer SRC to a floating point number,
- rounding according to ROUNDING_MODE. The sign of the floating
- point number is not modified. */
-IEEEFloat::opStatus IEEEFloat::convertFromUnsignedParts(
- const integerPart *src, unsigned int srcCount, roundingMode rounding_mode) {
- unsigned int omsb, precision, dstCount;
- integerPart *dst;
- lostFraction lost_fraction;
-
- category = fcNormal;
- omsb = APInt::tcMSB(src, srcCount) + 1;
- dst = significandParts();
- dstCount = partCount();
- precision = semantics->precision;
-
- /* We want the most significant PRECISION bits of SRC. There may not
- be that many; extract what we can. */
- if (precision <= omsb) {
- exponent = omsb - 1;
- lost_fraction = lostFractionThroughTruncation(src, srcCount,
- omsb - precision);
- APInt::tcExtract(dst, dstCount, src, precision, omsb - precision);
- } else {
- exponent = precision - 1;
- lost_fraction = lfExactlyZero;
- APInt::tcExtract(dst, dstCount, src, omsb, 0);
- }
-
- return normalize(rounding_mode, lost_fraction);
-}
-
-IEEEFloat::opStatus IEEEFloat::convertFromAPInt(const APInt &Val, bool isSigned,
- roundingMode rounding_mode) {
- unsigned int partCount = Val.getNumWords();
- APInt api = Val;
-
- sign = false;
- if (isSigned && api.isNegative()) {
- sign = true;
- api = -api;
- }
-
- return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode);
-}
-
-/* Convert a two's complement integer SRC to a floating point number,
- rounding according to ROUNDING_MODE. ISSIGNED is true if the
- integer is signed, in which case it must be sign-extended. */
-IEEEFloat::opStatus
-IEEEFloat::convertFromSignExtendedInteger(const integerPart *src,
- unsigned int srcCount, bool isSigned,
- roundingMode rounding_mode) {
- opStatus status;
-
- if (isSigned &&
- APInt::tcExtractBit(src, srcCount * integerPartWidth - 1)) {
- integerPart *copy;
-
- /* If we're signed and negative negate a copy. */
- sign = true;
- copy = new integerPart[srcCount];
- APInt::tcAssign(copy, src, srcCount);
- APInt::tcNegate(copy, srcCount);
- status = convertFromUnsignedParts(copy, srcCount, rounding_mode);
- delete [] copy;
- } else {
- sign = false;
- status = convertFromUnsignedParts(src, srcCount, rounding_mode);
- }
-
- return status;
-}
-
-/* FIXME: should this just take a const APInt reference? */
-IEEEFloat::opStatus
-IEEEFloat::convertFromZeroExtendedInteger(const integerPart *parts,
- unsigned int width, bool isSigned,
- roundingMode rounding_mode) {
- unsigned int partCount = partCountForBits(width);
- APInt api = APInt(width, makeArrayRef(parts, partCount));
-
- sign = false;
- if (isSigned && APInt::tcExtractBit(parts, width - 1)) {
- sign = true;
- api = -api;
- }
-
- return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode);
-}
-
-IEEEFloat::opStatus
-IEEEFloat::convertFromHexadecimalString(StringRef s,
- roundingMode rounding_mode) {
- lostFraction lost_fraction = lfExactlyZero;
-
- category = fcNormal;
- zeroSignificand();
- exponent = 0;
-
- integerPart *significand = significandParts();
- unsigned partsCount = partCount();
- unsigned bitPos = partsCount * integerPartWidth;
- bool computedTrailingFraction = false;
-
- // Skip leading zeroes and any (hexa)decimal point.
- StringRef::iterator begin = s.begin();
- StringRef::iterator end = s.end();
- StringRef::iterator dot;
- StringRef::iterator p = skipLeadingZeroesAndAnyDot(begin, end, &dot);
- StringRef::iterator firstSignificantDigit = p;
-
- while (p != end) {
- integerPart hex_value;
-
- if (*p == '.') {
- assert(dot == end && "String contains multiple dots");
- dot = p++;
- continue;
- }
-
- hex_value = hexDigitValue(*p);
- if (hex_value == -1U)
- break;
-
- p++;
-
- // Store the number while we have space.
- if (bitPos) {
- bitPos -= 4;
- hex_value <<= bitPos % integerPartWidth;
- significand[bitPos / integerPartWidth] |= hex_value;
- } else if (!computedTrailingFraction) {
- lost_fraction = trailingHexadecimalFraction(p, end, hex_value);
- computedTrailingFraction = true;
- }
- }
-
- /* Hex floats require an exponent but not a hexadecimal point. */
- assert(p != end && "Hex strings require an exponent");
- assert((*p == 'p' || *p == 'P') && "Invalid character in significand");
- assert(p != begin && "Significand has no digits");
- assert((dot == end || p - begin != 1) && "Significand has no digits");
-
- /* Ignore the exponent if we are zero. */
- if (p != firstSignificantDigit) {
- int expAdjustment;
-
- /* Implicit hexadecimal point? */
- if (dot == end)
- dot = p;
-
- /* Calculate the exponent adjustment implicit in the number of
- significant digits. */
- expAdjustment = static_cast<int>(dot - firstSignificantDigit);
- if (expAdjustment < 0)
- expAdjustment++;
- expAdjustment = expAdjustment * 4 - 1;
-
- /* Adjust for writing the significand starting at the most
- significant nibble. */
- expAdjustment += semantics->precision;
- expAdjustment -= partsCount * integerPartWidth;
-
- /* Adjust for the given exponent. */
- exponent = totalExponent(p + 1, end, expAdjustment);
- }
-
- return normalize(rounding_mode, lost_fraction);
-}
-
-IEEEFloat::opStatus
-IEEEFloat::roundSignificandWithExponent(const integerPart *decSigParts,
- unsigned sigPartCount, int exp,
- roundingMode rounding_mode) {
- unsigned int parts, pow5PartCount;
- fltSemantics calcSemantics = { 32767, -32767, 0, 0 };
- integerPart pow5Parts[maxPowerOfFiveParts];
- bool isNearest;
-
- isNearest = (rounding_mode == rmNearestTiesToEven ||
- rounding_mode == rmNearestTiesToAway);
-
- parts = partCountForBits(semantics->precision + 11);
-
- /* Calculate pow(5, abs(exp)). */
- pow5PartCount = powerOf5(pow5Parts, exp >= 0 ? exp: -exp);
-
- for (;; parts *= 2) {
- opStatus sigStatus, powStatus;
- unsigned int excessPrecision, truncatedBits;
-
- calcSemantics.precision = parts * integerPartWidth - 1;
- excessPrecision = calcSemantics.precision - semantics->precision;
- truncatedBits = excessPrecision;
-
- IEEEFloat decSig(calcSemantics, uninitialized);
- decSig.makeZero(sign);
- IEEEFloat pow5(calcSemantics);
-
- sigStatus = decSig.convertFromUnsignedParts(decSigParts, sigPartCount,
- rmNearestTiesToEven);
- powStatus = pow5.convertFromUnsignedParts(pow5Parts, pow5PartCount,
- rmNearestTiesToEven);
- /* Add exp, as 10^n = 5^n * 2^n. */
- decSig.exponent += exp;
-
- lostFraction calcLostFraction;
- integerPart HUerr, HUdistance;
- unsigned int powHUerr;
-
- if (exp >= 0) {
- /* multiplySignificand leaves the precision-th bit set to 1. */
- calcLostFraction = decSig.multiplySignificand(pow5, nullptr);
- powHUerr = powStatus != opOK;
- } else {
- calcLostFraction = decSig.divideSignificand(pow5);
- /* Denormal numbers have less precision. */
- if (decSig.exponent < semantics->minExponent) {
- excessPrecision += (semantics->minExponent - decSig.exponent);
- truncatedBits = excessPrecision;
- if (excessPrecision > calcSemantics.precision)
- excessPrecision = calcSemantics.precision;
- }
- /* Extra half-ulp lost in reciprocal of exponent. */
- powHUerr = (powStatus == opOK && calcLostFraction == lfExactlyZero) ? 0:2;
- }
-
- /* Both multiplySignificand and divideSignificand return the
- result with the integer bit set. */
- assert(APInt::tcExtractBit
- (decSig.significandParts(), calcSemantics.precision - 1) == 1);
-
- HUerr = HUerrBound(calcLostFraction != lfExactlyZero, sigStatus != opOK,
- powHUerr);
- HUdistance = 2 * ulpsFromBoundary(decSig.significandParts(),
- excessPrecision, isNearest);
-
- /* Are we guaranteed to round correctly if we truncate? */
- if (HUdistance >= HUerr) {
- APInt::tcExtract(significandParts(), partCount(), decSig.significandParts(),
- calcSemantics.precision - excessPrecision,
- excessPrecision);
- /* Take the exponent of decSig. If we tcExtract-ed less bits
- above we must adjust our exponent to compensate for the
- implicit right shift. */
- exponent = (decSig.exponent + semantics->precision
- - (calcSemantics.precision - excessPrecision));
- calcLostFraction = lostFractionThroughTruncation(decSig.significandParts(),
- decSig.partCount(),
- truncatedBits);
- return normalize(rounding_mode, calcLostFraction);
- }
- }
-}
-
-IEEEFloat::opStatus
-IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) {
- decimalInfo D;
- opStatus fs;
-
- /* Scan the text. */
- StringRef::iterator p = str.begin();
- interpretDecimal(p, str.end(), &D);
-
- /* Handle the quick cases. First the case of no significant digits,
- i.e. zero, and then exponents that are obviously too large or too
- small. Writing L for log 10 / log 2, a number d.ddddd*10^exp
- definitely overflows if
-
- (exp - 1) * L >= maxExponent
-
- and definitely underflows to zero where
-
- (exp + 1) * L <= minExponent - precision
-
- With integer arithmetic the tightest bounds for L are
-
- 93/28 < L < 196/59 [ numerator <= 256 ]
- 42039/12655 < L < 28738/8651 [ numerator <= 65536 ]
- */
-
- // Test if we have a zero number allowing for strings with no null terminators
- // and zero decimals with non-zero exponents.
- //
- // We computed firstSigDigit by ignoring all zeros and dots. Thus if
- // D->firstSigDigit equals str.end(), every digit must be a zero and there can
- // be at most one dot. On the other hand, if we have a zero with a non-zero
- // exponent, then we know that D.firstSigDigit will be non-numeric.
- if (D.firstSigDigit == str.end() || decDigitValue(*D.firstSigDigit) >= 10U) {
- category = fcZero;
- fs = opOK;
-
- /* Check whether the normalized exponent is high enough to overflow
- max during the log-rebasing in the max-exponent check below. */
- } else if (D.normalizedExponent - 1 > INT_MAX / 42039) {
- fs = handleOverflow(rounding_mode);
-
- /* If it wasn't, then it also wasn't high enough to overflow max
- during the log-rebasing in the min-exponent check. Check that it
- won't overflow min in either check, then perform the min-exponent
- check. */
- } else if (D.normalizedExponent - 1 < INT_MIN / 42039 ||
- (D.normalizedExponent + 1) * 28738 <=
- 8651 * (semantics->minExponent - (int) semantics->precision)) {
- /* Underflow to zero and round. */
- category = fcNormal;
- zeroSignificand();
- fs = normalize(rounding_mode, lfLessThanHalf);
-
- /* We can finally safely perform the max-exponent check. */
- } else if ((D.normalizedExponent - 1) * 42039
- >= 12655 * semantics->maxExponent) {
- /* Overflow and round. */
- fs = handleOverflow(rounding_mode);
- } else {
- integerPart *decSignificand;
- unsigned int partCount;
-
- /* A tight upper bound on number of bits required to hold an
- N-digit decimal integer is N * 196 / 59. Allocate enough space
- to hold the full significand, and an extra part required by
- tcMultiplyPart. */
- partCount = static_cast<unsigned int>(D.lastSigDigit - D.firstSigDigit) + 1;
- partCount = partCountForBits(1 + 196 * partCount / 59);
- decSignificand = new integerPart[partCount + 1];
- partCount = 0;
-
- /* Convert to binary efficiently - we do almost all multiplication
- in an integerPart. When this would overflow do we do a single
- bignum multiplication, and then revert again to multiplication
- in an integerPart. */
- do {
- integerPart decValue, val, multiplier;
-
- val = 0;
- multiplier = 1;
-
- do {
- if (*p == '.') {
- p++;
- if (p == str.end()) {
- break;
- }
- }
- decValue = decDigitValue(*p++);
- assert(decValue < 10U && "Invalid character in significand");
- multiplier *= 10;
- val = val * 10 + decValue;
- /* The maximum number that can be multiplied by ten with any
- digit added without overflowing an integerPart. */
- } while (p <= D.lastSigDigit && multiplier <= (~ (integerPart) 0 - 9) / 10);
-
- /* Multiply out the current part. */
- APInt::tcMultiplyPart(decSignificand, decSignificand, multiplier, val,
- partCount, partCount + 1, false);
-
- /* If we used another part (likely but not guaranteed), increase
- the count. */
- if (decSignificand[partCount])
- partCount++;
- } while (p <= D.lastSigDigit);
-
- category = fcNormal;
- fs = roundSignificandWithExponent(decSignificand, partCount,
- D.exponent, rounding_mode);
-
- delete [] decSignificand;
- }
-
- return fs;
-}
-
-bool IEEEFloat::convertFromStringSpecials(StringRef str) {
- if (str.equals("inf") || str.equals("INFINITY") || str.equals("+Inf")) {
- makeInf(false);
- return true;
- }
-
- if (str.equals("-inf") || str.equals("-INFINITY") || str.equals("-Inf")) {
- makeInf(true);
- return true;
- }
-
- if (str.equals("nan") || str.equals("NaN")) {
- makeNaN(false, false);
- return true;
- }
-
- if (str.equals("-nan") || str.equals("-NaN")) {
- makeNaN(false, true);
- return true;
- }
-
- return false;
-}
-
-IEEEFloat::opStatus IEEEFloat::convertFromString(StringRef str,
- roundingMode rounding_mode) {
- assert(!str.empty() && "Invalid string length");
-
- // Handle special cases.
- if (convertFromStringSpecials(str))
- return opOK;
-
- /* Handle a leading minus sign. */
- StringRef::iterator p = str.begin();
- size_t slen = str.size();
- sign = *p == '-' ? 1 : 0;
- if (*p == '-' || *p == '+') {
- p++;
- slen--;
- assert(slen && "String has no digits");
- }
-
- if (slen >= 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
- assert(slen - 2 && "Invalid string");
- return convertFromHexadecimalString(StringRef(p + 2, slen - 2),
- rounding_mode);
- }
-
- return convertFromDecimalString(StringRef(p, slen), rounding_mode);
-}
-
-/* Write out a hexadecimal representation of the floating point value
- to DST, which must be of sufficient size, in the C99 form
- [-]0xh.hhhhp[+-]d. Return the number of characters written,
- excluding the terminating NUL.
-
- If UPPERCASE, the output is in upper case, otherwise in lower case.
-
- HEXDIGITS digits appear altogether, rounding the value if
- necessary. If HEXDIGITS is 0, the minimal precision to display the
- number precisely is used instead. If nothing would appear after
- the decimal point it is suppressed.
-
- The decimal exponent is always printed and has at least one digit.
- Zero values display an exponent of zero. Infinities and NaNs
- appear as "infinity" or "nan" respectively.
-
- The above rules are as specified by C99. There is ambiguity about
- what the leading hexadecimal digit should be. This implementation
- uses whatever is necessary so that the exponent is displayed as
- stored. This implies the exponent will fall within the IEEE format
- range, and the leading hexadecimal digit will be 0 (for denormals),
- 1 (normal numbers) or 2 (normal numbers rounded-away-from-zero with
- any other digits zero).
-*/
-unsigned int IEEEFloat::convertToHexString(char *dst, unsigned int hexDigits,
- bool upperCase,
- roundingMode rounding_mode) const {
- char *p;
-
- p = dst;
- if (sign)
- *dst++ = '-';
-
- switch (category) {
- case fcInfinity:
- memcpy (dst, upperCase ? infinityU: infinityL, sizeof infinityU - 1);
- dst += sizeof infinityL - 1;
- break;
-
- case fcNaN:
- memcpy (dst, upperCase ? NaNU: NaNL, sizeof NaNU - 1);
- dst += sizeof NaNU - 1;
- break;
-
- case fcZero:
- *dst++ = '0';
- *dst++ = upperCase ? 'X': 'x';
- *dst++ = '0';
- if (hexDigits > 1) {
- *dst++ = '.';
- memset (dst, '0', hexDigits - 1);
- dst += hexDigits - 1;
- }
- *dst++ = upperCase ? 'P': 'p';
- *dst++ = '0';
- break;
-
- case fcNormal:
- dst = convertNormalToHexString (dst, hexDigits, upperCase, rounding_mode);
- break;
- }
-
- *dst = 0;
-
- return static_cast<unsigned int>(dst - p);
-}
-
-/* Does the hard work of outputting the correctly rounded hexadecimal
- form of a normal floating point number with the specified number of
- hexadecimal digits. If HEXDIGITS is zero the minimum number of
- digits necessary to print the value precisely is output. */
-char *IEEEFloat::convertNormalToHexString(char *dst, unsigned int hexDigits,
- bool upperCase,
- roundingMode rounding_mode) const {
- unsigned int count, valueBits, shift, partsCount, outputDigits;
- const char *hexDigitChars;
- const integerPart *significand;
- char *p;
- bool roundUp;
-
- *dst++ = '0';
- *dst++ = upperCase ? 'X': 'x';
-
- roundUp = false;
- hexDigitChars = upperCase ? hexDigitsUpper: hexDigitsLower;
-
- significand = significandParts();
- partsCount = partCount();
-
- /* +3 because the first digit only uses the single integer bit, so
- we have 3 virtual zero most-significant-bits. */
- valueBits = semantics->precision + 3;
- shift = integerPartWidth - valueBits % integerPartWidth;
-
- /* The natural number of digits required ignoring trailing
- insignificant zeroes. */
- outputDigits = (valueBits - significandLSB () + 3) / 4;
-
- /* hexDigits of zero means use the required number for the
- precision. Otherwise, see if we are truncating. If we are,
- find out if we need to round away from zero. */
- if (hexDigits) {
- if (hexDigits < outputDigits) {
- /* We are dropping non-zero bits, so need to check how to round.
- "bits" is the number of dropped bits. */
- unsigned int bits;
- lostFraction fraction;
-
- bits = valueBits - hexDigits * 4;
- fraction = lostFractionThroughTruncation (significand, partsCount, bits);
- roundUp = roundAwayFromZero(rounding_mode, fraction, bits);
- }
- outputDigits = hexDigits;
- }
-
- /* Write the digits consecutively, and start writing in the location
- of the hexadecimal point. We move the most significant digit
- left and add the hexadecimal point later. */
- p = ++dst;
-
- count = (valueBits + integerPartWidth - 1) / integerPartWidth;
-
- while (outputDigits && count) {
- integerPart part;
-
- /* Put the most significant integerPartWidth bits in "part". */
- if (--count == partsCount)
- part = 0; /* An imaginary higher zero part. */
- else
- part = significand[count] << shift;
-
- if (count && shift)
- part |= significand[count - 1] >> (integerPartWidth - shift);
-
- /* Convert as much of "part" to hexdigits as we can. */
- unsigned int curDigits = integerPartWidth / 4;
-
- if (curDigits > outputDigits)
- curDigits = outputDigits;
- dst += partAsHex (dst, part, curDigits, hexDigitChars);
- outputDigits -= curDigits;
- }
-
- if (roundUp) {
- char *q = dst;
-
- /* Note that hexDigitChars has a trailing '0'. */
- do {
- q--;
- *q = hexDigitChars[hexDigitValue (*q) + 1];
- } while (*q == '0');
- assert(q >= p);
- } else {
- /* Add trailing zeroes. */
- memset (dst, '0', outputDigits);
- dst += outputDigits;
- }
-
- /* Move the most significant digit to before the point, and if there
- is something after the decimal point add it. This must come
- after rounding above. */
- p[-1] = p[0];
- if (dst -1 == p)
- dst--;
- else
- p[0] = '.';
-
- /* Finally output the exponent. */
- *dst++ = upperCase ? 'P': 'p';
-
- return writeSignedDecimal (dst, exponent);
-}
-
-hash_code hash_value(const IEEEFloat &Arg) {
- if (!Arg.isFiniteNonZero())
- return hash_combine((uint8_t)Arg.category,
- // NaN has no sign, fix it at zero.
- Arg.isNaN() ? (uint8_t)0 : (uint8_t)Arg.sign,
- Arg.semantics->precision);
-
- // Normal floats need their exponent and significand hashed.
- return hash_combine((uint8_t)Arg.category, (uint8_t)Arg.sign,
- Arg.semantics->precision, Arg.exponent,
- hash_combine_range(
- Arg.significandParts(),
- Arg.significandParts() + Arg.partCount()));
-}
-
-// Conversion from APFloat to/from host float/double. It may eventually be
-// possible to eliminate these and have everybody deal with APFloats, but that
-// will take a while. This approach will not easily extend to long double.
-// Current implementation requires integerPartWidth==64, which is correct at
-// the moment but could be made more general.
-
-// Denormals have exponent minExponent in APFloat, but minExponent-1 in
-// the actual IEEE respresentations. We compensate for that here.
-
-APInt IEEEFloat::convertF80LongDoubleAPFloatToAPInt() const {
- assert(semantics == (const llvm::fltSemantics*)&semX87DoubleExtended);
- assert(partCount()==2);
-
- uint64_t myexponent, mysignificand;
-
- if (isFiniteNonZero()) {
- myexponent = exponent+16383; //bias
- mysignificand = significandParts()[0];
- if (myexponent==1 && !(mysignificand & 0x8000000000000000ULL))
- myexponent = 0; // denormal
- } else if (category==fcZero) {
- myexponent = 0;
- mysignificand = 0;
- } else if (category==fcInfinity) {
- myexponent = 0x7fff;
- mysignificand = 0x8000000000000000ULL;
- } else {
- assert(category == fcNaN && "Unknown category");
- myexponent = 0x7fff;
- mysignificand = significandParts()[0];
- }
-
- uint64_t words[2];
- words[0] = mysignificand;
- words[1] = ((uint64_t)(sign & 1) << 15) |
- (myexponent & 0x7fffLL);
- return APInt(80, words);
-}
-
-APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const {
- assert(semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy);
- assert(partCount()==2);
-
- uint64_t words[2];
- opStatus fs;
- bool losesInfo;
-
- // Convert number to double. To avoid spurious underflows, we re-
- // normalize against the "double" minExponent first, and only *then*
- // truncate the mantissa. The result of that second conversion
- // may be inexact, but should never underflow.
- // Declare fltSemantics before APFloat that uses it (and
- // saves pointer to it) to ensure correct destruction order.
- fltSemantics extendedSemantics = *semantics;
- extendedSemantics.minExponent = semIEEEdouble.minExponent;
- IEEEFloat extended(*this);
- fs = extended.convert(extendedSemantics, rmNearestTiesToEven, &losesInfo);
- assert(fs == opOK && !losesInfo);
- (void)fs;
-
- IEEEFloat u(extended);
- fs = u.convert(semIEEEdouble, rmNearestTiesToEven, &losesInfo);
- assert(fs == opOK || fs == opInexact);
- (void)fs;
- words[0] = *u.convertDoubleAPFloatToAPInt().getRawData();
-
- // If conversion was exact or resulted in a special case, we're done;
- // just set the second double to zero. Otherwise, re-convert back to
- // the extended format and compute the difference. This now should
- // convert exactly to double.
- if (u.isFiniteNonZero() && losesInfo) {
- fs = u.convert(extendedSemantics, rmNearestTiesToEven, &losesInfo);
- assert(fs == opOK && !losesInfo);
- (void)fs;
-
- IEEEFloat v(extended);
- v.subtract(u, rmNearestTiesToEven);
- fs = v.convert(semIEEEdouble, rmNearestTiesToEven, &losesInfo);
- assert(fs == opOK && !losesInfo);
- (void)fs;
- words[1] = *v.convertDoubleAPFloatToAPInt().getRawData();
- } else {
- words[1] = 0;
- }
-
- return APInt(128, words);
-}
-
-APInt IEEEFloat::convertQuadrupleAPFloatToAPInt() const {
- assert(semantics == (const llvm::fltSemantics*)&semIEEEquad);
- assert(partCount()==2);
-
- uint64_t myexponent, mysignificand, mysignificand2;
-
- if (isFiniteNonZero()) {
- myexponent = exponent+16383; //bias
- mysignificand = significandParts()[0];
- mysignificand2 = significandParts()[1];
- if (myexponent==1 && !(mysignificand2 & 0x1000000000000LL))
- myexponent = 0; // denormal
- } else if (category==fcZero) {
- myexponent = 0;
- mysignificand = mysignificand2 = 0;
- } else if (category==fcInfinity) {
- myexponent = 0x7fff;
- mysignificand = mysignificand2 = 0;
- } else {
- assert(category == fcNaN && "Unknown category!");
- myexponent = 0x7fff;
- mysignificand = significandParts()[0];
- mysignificand2 = significandParts()[1];
- }
-
- uint64_t words[2];
- words[0] = mysignificand;
- words[1] = ((uint64_t)(sign & 1) << 63) |
- ((myexponent & 0x7fff) << 48) |
- (mysignificand2 & 0xffffffffffffLL);
-
- return APInt(128, words);
-}
-
-APInt IEEEFloat::convertDoubleAPFloatToAPInt() const {
- assert(semantics == (const llvm::fltSemantics*)&semIEEEdouble);
- assert(partCount()==1);
-
- uint64_t myexponent, mysignificand;
-
- if (isFiniteNonZero()) {
- myexponent = exponent+1023; //bias
- mysignificand = *significandParts();
- if (myexponent==1 && !(mysignificand & 0x10000000000000LL))
- myexponent = 0; // denormal
- } else if (category==fcZero) {
- myexponent = 0;
- mysignificand = 0;
- } else if (category==fcInfinity) {
- myexponent = 0x7ff;
- mysignificand = 0;
- } else {
- assert(category == fcNaN && "Unknown category!");
- myexponent = 0x7ff;
- mysignificand = *significandParts();
- }
-
- return APInt(64, ((((uint64_t)(sign & 1) << 63) |
- ((myexponent & 0x7ff) << 52) |
- (mysignificand & 0xfffffffffffffLL))));
-}
-
-APInt IEEEFloat::convertFloatAPFloatToAPInt() const {
- assert(semantics == (const llvm::fltSemantics*)&semIEEEsingle);
- assert(partCount()==1);
-
- uint32_t myexponent, mysignificand;
-
- if (isFiniteNonZero()) {
- myexponent = exponent+127; //bias
- mysignificand = (uint32_t)*significandParts();
- if (myexponent == 1 && !(mysignificand & 0x800000))
- myexponent = 0; // denormal
- } else if (category==fcZero) {
- myexponent = 0;
- mysignificand = 0;
- } else if (category==fcInfinity) {
- myexponent = 0xff;
- mysignificand = 0;
- } else {
- assert(category == fcNaN && "Unknown category!");
- myexponent = 0xff;
- mysignificand = (uint32_t)*significandParts();
- }
-
- return APInt(32, (((sign&1) << 31) | ((myexponent&0xff) << 23) |
- (mysignificand & 0x7fffff)));
-}
-
-APInt IEEEFloat::convertHalfAPFloatToAPInt() const {
- assert(semantics == (const llvm::fltSemantics*)&semIEEEhalf);
- assert(partCount()==1);
-
- uint32_t myexponent, mysignificand;
-
- if (isFiniteNonZero()) {
- myexponent = exponent+15; //bias
- mysignificand = (uint32_t)*significandParts();
- if (myexponent == 1 && !(mysignificand & 0x400))
- myexponent = 0; // denormal
- } else if (category==fcZero) {
- myexponent = 0;
- mysignificand = 0;
- } else if (category==fcInfinity) {
- myexponent = 0x1f;
- mysignificand = 0;
- } else {
- assert(category == fcNaN && "Unknown category!");
- myexponent = 0x1f;
- mysignificand = (uint32_t)*significandParts();
- }
-
- return APInt(16, (((sign&1) << 15) | ((myexponent&0x1f) << 10) |
- (mysignificand & 0x3ff)));
-}
-
-// This function creates an APInt that is just a bit map of the floating
-// point constant as it would appear in memory. It is not a conversion,
-// and treating the result as a normal integer is unlikely to be useful.
-
-APInt IEEEFloat::bitcastToAPInt() const {
- if (semantics == (const llvm::fltSemantics*)&semIEEEhalf)
- return convertHalfAPFloatToAPInt();
-
- if (semantics == (const llvm::fltSemantics*)&semIEEEsingle)
- return convertFloatAPFloatToAPInt();
-
- if (semantics == (const llvm::fltSemantics*)&semIEEEdouble)
- return convertDoubleAPFloatToAPInt();
-
- if (semantics == (const llvm::fltSemantics*)&semIEEEquad)
- return convertQuadrupleAPFloatToAPInt();
-
- if (semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy)
- return convertPPCDoubleDoubleAPFloatToAPInt();
-
- assert(semantics == (const llvm::fltSemantics*)&semX87DoubleExtended &&
- "unknown format!");
- return convertF80LongDoubleAPFloatToAPInt();
-}
-
-float IEEEFloat::convertToFloat() const {
- assert(semantics == (const llvm::fltSemantics*)&semIEEEsingle &&
- "Float semantics are not IEEEsingle");
- APInt api = bitcastToAPInt();
- return api.bitsToFloat();
-}
-
-double IEEEFloat::convertToDouble() const {
- assert(semantics == (const llvm::fltSemantics*)&semIEEEdouble &&
- "Float semantics are not IEEEdouble");
- APInt api = bitcastToAPInt();
- return api.bitsToDouble();
-}
-
-/// Integer bit is explicit in this format. Intel hardware (387 and later)
-/// does not support these bit patterns:
-/// exponent = all 1's, integer bit 0, significand 0 ("pseudoinfinity")
-/// exponent = all 1's, integer bit 0, significand nonzero ("pseudoNaN")
-/// exponent!=0 nor all 1's, integer bit 0 ("unnormal")
-/// exponent = 0, integer bit 1 ("pseudodenormal")
-/// At the moment, the first three are treated as NaNs, the last one as Normal.
-void IEEEFloat::initFromF80LongDoubleAPInt(const APInt &api) {
- assert(api.getBitWidth()==80);
- uint64_t i1 = api.getRawData()[0];
- uint64_t i2 = api.getRawData()[1];
- uint64_t myexponent = (i2 & 0x7fff);
- uint64_t mysignificand = i1;
- uint8_t myintegerbit = mysignificand >> 63;
-
- initialize(&semX87DoubleExtended);
- assert(partCount()==2);
-
- sign = static_cast<unsigned int>(i2>>15);
- if (myexponent == 0 && mysignificand == 0) {
- // exponent, significand meaningless
- category = fcZero;
- } else if (myexponent==0x7fff && mysignificand==0x8000000000000000ULL) {
- // exponent, significand meaningless
- category = fcInfinity;
- } else if ((myexponent == 0x7fff && mysignificand != 0x8000000000000000ULL) ||
- (myexponent != 0x7fff && myexponent != 0 && myintegerbit == 0)) {
- // exponent meaningless
- category = fcNaN;
- significandParts()[0] = mysignificand;
- significandParts()[1] = 0;
- } else {
- category = fcNormal;
- exponent = myexponent - 16383;
- significandParts()[0] = mysignificand;
- significandParts()[1] = 0;
- if (myexponent==0) // denormal
- exponent = -16382;
- }
-}
-
-void IEEEFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) {
- assert(api.getBitWidth()==128);
- uint64_t i1 = api.getRawData()[0];
- uint64_t i2 = api.getRawData()[1];
- opStatus fs;
- bool losesInfo;
-
- // Get the first double and convert to our format.
- initFromDoubleAPInt(APInt(64, i1));
- fs = convert(semPPCDoubleDoubleLegacy, rmNearestTiesToEven, &losesInfo);
- assert(fs == opOK && !losesInfo);
- (void)fs;
-
- // Unless we have a special case, add in second double.
- if (isFiniteNonZero()) {
- IEEEFloat v(semIEEEdouble, APInt(64, i2));
- fs = v.convert(semPPCDoubleDoubleLegacy, rmNearestTiesToEven, &losesInfo);
- assert(fs == opOK && !losesInfo);
- (void)fs;
-
- add(v, rmNearestTiesToEven);
- }
-}
-
-void IEEEFloat::initFromQuadrupleAPInt(const APInt &api) {
- assert(api.getBitWidth()==128);
- uint64_t i1 = api.getRawData()[0];
- uint64_t i2 = api.getRawData()[1];
- uint64_t myexponent = (i2 >> 48) & 0x7fff;
- uint64_t mysignificand = i1;
- uint64_t mysignificand2 = i2 & 0xffffffffffffLL;
-
- initialize(&semIEEEquad);
- assert(partCount()==2);
-
- sign = static_cast<unsigned int>(i2>>63);
- if (myexponent==0 &&
- (mysignificand==0 && mysignificand2==0)) {
- // exponent, significand meaningless
- category = fcZero;
- } else if (myexponent==0x7fff &&
- (mysignificand==0 && mysignificand2==0)) {
- // exponent, significand meaningless
- category = fcInfinity;
- } else if (myexponent==0x7fff &&
- (mysignificand!=0 || mysignificand2 !=0)) {
- // exponent meaningless
- category = fcNaN;
- significandParts()[0] = mysignificand;
- significandParts()[1] = mysignificand2;
- } else {
- category = fcNormal;
- exponent = myexponent - 16383;
- significandParts()[0] = mysignificand;
- significandParts()[1] = mysignificand2;
- if (myexponent==0) // denormal
- exponent = -16382;
- else
- significandParts()[1] |= 0x1000000000000LL; // integer bit
- }
-}
-
-void IEEEFloat::initFromDoubleAPInt(const APInt &api) {
- assert(api.getBitWidth()==64);
- uint64_t i = *api.getRawData();
- uint64_t myexponent = (i >> 52) & 0x7ff;
- uint64_t mysignificand = i & 0xfffffffffffffLL;
-
- initialize(&semIEEEdouble);
- assert(partCount()==1);
-
- sign = static_cast<unsigned int>(i>>63);
- if (myexponent==0 && mysignificand==0) {
- // exponent, significand meaningless
- category = fcZero;
- } else if (myexponent==0x7ff && mysignificand==0) {
- // exponent, significand meaningless
- category = fcInfinity;
- } else if (myexponent==0x7ff && mysignificand!=0) {
- // exponent meaningless
- category = fcNaN;
- *significandParts() = mysignificand;
- } else {
- category = fcNormal;
- exponent = myexponent - 1023;
- *significandParts() = mysignificand;
- if (myexponent==0) // denormal
- exponent = -1022;
- else
- *significandParts() |= 0x10000000000000LL; // integer bit
- }
-}
-
-void IEEEFloat::initFromFloatAPInt(const APInt &api) {
- assert(api.getBitWidth()==32);
- uint32_t i = (uint32_t)*api.getRawData();
- uint32_t myexponent = (i >> 23) & 0xff;
- uint32_t mysignificand = i & 0x7fffff;
-
- initialize(&semIEEEsingle);
- assert(partCount()==1);
-
- sign = i >> 31;
- if (myexponent==0 && mysignificand==0) {
- // exponent, significand meaningless
- category = fcZero;
- } else if (myexponent==0xff && mysignificand==0) {
- // exponent, significand meaningless
- category = fcInfinity;
- } else if (myexponent==0xff && mysignificand!=0) {
- // sign, exponent, significand meaningless
- category = fcNaN;
- *significandParts() = mysignificand;
- } else {
- category = fcNormal;
- exponent = myexponent - 127; //bias
- *significandParts() = mysignificand;
- if (myexponent==0) // denormal
- exponent = -126;
- else
- *significandParts() |= 0x800000; // integer bit
- }
-}
-
-void IEEEFloat::initFromHalfAPInt(const APInt &api) {
- assert(api.getBitWidth()==16);
- uint32_t i = (uint32_t)*api.getRawData();
- uint32_t myexponent = (i >> 10) & 0x1f;
- uint32_t mysignificand = i & 0x3ff;
-
- initialize(&semIEEEhalf);
- assert(partCount()==1);
-
- sign = i >> 15;
- if (myexponent==0 && mysignificand==0) {
- // exponent, significand meaningless
- category = fcZero;
- } else if (myexponent==0x1f && mysignificand==0) {
- // exponent, significand meaningless
- category = fcInfinity;
- } else if (myexponent==0x1f && mysignificand!=0) {
- // sign, exponent, significand meaningless
- category = fcNaN;
- *significandParts() = mysignificand;
- } else {
- category = fcNormal;
- exponent = myexponent - 15; //bias
- *significandParts() = mysignificand;
- if (myexponent==0) // denormal
- exponent = -14;
- else
- *significandParts() |= 0x400; // integer bit
- }
-}
-
-/// Treat api as containing the bits of a floating point number. Currently
-/// we infer the floating point type from the size of the APInt. The
-/// isIEEE argument distinguishes between PPC128 and IEEE128 (not meaningful
-/// when the size is anything else).
-void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
- if (Sem == &semIEEEhalf)
- return initFromHalfAPInt(api);
- if (Sem == &semIEEEsingle)
- return initFromFloatAPInt(api);
- if (Sem == &semIEEEdouble)
- return initFromDoubleAPInt(api);
- if (Sem == &semX87DoubleExtended)
- return initFromF80LongDoubleAPInt(api);
- if (Sem == &semIEEEquad)
- return initFromQuadrupleAPInt(api);
- if (Sem == &semPPCDoubleDoubleLegacy)
- return initFromPPCDoubleDoubleAPInt(api);
-
- llvm_unreachable(nullptr);
-}
-
-/// Make this number the largest magnitude normal number in the given
-/// semantics.
-void IEEEFloat::makeLargest(bool Negative) {
- // We want (in interchange format):
- // sign = {Negative}
- // exponent = 1..10
- // significand = 1..1
- category = fcNormal;
- sign = Negative;
- exponent = semantics->maxExponent;
-
- // Use memset to set all but the highest integerPart to all ones.
- integerPart *significand = significandParts();
- unsigned PartCount = partCount();
- memset(significand, 0xFF, sizeof(integerPart)*(PartCount - 1));
-
- // Set the high integerPart especially setting all unused top bits for
- // internal consistency.
- const unsigned NumUnusedHighBits =
- PartCount*integerPartWidth - semantics->precision;
- significand[PartCount - 1] = (NumUnusedHighBits < integerPartWidth)
- ? (~integerPart(0) >> NumUnusedHighBits)
- : 0;
-}
-
-/// Make this number the smallest magnitude denormal number in the given
-/// semantics.
-void IEEEFloat::makeSmallest(bool Negative) {
- // We want (in interchange format):
- // sign = {Negative}
- // exponent = 0..0
- // significand = 0..01
- category = fcNormal;
- sign = Negative;
- exponent = semantics->minExponent;
- APInt::tcSet(significandParts(), 1, partCount());
-}
-
-void IEEEFloat::makeSmallestNormalized(bool Negative) {
- // We want (in interchange format):
- // sign = {Negative}
- // exponent = 0..0
- // significand = 10..0
-
- category = fcNormal;
- zeroSignificand();
- sign = Negative;
- exponent = semantics->minExponent;
- significandParts()[partCountForBits(semantics->precision) - 1] |=
- (((integerPart)1) << ((semantics->precision - 1) % integerPartWidth));
-}
-
-IEEEFloat::IEEEFloat(const fltSemantics &Sem, const APInt &API) {
- initFromAPInt(&Sem, API);
-}
-
-IEEEFloat::IEEEFloat(float f) {
- initFromAPInt(&semIEEEsingle, APInt::floatToBits(f));
-}
-
-IEEEFloat::IEEEFloat(double d) {
- initFromAPInt(&semIEEEdouble, APInt::doubleToBits(d));
-}
-
-namespace {
- void append(SmallVectorImpl<char> &Buffer, StringRef Str) {
- Buffer.append(Str.begin(), Str.end());
- }
-
- /// Removes data from the given significand until it is no more
- /// precise than is required for the desired precision.
- void AdjustToPrecision(APInt &significand,
- int &exp, unsigned FormatPrecision) {
- unsigned bits = significand.getActiveBits();
-
- // 196/59 is a very slight overestimate of lg_2(10).
- unsigned bitsRequired = (FormatPrecision * 196 + 58) / 59;
-
- if (bits <= bitsRequired) return;
-
- unsigned tensRemovable = (bits - bitsRequired) * 59 / 196;
- if (!tensRemovable) return;
-
- exp += tensRemovable;
-
- APInt divisor(significand.getBitWidth(), 1);
- APInt powten(significand.getBitWidth(), 10);
- while (true) {
- if (tensRemovable & 1)
- divisor *= powten;
- tensRemovable >>= 1;
- if (!tensRemovable) break;
- powten *= powten;
- }
-
- significand = significand.udiv(divisor);
-
- // Truncate the significand down to its active bit count.
- significand = significand.trunc(significand.getActiveBits());
- }
-
-
- void AdjustToPrecision(SmallVectorImpl<char> &buffer,
- int &exp, unsigned FormatPrecision) {
- unsigned N = buffer.size();
- if (N <= FormatPrecision) return;
-
- // The most significant figures are the last ones in the buffer.
- unsigned FirstSignificant = N - FormatPrecision;
-
- // Round.
- // FIXME: this probably shouldn't use 'round half up'.
-
- // Rounding down is just a truncation, except we also want to drop
- // trailing zeros from the new result.
- if (buffer[FirstSignificant - 1] < '5') {
- while (FirstSignificant < N && buffer[FirstSignificant] == '0')
- FirstSignificant++;
-
- exp += FirstSignificant;
- buffer.erase(&buffer[0], &buffer[FirstSignificant]);
- return;
- }
-
- // Rounding up requires a decimal add-with-carry. If we continue
- // the carry, the newly-introduced zeros will just be truncated.
- for (unsigned I = FirstSignificant; I != N; ++I) {
- if (buffer[I] == '9') {
- FirstSignificant++;
- } else {
- buffer[I]++;
- break;
- }
- }
-
- // If we carried through, we have exactly one digit of precision.
- if (FirstSignificant == N) {
- exp += FirstSignificant;
- buffer.clear();
- buffer.push_back('1');
- return;
- }
-
- exp += FirstSignificant;
- buffer.erase(&buffer[0], &buffer[FirstSignificant]);
- }
-}
-
-void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
- unsigned FormatMaxPadding, bool TruncateZero) const {
- switch (category) {
- case fcInfinity:
- if (isNegative())
- return append(Str, "-Inf");
- else
- return append(Str, "+Inf");
-
- case fcNaN: return append(Str, "NaN");
-
- case fcZero:
- if (isNegative())
- Str.push_back('-');
-
- if (!FormatMaxPadding) {
- if (TruncateZero)
- append(Str, "0.0E+0");
- else {
- append(Str, "0.0");
- if (FormatPrecision > 1)
- Str.append(FormatPrecision - 1, '0');
- append(Str, "e+00");
- }
- } else
- Str.push_back('0');
- return;
-
- case fcNormal:
- break;
- }
-
- if (isNegative())
- Str.push_back('-');
-
- // Decompose the number into an APInt and an exponent.
- int exp = exponent - ((int) semantics->precision - 1);
- APInt significand(semantics->precision,
- makeArrayRef(significandParts(),
- partCountForBits(semantics->precision)));
-
- // Set FormatPrecision if zero. We want to do this before we
- // truncate trailing zeros, as those are part of the precision.
- if (!FormatPrecision) {
- // We use enough digits so the number can be round-tripped back to an
- // APFloat. The formula comes from "How to Print Floating-Point Numbers
- // Accurately" by Steele and White.
- // FIXME: Using a formula based purely on the precision is conservative;
- // we can print fewer digits depending on the actual value being printed.
-
- // FormatPrecision = 2 + floor(significandBits / lg_2(10))
- FormatPrecision = 2 + semantics->precision * 59 / 196;
- }
-
- // Ignore trailing binary zeros.
- int trailingZeros = significand.countTrailingZeros();
- exp += trailingZeros;
- significand.lshrInPlace(trailingZeros);
-
- // Change the exponent from 2^e to 10^e.
- if (exp == 0) {
- // Nothing to do.
- } else if (exp > 0) {
- // Just shift left.
- significand = significand.zext(semantics->precision + exp);
- significand <<= exp;
- exp = 0;
- } else { /* exp < 0 */
- int texp = -exp;
-
- // We transform this using the identity:
- // (N)(2^-e) == (N)(5^e)(10^-e)
- // This means we have to multiply N (the significand) by 5^e.
- // To avoid overflow, we have to operate on numbers large
- // enough to store N * 5^e:
- // log2(N * 5^e) == log2(N) + e * log2(5)
- // <= semantics->precision + e * 137 / 59
- // (log_2(5) ~ 2.321928 < 2.322034 ~ 137/59)
-
- unsigned precision = semantics->precision + (137 * texp + 136) / 59;
-
- // Multiply significand by 5^e.
- // N * 5^0101 == N * 5^(1*1) * 5^(0*2) * 5^(1*4) * 5^(0*8)
- significand = significand.zext(precision);
- APInt five_to_the_i(precision, 5);
- while (true) {
- if (texp & 1) significand *= five_to_the_i;
-
- texp >>= 1;
- if (!texp) break;
- five_to_the_i *= five_to_the_i;
- }
- }
-
- AdjustToPrecision(significand, exp, FormatPrecision);
-
- SmallVector<char, 256> buffer;
-
- // Fill the buffer.
- unsigned precision = significand.getBitWidth();
- APInt ten(precision, 10);
- APInt digit(precision, 0);
-
- bool inTrail = true;
- while (significand != 0) {
- // digit <- significand % 10
- // significand <- significand / 10
- APInt::udivrem(significand, ten, significand, digit);
-
- unsigned d = digit.getZExtValue();
-
- // Drop trailing zeros.
- if (inTrail && !d) exp++;
- else {
- buffer.push_back((char) ('0' + d));
- inTrail = false;
- }
- }
-
- assert(!buffer.empty() && "no characters in buffer!");
-
- // Drop down to FormatPrecision.
- // TODO: don't do more precise calculations above than are required.
- AdjustToPrecision(buffer, exp, FormatPrecision);
-
- unsigned NDigits = buffer.size();
-
- // Check whether we should use scientific notation.
- bool FormatScientific;
- if (!FormatMaxPadding)
- FormatScientific = true;
- else {
- if (exp >= 0) {
- // 765e3 --> 765000
- // ^^^
- // But we shouldn't make the number look more precise than it is.
- FormatScientific = ((unsigned) exp > FormatMaxPadding ||
- NDigits + (unsigned) exp > FormatPrecision);
- } else {
- // Power of the most significant digit.
- int MSD = exp + (int) (NDigits - 1);
- if (MSD >= 0) {
- // 765e-2 == 7.65
- FormatScientific = false;
- } else {
- // 765e-5 == 0.00765
- // ^ ^^
- FormatScientific = ((unsigned) -MSD) > FormatMaxPadding;
- }
- }
- }
-
- // Scientific formatting is pretty straightforward.
- if (FormatScientific) {
- exp += (NDigits - 1);
-
- Str.push_back(buffer[NDigits-1]);
- Str.push_back('.');
- if (NDigits == 1 && TruncateZero)
- Str.push_back('0');
- else
- for (unsigned I = 1; I != NDigits; ++I)
- Str.push_back(buffer[NDigits-1-I]);
- // Fill with zeros up to FormatPrecision.
- if (!TruncateZero && FormatPrecision > NDigits - 1)
- Str.append(FormatPrecision - NDigits + 1, '0');
- // For !TruncateZero we use lower 'e'.
- Str.push_back(TruncateZero ? 'E' : 'e');
-
- Str.push_back(exp >= 0 ? '+' : '-');
- if (exp < 0) exp = -exp;
- SmallVector<char, 6> expbuf;
- do {
- expbuf.push_back((char) ('0' + (exp % 10)));
- exp /= 10;
- } while (exp);
- // Exponent always at least two digits if we do not truncate zeros.
- if (!TruncateZero && expbuf.size() < 2)
- expbuf.push_back('0');
- for (unsigned I = 0, E = expbuf.size(); I != E; ++I)
- Str.push_back(expbuf[E-1-I]);
- return;
- }
-
- // Non-scientific, positive exponents.
- if (exp >= 0) {
- for (unsigned I = 0; I != NDigits; ++I)
- Str.push_back(buffer[NDigits-1-I]);
- for (unsigned I = 0; I != (unsigned) exp; ++I)
- Str.push_back('0');
- return;
- }
-
- // Non-scientific, negative exponents.
-
- // The number of digits to the left of the decimal point.
- int NWholeDigits = exp + (int) NDigits;
-
- unsigned I = 0;
- if (NWholeDigits > 0) {
- for (; I != (unsigned) NWholeDigits; ++I)
- Str.push_back(buffer[NDigits-I-1]);
- Str.push_back('.');
- } else {
- unsigned NZeros = 1 + (unsigned) -NWholeDigits;
-
- Str.push_back('0');
- Str.push_back('.');
- for (unsigned Z = 1; Z != NZeros; ++Z)
- Str.push_back('0');
- }
-
- for (; I != NDigits; ++I)
- Str.push_back(buffer[NDigits-I-1]);
-}
-
-bool IEEEFloat::getExactInverse(APFloat *inv) const {
- // Special floats and denormals have no exact inverse.
- if (!isFiniteNonZero())
- return false;
-
- // Check that the number is a power of two by making sure that only the
- // integer bit is set in the significand.
- if (significandLSB() != semantics->precision - 1)
- return false;
-
- // Get the inverse.
- IEEEFloat reciprocal(*semantics, 1ULL);
- if (reciprocal.divide(*this, rmNearestTiesToEven) != opOK)
- return false;
-
- // Avoid multiplication with a denormal, it is not safe on all platforms and
- // may be slower than a normal division.
- if (reciprocal.isDenormal())
- return false;
-
- assert(reciprocal.isFiniteNonZero() &&
- reciprocal.significandLSB() == reciprocal.semantics->precision - 1);
-
- if (inv)
- *inv = APFloat(reciprocal, *semantics);
-
- return true;
-}
-
-bool IEEEFloat::isSignaling() const {
- if (!isNaN())
- return false;
-
- // IEEE-754R 2008 6.2.1: A signaling NaN bit string should be encoded with the
- // first bit of the trailing significand being 0.
- return !APInt::tcExtractBit(significandParts(), semantics->precision - 2);
-}
-
-/// IEEE-754R 2008 5.3.1: nextUp/nextDown.
-///
-/// *NOTE* since nextDown(x) = -nextUp(-x), we only implement nextUp with
-/// appropriate sign switching before/after the computation.
-IEEEFloat::opStatus IEEEFloat::next(bool nextDown) {
- // If we are performing nextDown, swap sign so we have -x.
- if (nextDown)
- changeSign();
-
- // Compute nextUp(x)
- opStatus result = opOK;
-
- // Handle each float category separately.
- switch (category) {
- case fcInfinity:
- // nextUp(+inf) = +inf
- if (!isNegative())
- break;
- // nextUp(-inf) = -getLargest()
- makeLargest(true);
- break;
- case fcNaN:
- // IEEE-754R 2008 6.2 Par 2: nextUp(sNaN) = qNaN. Set Invalid flag.
- // IEEE-754R 2008 6.2: nextUp(qNaN) = qNaN. Must be identity so we do not
- // change the payload.
- if (isSignaling()) {
- result = opInvalidOp;
- // For consistency, propagate the sign of the sNaN to the qNaN.
- makeNaN(false, isNegative(), nullptr);
- }
- break;
- case fcZero:
- // nextUp(pm 0) = +getSmallest()
- makeSmallest(false);
- break;
- case fcNormal:
- // nextUp(-getSmallest()) = -0
- if (isSmallest() && isNegative()) {
- APInt::tcSet(significandParts(), 0, partCount());
- category = fcZero;
- exponent = 0;
- break;
- }
-
- // nextUp(getLargest()) == INFINITY
- if (isLargest() && !isNegative()) {
- APInt::tcSet(significandParts(), 0, partCount());
- category = fcInfinity;
- exponent = semantics->maxExponent + 1;
- break;
- }
-
- // nextUp(normal) == normal + inc.
- if (isNegative()) {
- // If we are negative, we need to decrement the significand.
-
- // We only cross a binade boundary that requires adjusting the exponent
- // if:
- // 1. exponent != semantics->minExponent. This implies we are not in the
- // smallest binade or are dealing with denormals.
- // 2. Our significand excluding the integral bit is all zeros.
- bool WillCrossBinadeBoundary =
- exponent != semantics->minExponent && isSignificandAllZeros();
-
- // Decrement the significand.
- //
- // We always do this since:
- // 1. If we are dealing with a non-binade decrement, by definition we
- // just decrement the significand.
- // 2. If we are dealing with a normal -> normal binade decrement, since
- // we have an explicit integral bit the fact that all bits but the
- // integral bit are zero implies that subtracting one will yield a
- // significand with 0 integral bit and 1 in all other spots. Thus we
- // must just adjust the exponent and set the integral bit to 1.
- // 3. If we are dealing with a normal -> denormal binade decrement,
- // since we set the integral bit to 0 when we represent denormals, we
- // just decrement the significand.
- integerPart *Parts = significandParts();
- APInt::tcDecrement(Parts, partCount());
-
- if (WillCrossBinadeBoundary) {
- // Our result is a normal number. Do the following:
- // 1. Set the integral bit to 1.
- // 2. Decrement the exponent.
- APInt::tcSetBit(Parts, semantics->precision - 1);
- exponent--;
- }
- } else {
- // If we are positive, we need to increment the significand.
-
- // We only cross a binade boundary that requires adjusting the exponent if
- // the input is not a denormal and all of said input's significand bits
- // are set. If all of said conditions are true: clear the significand, set
- // the integral bit to 1, and increment the exponent. If we have a
- // denormal always increment since moving denormals and the numbers in the
- // smallest normal binade have the same exponent in our representation.
- bool WillCrossBinadeBoundary = !isDenormal() && isSignificandAllOnes();
-
- if (WillCrossBinadeBoundary) {
- integerPart *Parts = significandParts();
- APInt::tcSet(Parts, 0, partCount());
- APInt::tcSetBit(Parts, semantics->precision - 1);
- assert(exponent != semantics->maxExponent &&
- "We can not increment an exponent beyond the maxExponent allowed"
- " by the given floating point semantics.");
- exponent++;
- } else {
- incrementSignificand();
- }
- }
- break;
- }
-
- // If we are performing nextDown, swap sign so we have -nextUp(-x)
- if (nextDown)
- changeSign();
-
- return result;
-}
-
-void IEEEFloat::makeInf(bool Negative) {
- category = fcInfinity;
- sign = Negative;
- exponent = semantics->maxExponent + 1;
- APInt::tcSet(significandParts(), 0, partCount());
-}
-
-void IEEEFloat::makeZero(bool Negative) {
- category = fcZero;
- sign = Negative;
- exponent = semantics->minExponent-1;
- APInt::tcSet(significandParts(), 0, partCount());
-}
-
-void IEEEFloat::makeQuiet() {
- assert(isNaN());
- APInt::tcSetBit(significandParts(), semantics->precision - 2);
-}
-
-int ilogb(const IEEEFloat &Arg) {
- if (Arg.isNaN())
- return IEEEFloat::IEK_NaN;
- if (Arg.isZero())
- return IEEEFloat::IEK_Zero;
- if (Arg.isInfinity())
- return IEEEFloat::IEK_Inf;
- if (!Arg.isDenormal())
- return Arg.exponent;
-
- IEEEFloat Normalized(Arg);
- int SignificandBits = Arg.getSemantics().precision - 1;
-
- Normalized.exponent += SignificandBits;
- Normalized.normalize(IEEEFloat::rmNearestTiesToEven, lfExactlyZero);
- return Normalized.exponent - SignificandBits;
-}
-
-IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode RoundingMode) {
- auto MaxExp = X.getSemantics().maxExponent;
- auto MinExp = X.getSemantics().minExponent;
-
- // If Exp is wildly out-of-scale, simply adding it to X.exponent will
- // overflow; clamp it to a safe range before adding, but ensure that the range
- // is large enough that the clamp does not change the result. The range we
- // need to support is the difference between the largest possible exponent and
- // the normalized exponent of half the smallest denormal.
-
- int SignificandBits = X.getSemantics().precision - 1;
- int MaxIncrement = MaxExp - (MinExp - SignificandBits) + 1;
-
- // Clamp to one past the range ends to let normalize handle overlflow.
- X.exponent += std::min(std::max(Exp, -MaxIncrement - 1), MaxIncrement);
- X.normalize(RoundingMode, lfExactlyZero);
- if (X.isNaN())
- X.makeQuiet();
- return X;
-}
-
-IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM) {
- Exp = ilogb(Val);
-
- // Quiet signalling nans.
- if (Exp == IEEEFloat::IEK_NaN) {
- IEEEFloat Quiet(Val);
- Quiet.makeQuiet();
- return Quiet;
- }
-
- if (Exp == IEEEFloat::IEK_Inf)
- return Val;
-
- // 1 is added because frexp is defined to return a normalized fraction in
- // +/-[0.5, 1.0), rather than the usual +/-[1.0, 2.0).
- Exp = Exp == IEEEFloat::IEK_Zero ? 0 : Exp + 1;
- return scalbn(Val, -Exp, RM);
-}
-
-DoubleAPFloat::DoubleAPFloat(const fltSemantics &S)
- : Semantics(&S),
- Floats(new APFloat[2]{APFloat(semIEEEdouble), APFloat(semIEEEdouble)}) {
- assert(Semantics == &semPPCDoubleDouble);
-}
-
-DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, uninitializedTag)
- : Semantics(&S),
- Floats(new APFloat[2]{APFloat(semIEEEdouble, uninitialized),
- APFloat(semIEEEdouble, uninitialized)}) {
- assert(Semantics == &semPPCDoubleDouble);
-}
-
-DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, integerPart I)
- : Semantics(&S), Floats(new APFloat[2]{APFloat(semIEEEdouble, I),
- APFloat(semIEEEdouble)}) {
- assert(Semantics == &semPPCDoubleDouble);
-}
-
-DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, const APInt &I)
- : Semantics(&S),
- Floats(new APFloat[2]{
- APFloat(semIEEEdouble, APInt(64, I.getRawData()[0])),
- APFloat(semIEEEdouble, APInt(64, I.getRawData()[1]))}) {
- assert(Semantics == &semPPCDoubleDouble);
-}
-
-DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, APFloat &&First,
- APFloat &&Second)
- : Semantics(&S),
- Floats(new APFloat[2]{std::move(First), std::move(Second)}) {
- assert(Semantics == &semPPCDoubleDouble);
- assert(&Floats[0].getSemantics() == &semIEEEdouble);
- assert(&Floats[1].getSemantics() == &semIEEEdouble);
-}
-
-DoubleAPFloat::DoubleAPFloat(const DoubleAPFloat &RHS)
- : Semantics(RHS.Semantics),
- Floats(RHS.Floats ? new APFloat[2]{APFloat(RHS.Floats[0]),
- APFloat(RHS.Floats[1])}
- : nullptr) {
- assert(Semantics == &semPPCDoubleDouble);
-}
-
-DoubleAPFloat::DoubleAPFloat(DoubleAPFloat &&RHS)
- : Semantics(RHS.Semantics), Floats(std::move(RHS.Floats)) {
- RHS.Semantics = &semBogus;
- assert(Semantics == &semPPCDoubleDouble);
-}
-
-DoubleAPFloat &DoubleAPFloat::operator=(const DoubleAPFloat &RHS) {
- if (Semantics == RHS.Semantics && RHS.Floats) {
- Floats[0] = RHS.Floats[0];
- Floats[1] = RHS.Floats[1];
- } else if (this != &RHS) {
- this->~DoubleAPFloat();
- new (this) DoubleAPFloat(RHS);
- }
- return *this;
-}
-
-// Implement addition, subtraction, multiplication and division based on:
-// "Software for Doubled-Precision Floating-Point Computations",
-// by Seppo Linnainmaa, ACM TOMS vol 7 no 3, September 1981, pages 272-283.
-APFloat::opStatus DoubleAPFloat::addImpl(const APFloat &a, const APFloat &aa,
- const APFloat &c, const APFloat &cc,
- roundingMode RM) {
- int Status = opOK;
- APFloat z = a;
- Status |= z.add(c, RM);
- if (!z.isFinite()) {
- if (!z.isInfinity()) {
- Floats[0] = std::move(z);
- Floats[1].makeZero(/* Neg = */ false);
- return (opStatus)Status;
- }
- Status = opOK;
- auto AComparedToC = a.compareAbsoluteValue(c);
- z = cc;
- Status |= z.add(aa, RM);
- if (AComparedToC == APFloat::cmpGreaterThan) {
- // z = cc + aa + c + a;
- Status |= z.add(c, RM);
- Status |= z.add(a, RM);
- } else {
- // z = cc + aa + a + c;
- Status |= z.add(a, RM);
- Status |= z.add(c, RM);
- }
- if (!z.isFinite()) {
- Floats[0] = std::move(z);
- Floats[1].makeZero(/* Neg = */ false);
- return (opStatus)Status;
- }
- Floats[0] = z;
- APFloat zz = aa;
- Status |= zz.add(cc, RM);
- if (AComparedToC == APFloat::cmpGreaterThan) {
- // Floats[1] = a - z + c + zz;
- Floats[1] = a;
- Status |= Floats[1].subtract(z, RM);
- Status |= Floats[1].add(c, RM);
- Status |= Floats[1].add(zz, RM);
- } else {
- // Floats[1] = c - z + a + zz;
- Floats[1] = c;
- Status |= Floats[1].subtract(z, RM);
- Status |= Floats[1].add(a, RM);
- Status |= Floats[1].add(zz, RM);
- }
- } else {
- // q = a - z;
- APFloat q = a;
- Status |= q.subtract(z, RM);
-
- // zz = q + c + (a - (q + z)) + aa + cc;
- // Compute a - (q + z) as -((q + z) - a) to avoid temporary copies.
- auto zz = q;
- Status |= zz.add(c, RM);
- Status |= q.add(z, RM);
- Status |= q.subtract(a, RM);
- q.changeSign();
- Status |= zz.add(q, RM);
- Status |= zz.add(aa, RM);
- Status |= zz.add(cc, RM);
- if (zz.isZero() && !zz.isNegative()) {
- Floats[0] = std::move(z);
- Floats[1].makeZero(/* Neg = */ false);
- return opOK;
- }
- Floats[0] = z;
- Status |= Floats[0].add(zz, RM);
- if (!Floats[0].isFinite()) {
- Floats[1].makeZero(/* Neg = */ false);
- return (opStatus)Status;
- }
- Floats[1] = std::move(z);
- Status |= Floats[1].subtract(Floats[0], RM);
- Status |= Floats[1].add(zz, RM);
- }
- return (opStatus)Status;
-}
-
-APFloat::opStatus DoubleAPFloat::addWithSpecial(const DoubleAPFloat &LHS,
- const DoubleAPFloat &RHS,
- DoubleAPFloat &Out,
- roundingMode RM) {
- if (LHS.getCategory() == fcNaN) {
- Out = LHS;
- return opOK;
- }
- if (RHS.getCategory() == fcNaN) {
- Out = RHS;
- return opOK;
- }
- if (LHS.getCategory() == fcZero) {
- Out = RHS;
- return opOK;
- }
- if (RHS.getCategory() == fcZero) {
- Out = LHS;
- return opOK;
- }
- if (LHS.getCategory() == fcInfinity && RHS.getCategory() == fcInfinity &&
- LHS.isNegative() != RHS.isNegative()) {
- Out.makeNaN(false, Out.isNegative(), nullptr);
- return opInvalidOp;
- }
- if (LHS.getCategory() == fcInfinity) {
- Out = LHS;
- return opOK;
- }
- if (RHS.getCategory() == fcInfinity) {
- Out = RHS;
- return opOK;
- }
- assert(LHS.getCategory() == fcNormal && RHS.getCategory() == fcNormal);
-
- APFloat A(LHS.Floats[0]), AA(LHS.Floats[1]), C(RHS.Floats[0]),
- CC(RHS.Floats[1]);
- assert(&A.getSemantics() == &semIEEEdouble);
- assert(&AA.getSemantics() == &semIEEEdouble);
- assert(&C.getSemantics() == &semIEEEdouble);
- assert(&CC.getSemantics() == &semIEEEdouble);
- assert(&Out.Floats[0].getSemantics() == &semIEEEdouble);
- assert(&Out.Floats[1].getSemantics() == &semIEEEdouble);
- return Out.addImpl(A, AA, C, CC, RM);
-}
-
-APFloat::opStatus DoubleAPFloat::add(const DoubleAPFloat &RHS,
- roundingMode RM) {
- return addWithSpecial(*this, RHS, *this, RM);
-}
-
-APFloat::opStatus DoubleAPFloat::subtract(const DoubleAPFloat &RHS,
- roundingMode RM) {
- changeSign();
- auto Ret = add(RHS, RM);
- changeSign();
- return Ret;
-}
-
-APFloat::opStatus DoubleAPFloat::multiply(const DoubleAPFloat &RHS,
- APFloat::roundingMode RM) {
- const auto &LHS = *this;
- auto &Out = *this;
- /* Interesting observation: For special categories, finding the lowest
- common ancestor of the following layered graph gives the correct
- return category:
-
- NaN
- / \
- Zero Inf
- \ /
- Normal
-
- e.g. NaN * NaN = NaN
- Zero * Inf = NaN
- Normal * Zero = Zero
- Normal * Inf = Inf
- */
- if (LHS.getCategory() == fcNaN) {
- Out = LHS;
- return opOK;
- }
- if (RHS.getCategory() == fcNaN) {
- Out = RHS;
- return opOK;
- }
- if ((LHS.getCategory() == fcZero && RHS.getCategory() == fcInfinity) ||
- (LHS.getCategory() == fcInfinity && RHS.getCategory() == fcZero)) {
- Out.makeNaN(false, false, nullptr);
- return opOK;
- }
- if (LHS.getCategory() == fcZero || LHS.getCategory() == fcInfinity) {
- Out = LHS;
- return opOK;
- }
- if (RHS.getCategory() == fcZero || RHS.getCategory() == fcInfinity) {
- Out = RHS;
- return opOK;
- }
- assert(LHS.getCategory() == fcNormal && RHS.getCategory() == fcNormal &&
- "Special cases not handled exhaustively");
-
- int Status = opOK;
- APFloat A = Floats[0], B = Floats[1], C = RHS.Floats[0], D = RHS.Floats[1];
- // t = a * c
- APFloat T = A;
- Status |= T.multiply(C, RM);
- if (!T.isFiniteNonZero()) {
- Floats[0] = T;
- Floats[1].makeZero(/* Neg = */ false);
- return (opStatus)Status;
- }
-
- // tau = fmsub(a, c, t), that is -fmadd(-a, c, t).
- APFloat Tau = A;
- T.changeSign();
- Status |= Tau.fusedMultiplyAdd(C, T, RM);
- T.changeSign();
- {
- // v = a * d
- APFloat V = A;
- Status |= V.multiply(D, RM);
- // w = b * c
- APFloat W = B;
- Status |= W.multiply(C, RM);
- Status |= V.add(W, RM);
- // tau += v + w
- Status |= Tau.add(V, RM);
- }
- // u = t + tau
- APFloat U = T;
- Status |= U.add(Tau, RM);
-
- Floats[0] = U;
- if (!U.isFinite()) {
- Floats[1].makeZero(/* Neg = */ false);
- } else {
- // Floats[1] = (t - u) + tau
- Status |= T.subtract(U, RM);
- Status |= T.add(Tau, RM);
- Floats[1] = T;
- }
- return (opStatus)Status;
-}
-
-APFloat::opStatus DoubleAPFloat::divide(const DoubleAPFloat &RHS,
- APFloat::roundingMode RM) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
- auto Ret =
- Tmp.divide(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()), RM);
- *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
- return Ret;
-}
-
-APFloat::opStatus DoubleAPFloat::remainder(const DoubleAPFloat &RHS) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
- auto Ret =
- Tmp.remainder(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()));
- *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
- return Ret;
-}
-
-APFloat::opStatus DoubleAPFloat::mod(const DoubleAPFloat &RHS) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
- auto Ret = Tmp.mod(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()));
- *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
- return Ret;
-}
-
-APFloat::opStatus
-DoubleAPFloat::fusedMultiplyAdd(const DoubleAPFloat &Multiplicand,
- const DoubleAPFloat &Addend,
- APFloat::roundingMode RM) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
- auto Ret = Tmp.fusedMultiplyAdd(
- APFloat(semPPCDoubleDoubleLegacy, Multiplicand.bitcastToAPInt()),
- APFloat(semPPCDoubleDoubleLegacy, Addend.bitcastToAPInt()), RM);
- *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
- return Ret;
-}
-
-APFloat::opStatus DoubleAPFloat::roundToIntegral(APFloat::roundingMode RM) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
- auto Ret = Tmp.roundToIntegral(RM);
- *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
- return Ret;
-}
-
-void DoubleAPFloat::changeSign() {
- Floats[0].changeSign();
- Floats[1].changeSign();
-}
-
-APFloat::cmpResult
-DoubleAPFloat::compareAbsoluteValue(const DoubleAPFloat &RHS) const {
- auto Result = Floats[0].compareAbsoluteValue(RHS.Floats[0]);
- if (Result != cmpEqual)
- return Result;
- Result = Floats[1].compareAbsoluteValue(RHS.Floats[1]);
- if (Result == cmpLessThan || Result == cmpGreaterThan) {
- auto Against = Floats[0].isNegative() ^ Floats[1].isNegative();
- auto RHSAgainst = RHS.Floats[0].isNegative() ^ RHS.Floats[1].isNegative();
- if (Against && !RHSAgainst)
- return cmpLessThan;
- if (!Against && RHSAgainst)
- return cmpGreaterThan;
- if (!Against && !RHSAgainst)
- return Result;
- if (Against && RHSAgainst)
- return (cmpResult)(cmpLessThan + cmpGreaterThan - Result);
- }
- return Result;
-}
-
-APFloat::fltCategory DoubleAPFloat::getCategory() const {
- return Floats[0].getCategory();
-}
-
-bool DoubleAPFloat::isNegative() const { return Floats[0].isNegative(); }
-
-void DoubleAPFloat::makeInf(bool Neg) {
- Floats[0].makeInf(Neg);
- Floats[1].makeZero(/* Neg = */ false);
-}
-
-void DoubleAPFloat::makeZero(bool Neg) {
- Floats[0].makeZero(Neg);
- Floats[1].makeZero(/* Neg = */ false);
-}
-
-void DoubleAPFloat::makeLargest(bool Neg) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- Floats[0] = APFloat(semIEEEdouble, APInt(64, 0x7fefffffffffffffull));
- Floats[1] = APFloat(semIEEEdouble, APInt(64, 0x7c8ffffffffffffeull));
- if (Neg)
- changeSign();
-}
-
-void DoubleAPFloat::makeSmallest(bool Neg) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- Floats[0].makeSmallest(Neg);
- Floats[1].makeZero(/* Neg = */ false);
-}
-
-void DoubleAPFloat::makeSmallestNormalized(bool Neg) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- Floats[0] = APFloat(semIEEEdouble, APInt(64, 0x0360000000000000ull));
- if (Neg)
- Floats[0].changeSign();
- Floats[1].makeZero(/* Neg = */ false);
-}
-
-void DoubleAPFloat::makeNaN(bool SNaN, bool Neg, const APInt *fill) {
- Floats[0].makeNaN(SNaN, Neg, fill);
- Floats[1].makeZero(/* Neg = */ false);
-}
-
-APFloat::cmpResult DoubleAPFloat::compare(const DoubleAPFloat &RHS) const {
- auto Result = Floats[0].compare(RHS.Floats[0]);
- // |Float[0]| > |Float[1]|
- if (Result == APFloat::cmpEqual)
- return Floats[1].compare(RHS.Floats[1]);
- return Result;
-}
-
-bool DoubleAPFloat::bitwiseIsEqual(const DoubleAPFloat &RHS) const {
- return Floats[0].bitwiseIsEqual(RHS.Floats[0]) &&
- Floats[1].bitwiseIsEqual(RHS.Floats[1]);
-}
-
-hash_code hash_value(const DoubleAPFloat &Arg) {
- if (Arg.Floats)
- return hash_combine(hash_value(Arg.Floats[0]), hash_value(Arg.Floats[1]));
- return hash_combine(Arg.Semantics);
-}
-
-APInt DoubleAPFloat::bitcastToAPInt() const {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- uint64_t Data[] = {
- Floats[0].bitcastToAPInt().getRawData()[0],
- Floats[1].bitcastToAPInt().getRawData()[0],
- };
- return APInt(128, 2, Data);
-}
-
-APFloat::opStatus DoubleAPFloat::convertFromString(StringRef S,
- roundingMode RM) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat Tmp(semPPCDoubleDoubleLegacy);
- auto Ret = Tmp.convertFromString(S, RM);
- *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
- return Ret;
-}
-
-APFloat::opStatus DoubleAPFloat::next(bool nextDown) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
- auto Ret = Tmp.next(nextDown);
- *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
- return Ret;
-}
-
-APFloat::opStatus
-DoubleAPFloat::convertToInteger(MutableArrayRef<integerPart> Input,
- unsigned int Width, bool IsSigned,
- roundingMode RM, bool *IsExact) const {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- return APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt())
- .convertToInteger(Input, Width, IsSigned, RM, IsExact);
-}
-
-APFloat::opStatus DoubleAPFloat::convertFromAPInt(const APInt &Input,
- bool IsSigned,
- roundingMode RM) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat Tmp(semPPCDoubleDoubleLegacy);
- auto Ret = Tmp.convertFromAPInt(Input, IsSigned, RM);
- *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
- return Ret;
-}
-
-APFloat::opStatus
-DoubleAPFloat::convertFromSignExtendedInteger(const integerPart *Input,
- unsigned int InputSize,
- bool IsSigned, roundingMode RM) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat Tmp(semPPCDoubleDoubleLegacy);
- auto Ret = Tmp.convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM);
- *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
- return Ret;
-}
-
-APFloat::opStatus
-DoubleAPFloat::convertFromZeroExtendedInteger(const integerPart *Input,
- unsigned int InputSize,
- bool IsSigned, roundingMode RM) {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat Tmp(semPPCDoubleDoubleLegacy);
- auto Ret = Tmp.convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM);
- *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
- return Ret;
-}
-
-unsigned int DoubleAPFloat::convertToHexString(char *DST,
- unsigned int HexDigits,
- bool UpperCase,
- roundingMode RM) const {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- return APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt())
- .convertToHexString(DST, HexDigits, UpperCase, RM);
-}
-
-bool DoubleAPFloat::isDenormal() const {
- return getCategory() == fcNormal &&
- (Floats[0].isDenormal() || Floats[1].isDenormal() ||
- // (double)(Hi + Lo) == Hi defines a normal number.
- Floats[0].compare(Floats[0] + Floats[1]) != cmpEqual);
-}
-
-bool DoubleAPFloat::isSmallest() const {
- if (getCategory() != fcNormal)
- return false;
- DoubleAPFloat Tmp(*this);
- Tmp.makeSmallest(this->isNegative());
- return Tmp.compare(*this) == cmpEqual;
-}
-
-bool DoubleAPFloat::isLargest() const {
- if (getCategory() != fcNormal)
- return false;
- DoubleAPFloat Tmp(*this);
- Tmp.makeLargest(this->isNegative());
- return Tmp.compare(*this) == cmpEqual;
-}
-
-bool DoubleAPFloat::isInteger() const {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- return Floats[0].isInteger() && Floats[1].isInteger();
-}
-
-void DoubleAPFloat::toString(SmallVectorImpl<char> &Str,
- unsigned FormatPrecision,
- unsigned FormatMaxPadding,
- bool TruncateZero) const {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt())
- .toString(Str, FormatPrecision, FormatMaxPadding, TruncateZero);
-}
-
-bool DoubleAPFloat::getExactInverse(APFloat *inv) const {
- assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
- if (!inv)
- return Tmp.getExactInverse(nullptr);
- APFloat Inv(semPPCDoubleDoubleLegacy);
- auto Ret = Tmp.getExactInverse(&Inv);
- *inv = APFloat(semPPCDoubleDouble, Inv.bitcastToAPInt());
- return Ret;
-}
-
-DoubleAPFloat scalbn(DoubleAPFloat Arg, int Exp, APFloat::roundingMode RM) {
- assert(Arg.Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- return DoubleAPFloat(semPPCDoubleDouble, scalbn(Arg.Floats[0], Exp, RM),
- scalbn(Arg.Floats[1], Exp, RM));
-}
-
-DoubleAPFloat frexp(const DoubleAPFloat &Arg, int &Exp,
- APFloat::roundingMode RM) {
- assert(Arg.Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
- APFloat First = frexp(Arg.Floats[0], Exp, RM);
- APFloat Second = Arg.Floats[1];
- if (Arg.getCategory() == APFloat::fcNormal)
- Second = scalbn(Second, -Exp, RM);
- return DoubleAPFloat(semPPCDoubleDouble, std::move(First), std::move(Second));
-}
-
-} // End detail namespace
-
-APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) {
- if (usesLayout<IEEEFloat>(Semantics)) {
- new (&IEEE) IEEEFloat(std::move(F));
- return;
- }
- if (usesLayout<DoubleAPFloat>(Semantics)) {
- new (&Double)
- DoubleAPFloat(Semantics, APFloat(std::move(F), F.getSemantics()),
- APFloat(semIEEEdouble));
- return;
- }
- llvm_unreachable("Unexpected semantics");
-}
-
-APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) {
- APFLOAT_DISPATCH_ON_SEMANTICS(convertFromString(Str, RM));
-}
-
-hash_code hash_value(const APFloat &Arg) {
- if (APFloat::usesLayout<detail::IEEEFloat>(Arg.getSemantics()))
- return hash_value(Arg.U.IEEE);
- if (APFloat::usesLayout<detail::DoubleAPFloat>(Arg.getSemantics()))
- return hash_value(Arg.U.Double);
- llvm_unreachable("Unexpected semantics");
-}
-
-APFloat::APFloat(const fltSemantics &Semantics, StringRef S)
- : APFloat(Semantics) {
- convertFromString(S, rmNearestTiesToEven);
-}
-
-APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics,
- roundingMode RM, bool *losesInfo) {
- if (&getSemantics() == &ToSemantics) {
- *losesInfo = false;
- return opOK;
- }
- if (usesLayout<IEEEFloat>(getSemantics()) &&
- usesLayout<IEEEFloat>(ToSemantics))
- return U.IEEE.convert(ToSemantics, RM, losesInfo);
- if (usesLayout<IEEEFloat>(getSemantics()) &&
- usesLayout<DoubleAPFloat>(ToSemantics)) {
- assert(&ToSemantics == &semPPCDoubleDouble);
- auto Ret = U.IEEE.convert(semPPCDoubleDoubleLegacy, RM, losesInfo);
- *this = APFloat(ToSemantics, U.IEEE.bitcastToAPInt());
- return Ret;
- }
- if (usesLayout<DoubleAPFloat>(getSemantics()) &&
- usesLayout<IEEEFloat>(ToSemantics)) {
- auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo);
- *this = APFloat(std::move(getIEEE()), ToSemantics);
- return Ret;
- }
- llvm_unreachable("Unexpected semantics");
-}
-
-APFloat APFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) {
- if (isIEEE) {
- switch (BitWidth) {
- case 16:
- return APFloat(semIEEEhalf, APInt::getAllOnesValue(BitWidth));
- case 32:
- return APFloat(semIEEEsingle, APInt::getAllOnesValue(BitWidth));
- case 64:
- return APFloat(semIEEEdouble, APInt::getAllOnesValue(BitWidth));
- case 80:
- return APFloat(semX87DoubleExtended, APInt::getAllOnesValue(BitWidth));
- case 128:
- return APFloat(semIEEEquad, APInt::getAllOnesValue(BitWidth));
- default:
- llvm_unreachable("Unknown floating bit width");
- }
- } else {
- assert(BitWidth == 128);
- return APFloat(semPPCDoubleDouble, APInt::getAllOnesValue(BitWidth));
- }
-}
-
-void APFloat::print(raw_ostream &OS) const {
- SmallVector<char, 16> Buffer;
- toString(Buffer);
- OS << Buffer << "\n";
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void APFloat::dump() const { print(dbgs()); }
-#endif
-
-void APFloat::Profile(FoldingSetNodeID &NID) const {
- NID.Add(bitcastToAPInt());
-}
-
-/* Same as convertToInteger(integerPart*, ...), except the result is returned in
- an APSInt, whose initial bit-width and signed-ness are used to determine the
- precision of the conversion.
- */
-APFloat::opStatus APFloat::convertToInteger(APSInt &result,
- roundingMode rounding_mode,
- bool *isExact) const {
- unsigned bitWidth = result.getBitWidth();
- SmallVector<uint64_t, 4> parts(result.getNumWords());
- opStatus status = convertToInteger(parts, bitWidth, result.isSigned(),
- rounding_mode, isExact);
- // Keeps the original signed-ness.
- result = APInt(bitWidth, parts);
- return status;
-}
-
-} // End llvm namespace
-
-#undef APFLOAT_DISPATCH_ON_SEMANTICS
diff --git a/gnu/llvm/lib/Support/APInt.cpp b/gnu/llvm/lib/Support/APInt.cpp
deleted file mode 100644
index a5f4f98c489..00000000000
--- a/gnu/llvm/lib/Support/APInt.cpp
+++ /dev/null
@@ -1,2925 +0,0 @@
-//===-- APInt.cpp - Implement APInt class ---------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a class to represent arbitrary precision integer
-// constant values and provide a variety of arithmetic operations on them.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/bit.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include <climits>
-#include <cmath>
-#include <cstdlib>
-#include <cstring>
-using namespace llvm;
-
-#define DEBUG_TYPE "apint"
-
-/// A utility function for allocating memory, checking for allocation failures,
-/// and ensuring the contents are zeroed.
-inline static uint64_t* getClearedMemory(unsigned numWords) {
- uint64_t *result = new uint64_t[numWords];
- memset(result, 0, numWords * sizeof(uint64_t));
- return result;
-}
-
-/// A utility function for allocating memory and checking for allocation
-/// failure. The content is not zeroed.
-inline static uint64_t* getMemory(unsigned numWords) {
- return new uint64_t[numWords];
-}
-
-/// A utility function that converts a character to a digit.
-inline static unsigned getDigit(char cdigit, uint8_t radix) {
- unsigned r;
-
- if (radix == 16 || radix == 36) {
- r = cdigit - '0';
- if (r <= 9)
- return r;
-
- r = cdigit - 'A';
- if (r <= radix - 11U)
- return r + 10;
-
- r = cdigit - 'a';
- if (r <= radix - 11U)
- return r + 10;
-
- radix = 10;
- }
-
- r = cdigit - '0';
- if (r < radix)
- return r;
-
- return -1U;
-}
-
-
-void APInt::initSlowCase(uint64_t val, bool isSigned) {
- U.pVal = getClearedMemory(getNumWords());
- U.pVal[0] = val;
- if (isSigned && int64_t(val) < 0)
- for (unsigned i = 1; i < getNumWords(); ++i)
- U.pVal[i] = WORDTYPE_MAX;
- clearUnusedBits();
-}
-
-void APInt::initSlowCase(const APInt& that) {
- U.pVal = getMemory(getNumWords());
- memcpy(U.pVal, that.U.pVal, getNumWords() * APINT_WORD_SIZE);
-}
-
-void APInt::initFromArray(ArrayRef<uint64_t> bigVal) {
- assert(BitWidth && "Bitwidth too small");
- assert(bigVal.data() && "Null pointer detected!");
- if (isSingleWord())
- U.VAL = bigVal[0];
- else {
- // Get memory, cleared to 0
- U.pVal = getClearedMemory(getNumWords());
- // Calculate the number of words to copy
- unsigned words = std::min<unsigned>(bigVal.size(), getNumWords());
- // Copy the words from bigVal to pVal
- memcpy(U.pVal, bigVal.data(), words * APINT_WORD_SIZE);
- }
- // Make sure unused high bits are cleared
- clearUnusedBits();
-}
-
-APInt::APInt(unsigned numBits, ArrayRef<uint64_t> bigVal)
- : BitWidth(numBits) {
- initFromArray(bigVal);
-}
-
-APInt::APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[])
- : BitWidth(numBits) {
- initFromArray(makeArrayRef(bigVal, numWords));
-}
-
-APInt::APInt(unsigned numbits, StringRef Str, uint8_t radix)
- : BitWidth(numbits) {
- assert(BitWidth && "Bitwidth too small");
- fromString(numbits, Str, radix);
-}
-
-void APInt::reallocate(unsigned NewBitWidth) {
- // If the number of words is the same we can just change the width and stop.
- if (getNumWords() == getNumWords(NewBitWidth)) {
- BitWidth = NewBitWidth;
- return;
- }
-
- // If we have an allocation, delete it.
- if (!isSingleWord())
- delete [] U.pVal;
-
- // Update BitWidth.
- BitWidth = NewBitWidth;
-
- // If we are supposed to have an allocation, create it.
- if (!isSingleWord())
- U.pVal = getMemory(getNumWords());
-}
-
-void APInt::AssignSlowCase(const APInt& RHS) {
- // Don't do anything for X = X
- if (this == &RHS)
- return;
-
- // Adjust the bit width and handle allocations as necessary.
- reallocate(RHS.getBitWidth());
-
- // Copy the data.
- if (isSingleWord())
- U.VAL = RHS.U.VAL;
- else
- memcpy(U.pVal, RHS.U.pVal, getNumWords() * APINT_WORD_SIZE);
-}
-
-/// This method 'profiles' an APInt for use with FoldingSet.
-void APInt::Profile(FoldingSetNodeID& ID) const {
- ID.AddInteger(BitWidth);
-
- if (isSingleWord()) {
- ID.AddInteger(U.VAL);
- return;
- }
-
- unsigned NumWords = getNumWords();
- for (unsigned i = 0; i < NumWords; ++i)
- ID.AddInteger(U.pVal[i]);
-}
-
-/// Prefix increment operator. Increments the APInt by one.
-APInt& APInt::operator++() {
- if (isSingleWord())
- ++U.VAL;
- else
- tcIncrement(U.pVal, getNumWords());
- return clearUnusedBits();
-}
-
-/// Prefix decrement operator. Decrements the APInt by one.
-APInt& APInt::operator--() {
- if (isSingleWord())
- --U.VAL;
- else
- tcDecrement(U.pVal, getNumWords());
- return clearUnusedBits();
-}
-
-/// Adds the RHS APint to this APInt.
-/// @returns this, after addition of RHS.
-/// Addition assignment operator.
-APInt& APInt::operator+=(const APInt& RHS) {
- assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- if (isSingleWord())
- U.VAL += RHS.U.VAL;
- else
- tcAdd(U.pVal, RHS.U.pVal, 0, getNumWords());
- return clearUnusedBits();
-}
-
-APInt& APInt::operator+=(uint64_t RHS) {
- if (isSingleWord())
- U.VAL += RHS;
- else
- tcAddPart(U.pVal, RHS, getNumWords());
- return clearUnusedBits();
-}
-
-/// Subtracts the RHS APInt from this APInt
-/// @returns this, after subtraction
-/// Subtraction assignment operator.
-APInt& APInt::operator-=(const APInt& RHS) {
- assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- if (isSingleWord())
- U.VAL -= RHS.U.VAL;
- else
- tcSubtract(U.pVal, RHS.U.pVal, 0, getNumWords());
- return clearUnusedBits();
-}
-
-APInt& APInt::operator-=(uint64_t RHS) {
- if (isSingleWord())
- U.VAL -= RHS;
- else
- tcSubtractPart(U.pVal, RHS, getNumWords());
- return clearUnusedBits();
-}
-
-APInt APInt::operator*(const APInt& RHS) const {
- assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- if (isSingleWord())
- return APInt(BitWidth, U.VAL * RHS.U.VAL);
-
- APInt Result(getMemory(getNumWords()), getBitWidth());
-
- tcMultiply(Result.U.pVal, U.pVal, RHS.U.pVal, getNumWords());
-
- Result.clearUnusedBits();
- return Result;
-}
-
-void APInt::AndAssignSlowCase(const APInt& RHS) {
- tcAnd(U.pVal, RHS.U.pVal, getNumWords());
-}
-
-void APInt::OrAssignSlowCase(const APInt& RHS) {
- tcOr(U.pVal, RHS.U.pVal, getNumWords());
-}
-
-void APInt::XorAssignSlowCase(const APInt& RHS) {
- tcXor(U.pVal, RHS.U.pVal, getNumWords());
-}
-
-APInt& APInt::operator*=(const APInt& RHS) {
- assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- *this = *this * RHS;
- return *this;
-}
-
-APInt& APInt::operator*=(uint64_t RHS) {
- if (isSingleWord()) {
- U.VAL *= RHS;
- } else {
- unsigned NumWords = getNumWords();
- tcMultiplyPart(U.pVal, U.pVal, RHS, 0, NumWords, NumWords, false);
- }
- return clearUnusedBits();
-}
-
-bool APInt::EqualSlowCase(const APInt& RHS) const {
- return std::equal(U.pVal, U.pVal + getNumWords(), RHS.U.pVal);
-}
-
-int APInt::compare(const APInt& RHS) const {
- assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
- if (isSingleWord())
- return U.VAL < RHS.U.VAL ? -1 : U.VAL > RHS.U.VAL;
-
- return tcCompare(U.pVal, RHS.U.pVal, getNumWords());
-}
-
-int APInt::compareSigned(const APInt& RHS) const {
- assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
- if (isSingleWord()) {
- int64_t lhsSext = SignExtend64(U.VAL, BitWidth);
- int64_t rhsSext = SignExtend64(RHS.U.VAL, BitWidth);
- return lhsSext < rhsSext ? -1 : lhsSext > rhsSext;
- }
-
- bool lhsNeg = isNegative();
- bool rhsNeg = RHS.isNegative();
-
- // If the sign bits don't match, then (LHS < RHS) if LHS is negative
- if (lhsNeg != rhsNeg)
- return lhsNeg ? -1 : 1;
-
- // Otherwise we can just use an unsigned comparison, because even negative
- // numbers compare correctly this way if both have the same signed-ness.
- return tcCompare(U.pVal, RHS.U.pVal, getNumWords());
-}
-
-void APInt::setBitsSlowCase(unsigned loBit, unsigned hiBit) {
- unsigned loWord = whichWord(loBit);
- unsigned hiWord = whichWord(hiBit);
-
- // Create an initial mask for the low word with zeros below loBit.
- uint64_t loMask = WORDTYPE_MAX << whichBit(loBit);
-
- // If hiBit is not aligned, we need a high mask.
- unsigned hiShiftAmt = whichBit(hiBit);
- if (hiShiftAmt != 0) {
- // Create a high mask with zeros above hiBit.
- uint64_t hiMask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - hiShiftAmt);
- // If loWord and hiWord are equal, then we combine the masks. Otherwise,
- // set the bits in hiWord.
- if (hiWord == loWord)
- loMask &= hiMask;
- else
- U.pVal[hiWord] |= hiMask;
- }
- // Apply the mask to the low word.
- U.pVal[loWord] |= loMask;
-
- // Fill any words between loWord and hiWord with all ones.
- for (unsigned word = loWord + 1; word < hiWord; ++word)
- U.pVal[word] = WORDTYPE_MAX;
-}
-
-/// Toggle every bit to its opposite value.
-void APInt::flipAllBitsSlowCase() {
- tcComplement(U.pVal, getNumWords());
- clearUnusedBits();
-}
-
-/// Toggle a given bit to its opposite value whose position is given
-/// as "bitPosition".
-/// Toggles a given bit to its opposite value.
-void APInt::flipBit(unsigned bitPosition) {
- assert(bitPosition < BitWidth && "Out of the bit-width range!");
- if ((*this)[bitPosition]) clearBit(bitPosition);
- else setBit(bitPosition);
-}
-
-void APInt::insertBits(const APInt &subBits, unsigned bitPosition) {
- unsigned subBitWidth = subBits.getBitWidth();
- assert(0 < subBitWidth && (subBitWidth + bitPosition) <= BitWidth &&
- "Illegal bit insertion");
-
- // Insertion is a direct copy.
- if (subBitWidth == BitWidth) {
- *this = subBits;
- return;
- }
-
- // Single word result can be done as a direct bitmask.
- if (isSingleWord()) {
- uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - subBitWidth);
- U.VAL &= ~(mask << bitPosition);
- U.VAL |= (subBits.U.VAL << bitPosition);
- return;
- }
-
- unsigned loBit = whichBit(bitPosition);
- unsigned loWord = whichWord(bitPosition);
- unsigned hi1Word = whichWord(bitPosition + subBitWidth - 1);
-
- // Insertion within a single word can be done as a direct bitmask.
- if (loWord == hi1Word) {
- uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - subBitWidth);
- U.pVal[loWord] &= ~(mask << loBit);
- U.pVal[loWord] |= (subBits.U.VAL << loBit);
- return;
- }
-
- // Insert on word boundaries.
- if (loBit == 0) {
- // Direct copy whole words.
- unsigned numWholeSubWords = subBitWidth / APINT_BITS_PER_WORD;
- memcpy(U.pVal + loWord, subBits.getRawData(),
- numWholeSubWords * APINT_WORD_SIZE);
-
- // Mask+insert remaining bits.
- unsigned remainingBits = subBitWidth % APINT_BITS_PER_WORD;
- if (remainingBits != 0) {
- uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - remainingBits);
- U.pVal[hi1Word] &= ~mask;
- U.pVal[hi1Word] |= subBits.getWord(subBitWidth - 1);
- }
- return;
- }
-
- // General case - set/clear individual bits in dst based on src.
- // TODO - there is scope for optimization here, but at the moment this code
- // path is barely used so prefer readability over performance.
- for (unsigned i = 0; i != subBitWidth; ++i) {
- if (subBits[i])
- setBit(bitPosition + i);
- else
- clearBit(bitPosition + i);
- }
-}
-
-APInt APInt::extractBits(unsigned numBits, unsigned bitPosition) const {
- assert(numBits > 0 && "Can't extract zero bits");
- assert(bitPosition < BitWidth && (numBits + bitPosition) <= BitWidth &&
- "Illegal bit extraction");
-
- if (isSingleWord())
- return APInt(numBits, U.VAL >> bitPosition);
-
- unsigned loBit = whichBit(bitPosition);
- unsigned loWord = whichWord(bitPosition);
- unsigned hiWord = whichWord(bitPosition + numBits - 1);
-
- // Single word result extracting bits from a single word source.
- if (loWord == hiWord)
- return APInt(numBits, U.pVal[loWord] >> loBit);
-
- // Extracting bits that start on a source word boundary can be done
- // as a fast memory copy.
- if (loBit == 0)
- return APInt(numBits, makeArrayRef(U.pVal + loWord, 1 + hiWord - loWord));
-
- // General case - shift + copy source words directly into place.
- APInt Result(numBits, 0);
- unsigned NumSrcWords = getNumWords();
- unsigned NumDstWords = Result.getNumWords();
-
- uint64_t *DestPtr = Result.isSingleWord() ? &Result.U.VAL : Result.U.pVal;
- for (unsigned word = 0; word < NumDstWords; ++word) {
- uint64_t w0 = U.pVal[loWord + word];
- uint64_t w1 =
- (loWord + word + 1) < NumSrcWords ? U.pVal[loWord + word + 1] : 0;
- DestPtr[word] = (w0 >> loBit) | (w1 << (APINT_BITS_PER_WORD - loBit));
- }
-
- return Result.clearUnusedBits();
-}
-
-unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) {
- assert(!str.empty() && "Invalid string length");
- assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 ||
- radix == 36) &&
- "Radix should be 2, 8, 10, 16, or 36!");
-
- size_t slen = str.size();
-
- // Each computation below needs to know if it's negative.
- StringRef::iterator p = str.begin();
- unsigned isNegative = *p == '-';
- if (*p == '-' || *p == '+') {
- p++;
- slen--;
- assert(slen && "String is only a sign, needs a value.");
- }
-
- // For radixes of power-of-two values, the bits required is accurately and
- // easily computed
- if (radix == 2)
- return slen + isNegative;
- if (radix == 8)
- return slen * 3 + isNegative;
- if (radix == 16)
- return slen * 4 + isNegative;
-
- // FIXME: base 36
-
- // This is grossly inefficient but accurate. We could probably do something
- // with a computation of roughly slen*64/20 and then adjust by the value of
- // the first few digits. But, I'm not sure how accurate that could be.
-
- // Compute a sufficient number of bits that is always large enough but might
- // be too large. This avoids the assertion in the constructor. This
- // calculation doesn't work appropriately for the numbers 0-9, so just use 4
- // bits in that case.
- unsigned sufficient
- = radix == 10? (slen == 1 ? 4 : slen * 64/18)
- : (slen == 1 ? 7 : slen * 16/3);
-
- // Convert to the actual binary value.
- APInt tmp(sufficient, StringRef(p, slen), radix);
-
- // Compute how many bits are required. If the log is infinite, assume we need
- // just bit.
- unsigned log = tmp.logBase2();
- if (log == (unsigned)-1) {
- return isNegative + 1;
- } else {
- return isNegative + log + 1;
- }
-}
-
-hash_code llvm::hash_value(const APInt &Arg) {
- if (Arg.isSingleWord())
- return hash_combine(Arg.U.VAL);
-
- return hash_combine_range(Arg.U.pVal, Arg.U.pVal + Arg.getNumWords());
-}
-
-bool APInt::isSplat(unsigned SplatSizeInBits) const {
- assert(getBitWidth() % SplatSizeInBits == 0 &&
- "SplatSizeInBits must divide width!");
- // We can check that all parts of an integer are equal by making use of a
- // little trick: rotate and check if it's still the same value.
- return *this == rotl(SplatSizeInBits);
-}
-
-/// This function returns the high "numBits" bits of this APInt.
-APInt APInt::getHiBits(unsigned numBits) const {
- return this->lshr(BitWidth - numBits);
-}
-
-/// This function returns the low "numBits" bits of this APInt.
-APInt APInt::getLoBits(unsigned numBits) const {
- APInt Result(getLowBitsSet(BitWidth, numBits));
- Result &= *this;
- return Result;
-}
-
-/// Return a value containing V broadcasted over NewLen bits.
-APInt APInt::getSplat(unsigned NewLen, const APInt &V) {
- assert(NewLen >= V.getBitWidth() && "Can't splat to smaller bit width!");
-
- APInt Val = V.zextOrSelf(NewLen);
- for (unsigned I = V.getBitWidth(); I < NewLen; I <<= 1)
- Val |= Val << I;
-
- return Val;
-}
-
-unsigned APInt::countLeadingZerosSlowCase() const {
- unsigned Count = 0;
- for (int i = getNumWords()-1; i >= 0; --i) {
- uint64_t V = U.pVal[i];
- if (V == 0)
- Count += APINT_BITS_PER_WORD;
- else {
- Count += llvm::countLeadingZeros(V);
- break;
- }
- }
- // Adjust for unused bits in the most significant word (they are zero).
- unsigned Mod = BitWidth % APINT_BITS_PER_WORD;
- Count -= Mod > 0 ? APINT_BITS_PER_WORD - Mod : 0;
- return Count;
-}
-
-unsigned APInt::countLeadingOnesSlowCase() const {
- unsigned highWordBits = BitWidth % APINT_BITS_PER_WORD;
- unsigned shift;
- if (!highWordBits) {
- highWordBits = APINT_BITS_PER_WORD;
- shift = 0;
- } else {
- shift = APINT_BITS_PER_WORD - highWordBits;
- }
- int i = getNumWords() - 1;
- unsigned Count = llvm::countLeadingOnes(U.pVal[i] << shift);
- if (Count == highWordBits) {
- for (i--; i >= 0; --i) {
- if (U.pVal[i] == WORDTYPE_MAX)
- Count += APINT_BITS_PER_WORD;
- else {
- Count += llvm::countLeadingOnes(U.pVal[i]);
- break;
- }
- }
- }
- return Count;
-}
-
-unsigned APInt::countTrailingZerosSlowCase() const {
- unsigned Count = 0;
- unsigned i = 0;
- for (; i < getNumWords() && U.pVal[i] == 0; ++i)
- Count += APINT_BITS_PER_WORD;
- if (i < getNumWords())
- Count += llvm::countTrailingZeros(U.pVal[i]);
- return std::min(Count, BitWidth);
-}
-
-unsigned APInt::countTrailingOnesSlowCase() const {
- unsigned Count = 0;
- unsigned i = 0;
- for (; i < getNumWords() && U.pVal[i] == WORDTYPE_MAX; ++i)
- Count += APINT_BITS_PER_WORD;
- if (i < getNumWords())
- Count += llvm::countTrailingOnes(U.pVal[i]);
- assert(Count <= BitWidth);
- return Count;
-}
-
-unsigned APInt::countPopulationSlowCase() const {
- unsigned Count = 0;
- for (unsigned i = 0; i < getNumWords(); ++i)
- Count += llvm::countPopulation(U.pVal[i]);
- return Count;
-}
-
-bool APInt::intersectsSlowCase(const APInt &RHS) const {
- for (unsigned i = 0, e = getNumWords(); i != e; ++i)
- if ((U.pVal[i] & RHS.U.pVal[i]) != 0)
- return true;
-
- return false;
-}
-
-bool APInt::isSubsetOfSlowCase(const APInt &RHS) const {
- for (unsigned i = 0, e = getNumWords(); i != e; ++i)
- if ((U.pVal[i] & ~RHS.U.pVal[i]) != 0)
- return false;
-
- return true;
-}
-
-APInt APInt::byteSwap() const {
- assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!");
- if (BitWidth == 16)
- return APInt(BitWidth, ByteSwap_16(uint16_t(U.VAL)));
- if (BitWidth == 32)
- return APInt(BitWidth, ByteSwap_32(unsigned(U.VAL)));
- if (BitWidth == 48) {
- unsigned Tmp1 = unsigned(U.VAL >> 16);
- Tmp1 = ByteSwap_32(Tmp1);
- uint16_t Tmp2 = uint16_t(U.VAL);
- Tmp2 = ByteSwap_16(Tmp2);
- return APInt(BitWidth, (uint64_t(Tmp2) << 32) | Tmp1);
- }
- if (BitWidth == 64)
- return APInt(BitWidth, ByteSwap_64(U.VAL));
-
- APInt Result(getNumWords() * APINT_BITS_PER_WORD, 0);
- for (unsigned I = 0, N = getNumWords(); I != N; ++I)
- Result.U.pVal[I] = ByteSwap_64(U.pVal[N - I - 1]);
- if (Result.BitWidth != BitWidth) {
- Result.lshrInPlace(Result.BitWidth - BitWidth);
- Result.BitWidth = BitWidth;
- }
- return Result;
-}
-
-APInt APInt::reverseBits() const {
- switch (BitWidth) {
- case 64:
- return APInt(BitWidth, llvm::reverseBits<uint64_t>(U.VAL));
- case 32:
- return APInt(BitWidth, llvm::reverseBits<uint32_t>(U.VAL));
- case 16:
- return APInt(BitWidth, llvm::reverseBits<uint16_t>(U.VAL));
- case 8:
- return APInt(BitWidth, llvm::reverseBits<uint8_t>(U.VAL));
- default:
- break;
- }
-
- APInt Val(*this);
- APInt Reversed(BitWidth, 0);
- unsigned S = BitWidth;
-
- for (; Val != 0; Val.lshrInPlace(1)) {
- Reversed <<= 1;
- Reversed |= Val[0];
- --S;
- }
-
- Reversed <<= S;
- return Reversed;
-}
-
-APInt llvm::APIntOps::GreatestCommonDivisor(APInt A, APInt B) {
- // Fast-path a common case.
- if (A == B) return A;
-
- // Corner cases: if either operand is zero, the other is the gcd.
- if (!A) return B;
- if (!B) return A;
-
- // Count common powers of 2 and remove all other powers of 2.
- unsigned Pow2;
- {
- unsigned Pow2_A = A.countTrailingZeros();
- unsigned Pow2_B = B.countTrailingZeros();
- if (Pow2_A > Pow2_B) {
- A.lshrInPlace(Pow2_A - Pow2_B);
- Pow2 = Pow2_B;
- } else if (Pow2_B > Pow2_A) {
- B.lshrInPlace(Pow2_B - Pow2_A);
- Pow2 = Pow2_A;
- } else {
- Pow2 = Pow2_A;
- }
- }
-
- // Both operands are odd multiples of 2^Pow_2:
- //
- // gcd(a, b) = gcd(|a - b| / 2^i, min(a, b))
- //
- // This is a modified version of Stein's algorithm, taking advantage of
- // efficient countTrailingZeros().
- while (A != B) {
- if (A.ugt(B)) {
- A -= B;
- A.lshrInPlace(A.countTrailingZeros() - Pow2);
- } else {
- B -= A;
- B.lshrInPlace(B.countTrailingZeros() - Pow2);
- }
- }
-
- return A;
-}
-
-APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) {
- uint64_t I = bit_cast<uint64_t>(Double);
-
- // Get the sign bit from the highest order bit
- bool isNeg = I >> 63;
-
- // Get the 11-bit exponent and adjust for the 1023 bit bias
- int64_t exp = ((I >> 52) & 0x7ff) - 1023;
-
- // If the exponent is negative, the value is < 0 so just return 0.
- if (exp < 0)
- return APInt(width, 0u);
-
- // Extract the mantissa by clearing the top 12 bits (sign + exponent).
- uint64_t mantissa = (I & (~0ULL >> 12)) | 1ULL << 52;
-
- // If the exponent doesn't shift all bits out of the mantissa
- if (exp < 52)
- return isNeg ? -APInt(width, mantissa >> (52 - exp)) :
- APInt(width, mantissa >> (52 - exp));
-
- // If the client didn't provide enough bits for us to shift the mantissa into
- // then the result is undefined, just return 0
- if (width <= exp - 52)
- return APInt(width, 0);
-
- // Otherwise, we have to shift the mantissa bits up to the right location
- APInt Tmp(width, mantissa);
- Tmp <<= (unsigned)exp - 52;
- return isNeg ? -Tmp : Tmp;
-}
-
-/// This function converts this APInt to a double.
-/// The layout for double is as following (IEEE Standard 754):
-/// --------------------------------------
-/// | Sign Exponent Fraction Bias |
-/// |-------------------------------------- |
-/// | 1[63] 11[62-52] 52[51-00] 1023 |
-/// --------------------------------------
-double APInt::roundToDouble(bool isSigned) const {
-
- // Handle the simple case where the value is contained in one uint64_t.
- // It is wrong to optimize getWord(0) to VAL; there might be more than one word.
- if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) {
- if (isSigned) {
- int64_t sext = SignExtend64(getWord(0), BitWidth);
- return double(sext);
- } else
- return double(getWord(0));
- }
-
- // Determine if the value is negative.
- bool isNeg = isSigned ? (*this)[BitWidth-1] : false;
-
- // Construct the absolute value if we're negative.
- APInt Tmp(isNeg ? -(*this) : (*this));
-
- // Figure out how many bits we're using.
- unsigned n = Tmp.getActiveBits();
-
- // The exponent (without bias normalization) is just the number of bits
- // we are using. Note that the sign bit is gone since we constructed the
- // absolute value.
- uint64_t exp = n;
-
- // Return infinity for exponent overflow
- if (exp > 1023) {
- if (!isSigned || !isNeg)
- return std::numeric_limits<double>::infinity();
- else
- return -std::numeric_limits<double>::infinity();
- }
- exp += 1023; // Increment for 1023 bias
-
- // Number of bits in mantissa is 52. To obtain the mantissa value, we must
- // extract the high 52 bits from the correct words in pVal.
- uint64_t mantissa;
- unsigned hiWord = whichWord(n-1);
- if (hiWord == 0) {
- mantissa = Tmp.U.pVal[0];
- if (n > 52)
- mantissa >>= n - 52; // shift down, we want the top 52 bits.
- } else {
- assert(hiWord > 0 && "huh?");
- uint64_t hibits = Tmp.U.pVal[hiWord] << (52 - n % APINT_BITS_PER_WORD);
- uint64_t lobits = Tmp.U.pVal[hiWord-1] >> (11 + n % APINT_BITS_PER_WORD);
- mantissa = hibits | lobits;
- }
-
- // The leading bit of mantissa is implicit, so get rid of it.
- uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0;
- uint64_t I = sign | (exp << 52) | mantissa;
- return bit_cast<double>(I);
-}
-
-// Truncate to new width.
-APInt APInt::trunc(unsigned width) const {
- assert(width < BitWidth && "Invalid APInt Truncate request");
- assert(width && "Can't truncate to 0 bits");
-
- if (width <= APINT_BITS_PER_WORD)
- return APInt(width, getRawData()[0]);
-
- APInt Result(getMemory(getNumWords(width)), width);
-
- // Copy full words.
- unsigned i;
- for (i = 0; i != width / APINT_BITS_PER_WORD; i++)
- Result.U.pVal[i] = U.pVal[i];
-
- // Truncate and copy any partial word.
- unsigned bits = (0 - width) % APINT_BITS_PER_WORD;
- if (bits != 0)
- Result.U.pVal[i] = U.pVal[i] << bits >> bits;
-
- return Result;
-}
-
-// Sign extend to a new width.
-APInt APInt::sext(unsigned Width) const {
- assert(Width > BitWidth && "Invalid APInt SignExtend request");
-
- if (Width <= APINT_BITS_PER_WORD)
- return APInt(Width, SignExtend64(U.VAL, BitWidth));
-
- APInt Result(getMemory(getNumWords(Width)), Width);
-
- // Copy words.
- std::memcpy(Result.U.pVal, getRawData(), getNumWords() * APINT_WORD_SIZE);
-
- // Sign extend the last word since there may be unused bits in the input.
- Result.U.pVal[getNumWords() - 1] =
- SignExtend64(Result.U.pVal[getNumWords() - 1],
- ((BitWidth - 1) % APINT_BITS_PER_WORD) + 1);
-
- // Fill with sign bits.
- std::memset(Result.U.pVal + getNumWords(), isNegative() ? -1 : 0,
- (Result.getNumWords() - getNumWords()) * APINT_WORD_SIZE);
- Result.clearUnusedBits();
- return Result;
-}
-
-// Zero extend to a new width.
-APInt APInt::zext(unsigned width) const {
- assert(width > BitWidth && "Invalid APInt ZeroExtend request");
-
- if (width <= APINT_BITS_PER_WORD)
- return APInt(width, U.VAL);
-
- APInt Result(getMemory(getNumWords(width)), width);
-
- // Copy words.
- std::memcpy(Result.U.pVal, getRawData(), getNumWords() * APINT_WORD_SIZE);
-
- // Zero remaining words.
- std::memset(Result.U.pVal + getNumWords(), 0,
- (Result.getNumWords() - getNumWords()) * APINT_WORD_SIZE);
-
- return Result;
-}
-
-APInt APInt::zextOrTrunc(unsigned width) const {
- if (BitWidth < width)
- return zext(width);
- if (BitWidth > width)
- return trunc(width);
- return *this;
-}
-
-APInt APInt::sextOrTrunc(unsigned width) const {
- if (BitWidth < width)
- return sext(width);
- if (BitWidth > width)
- return trunc(width);
- return *this;
-}
-
-APInt APInt::zextOrSelf(unsigned width) const {
- if (BitWidth < width)
- return zext(width);
- return *this;
-}
-
-APInt APInt::sextOrSelf(unsigned width) const {
- if (BitWidth < width)
- return sext(width);
- return *this;
-}
-
-/// Arithmetic right-shift this APInt by shiftAmt.
-/// Arithmetic right-shift function.
-void APInt::ashrInPlace(const APInt &shiftAmt) {
- ashrInPlace((unsigned)shiftAmt.getLimitedValue(BitWidth));
-}
-
-/// Arithmetic right-shift this APInt by shiftAmt.
-/// Arithmetic right-shift function.
-void APInt::ashrSlowCase(unsigned ShiftAmt) {
- // Don't bother performing a no-op shift.
- if (!ShiftAmt)
- return;
-
- // Save the original sign bit for later.
- bool Negative = isNegative();
-
- // WordShift is the inter-part shift; BitShift is intra-part shift.
- unsigned WordShift = ShiftAmt / APINT_BITS_PER_WORD;
- unsigned BitShift = ShiftAmt % APINT_BITS_PER_WORD;
-
- unsigned WordsToMove = getNumWords() - WordShift;
- if (WordsToMove != 0) {
- // Sign extend the last word to fill in the unused bits.
- U.pVal[getNumWords() - 1] = SignExtend64(
- U.pVal[getNumWords() - 1], ((BitWidth - 1) % APINT_BITS_PER_WORD) + 1);
-
- // Fastpath for moving by whole words.
- if (BitShift == 0) {
- std::memmove(U.pVal, U.pVal + WordShift, WordsToMove * APINT_WORD_SIZE);
- } else {
- // Move the words containing significant bits.
- for (unsigned i = 0; i != WordsToMove - 1; ++i)
- U.pVal[i] = (U.pVal[i + WordShift] >> BitShift) |
- (U.pVal[i + WordShift + 1] << (APINT_BITS_PER_WORD - BitShift));
-
- // Handle the last word which has no high bits to copy.
- U.pVal[WordsToMove - 1] = U.pVal[WordShift + WordsToMove - 1] >> BitShift;
- // Sign extend one more time.
- U.pVal[WordsToMove - 1] =
- SignExtend64(U.pVal[WordsToMove - 1], APINT_BITS_PER_WORD - BitShift);
- }
- }
-
- // Fill in the remainder based on the original sign.
- std::memset(U.pVal + WordsToMove, Negative ? -1 : 0,
- WordShift * APINT_WORD_SIZE);
- clearUnusedBits();
-}
-
-/// Logical right-shift this APInt by shiftAmt.
-/// Logical right-shift function.
-void APInt::lshrInPlace(const APInt &shiftAmt) {
- lshrInPlace((unsigned)shiftAmt.getLimitedValue(BitWidth));
-}
-
-/// Logical right-shift this APInt by shiftAmt.
-/// Logical right-shift function.
-void APInt::lshrSlowCase(unsigned ShiftAmt) {
- tcShiftRight(U.pVal, getNumWords(), ShiftAmt);
-}
-
-/// Left-shift this APInt by shiftAmt.
-/// Left-shift function.
-APInt &APInt::operator<<=(const APInt &shiftAmt) {
- // It's undefined behavior in C to shift by BitWidth or greater.
- *this <<= (unsigned)shiftAmt.getLimitedValue(BitWidth);
- return *this;
-}
-
-void APInt::shlSlowCase(unsigned ShiftAmt) {
- tcShiftLeft(U.pVal, getNumWords(), ShiftAmt);
- clearUnusedBits();
-}
-
-// Calculate the rotate amount modulo the bit width.
-static unsigned rotateModulo(unsigned BitWidth, const APInt &rotateAmt) {
- unsigned rotBitWidth = rotateAmt.getBitWidth();
- APInt rot = rotateAmt;
- if (rotBitWidth < BitWidth) {
- // Extend the rotate APInt, so that the urem doesn't divide by 0.
- // e.g. APInt(1, 32) would give APInt(1, 0).
- rot = rotateAmt.zext(BitWidth);
- }
- rot = rot.urem(APInt(rot.getBitWidth(), BitWidth));
- return rot.getLimitedValue(BitWidth);
-}
-
-APInt APInt::rotl(const APInt &rotateAmt) const {
- return rotl(rotateModulo(BitWidth, rotateAmt));
-}
-
-APInt APInt::rotl(unsigned rotateAmt) const {
- rotateAmt %= BitWidth;
- if (rotateAmt == 0)
- return *this;
- return shl(rotateAmt) | lshr(BitWidth - rotateAmt);
-}
-
-APInt APInt::rotr(const APInt &rotateAmt) const {
- return rotr(rotateModulo(BitWidth, rotateAmt));
-}
-
-APInt APInt::rotr(unsigned rotateAmt) const {
- rotateAmt %= BitWidth;
- if (rotateAmt == 0)
- return *this;
- return lshr(rotateAmt) | shl(BitWidth - rotateAmt);
-}
-
-// Square Root - this method computes and returns the square root of "this".
-// Three mechanisms are used for computation. For small values (<= 5 bits),
-// a table lookup is done. This gets some performance for common cases. For
-// values using less than 52 bits, the value is converted to double and then
-// the libc sqrt function is called. The result is rounded and then converted
-// back to a uint64_t which is then used to construct the result. Finally,
-// the Babylonian method for computing square roots is used.
-APInt APInt::sqrt() const {
-
- // Determine the magnitude of the value.
- unsigned magnitude = getActiveBits();
-
- // Use a fast table for some small values. This also gets rid of some
- // rounding errors in libc sqrt for small values.
- if (magnitude <= 5) {
- static const uint8_t results[32] = {
- /* 0 */ 0,
- /* 1- 2 */ 1, 1,
- /* 3- 6 */ 2, 2, 2, 2,
- /* 7-12 */ 3, 3, 3, 3, 3, 3,
- /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4,
- /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- /* 31 */ 6
- };
- return APInt(BitWidth, results[ (isSingleWord() ? U.VAL : U.pVal[0]) ]);
- }
-
- // If the magnitude of the value fits in less than 52 bits (the precision of
- // an IEEE double precision floating point value), then we can use the
- // libc sqrt function which will probably use a hardware sqrt computation.
- // This should be faster than the algorithm below.
- if (magnitude < 52) {
- return APInt(BitWidth,
- uint64_t(::round(::sqrt(double(isSingleWord() ? U.VAL
- : U.pVal[0])))));
- }
-
- // Okay, all the short cuts are exhausted. We must compute it. The following
- // is a classical Babylonian method for computing the square root. This code
- // was adapted to APInt from a wikipedia article on such computations.
- // See http://www.wikipedia.org/ and go to the page named
- // Calculate_an_integer_square_root.
- unsigned nbits = BitWidth, i = 4;
- APInt testy(BitWidth, 16);
- APInt x_old(BitWidth, 1);
- APInt x_new(BitWidth, 0);
- APInt two(BitWidth, 2);
-
- // Select a good starting value using binary logarithms.
- for (;; i += 2, testy = testy.shl(2))
- if (i >= nbits || this->ule(testy)) {
- x_old = x_old.shl(i / 2);
- break;
- }
-
- // Use the Babylonian method to arrive at the integer square root:
- for (;;) {
- x_new = (this->udiv(x_old) + x_old).udiv(two);
- if (x_old.ule(x_new))
- break;
- x_old = x_new;
- }
-
- // Make sure we return the closest approximation
- // NOTE: The rounding calculation below is correct. It will produce an
- // off-by-one discrepancy with results from pari/gp. That discrepancy has been
- // determined to be a rounding issue with pari/gp as it begins to use a
- // floating point representation after 192 bits. There are no discrepancies
- // between this algorithm and pari/gp for bit widths < 192 bits.
- APInt square(x_old * x_old);
- APInt nextSquare((x_old + 1) * (x_old +1));
- if (this->ult(square))
- return x_old;
- assert(this->ule(nextSquare) && "Error in APInt::sqrt computation");
- APInt midpoint((nextSquare - square).udiv(two));
- APInt offset(*this - square);
- if (offset.ult(midpoint))
- return x_old;
- return x_old + 1;
-}
-
-/// Computes the multiplicative inverse of this APInt for a given modulo. The
-/// iterative extended Euclidean algorithm is used to solve for this value,
-/// however we simplify it to speed up calculating only the inverse, and take
-/// advantage of div+rem calculations. We also use some tricks to avoid copying
-/// (potentially large) APInts around.
-APInt APInt::multiplicativeInverse(const APInt& modulo) const {
- assert(ult(modulo) && "This APInt must be smaller than the modulo");
-
- // Using the properties listed at the following web page (accessed 06/21/08):
- // http://www.numbertheory.org/php/euclid.html
- // (especially the properties numbered 3, 4 and 9) it can be proved that
- // BitWidth bits suffice for all the computations in the algorithm implemented
- // below. More precisely, this number of bits suffice if the multiplicative
- // inverse exists, but may not suffice for the general extended Euclidean
- // algorithm.
-
- APInt r[2] = { modulo, *this };
- APInt t[2] = { APInt(BitWidth, 0), APInt(BitWidth, 1) };
- APInt q(BitWidth, 0);
-
- unsigned i;
- for (i = 0; r[i^1] != 0; i ^= 1) {
- // An overview of the math without the confusing bit-flipping:
- // q = r[i-2] / r[i-1]
- // r[i] = r[i-2] % r[i-1]
- // t[i] = t[i-2] - t[i-1] * q
- udivrem(r[i], r[i^1], q, r[i]);
- t[i] -= t[i^1] * q;
- }
-
- // If this APInt and the modulo are not coprime, there is no multiplicative
- // inverse, so return 0. We check this by looking at the next-to-last
- // remainder, which is the gcd(*this,modulo) as calculated by the Euclidean
- // algorithm.
- if (r[i] != 1)
- return APInt(BitWidth, 0);
-
- // The next-to-last t is the multiplicative inverse. However, we are
- // interested in a positive inverse. Calculate a positive one from a negative
- // one if necessary. A simple addition of the modulo suffices because
- // abs(t[i]) is known to be less than *this/2 (see the link above).
- if (t[i].isNegative())
- t[i] += modulo;
-
- return std::move(t[i]);
-}
-
-/// Calculate the magic numbers required to implement a signed integer division
-/// by a constant as a sequence of multiplies, adds and shifts. Requires that
-/// the divisor not be 0, 1, or -1. Taken from "Hacker's Delight", Henry S.
-/// Warren, Jr., chapter 10.
-APInt::ms APInt::magic() const {
- const APInt& d = *this;
- unsigned p;
- APInt ad, anc, delta, q1, r1, q2, r2, t;
- APInt signedMin = APInt::getSignedMinValue(d.getBitWidth());
- struct ms mag;
-
- ad = d.abs();
- t = signedMin + (d.lshr(d.getBitWidth() - 1));
- anc = t - 1 - t.urem(ad); // absolute value of nc
- p = d.getBitWidth() - 1; // initialize p
- q1 = signedMin.udiv(anc); // initialize q1 = 2p/abs(nc)
- r1 = signedMin - q1*anc; // initialize r1 = rem(2p,abs(nc))
- q2 = signedMin.udiv(ad); // initialize q2 = 2p/abs(d)
- r2 = signedMin - q2*ad; // initialize r2 = rem(2p,abs(d))
- do {
- p = p + 1;
- q1 = q1<<1; // update q1 = 2p/abs(nc)
- r1 = r1<<1; // update r1 = rem(2p/abs(nc))
- if (r1.uge(anc)) { // must be unsigned comparison
- q1 = q1 + 1;
- r1 = r1 - anc;
- }
- q2 = q2<<1; // update q2 = 2p/abs(d)
- r2 = r2<<1; // update r2 = rem(2p/abs(d))
- if (r2.uge(ad)) { // must be unsigned comparison
- q2 = q2 + 1;
- r2 = r2 - ad;
- }
- delta = ad - r2;
- } while (q1.ult(delta) || (q1 == delta && r1 == 0));
-
- mag.m = q2 + 1;
- if (d.isNegative()) mag.m = -mag.m; // resulting magic number
- mag.s = p - d.getBitWidth(); // resulting shift
- return mag;
-}
-
-/// Calculate the magic numbers required to implement an unsigned integer
-/// division by a constant as a sequence of multiplies, adds and shifts.
-/// Requires that the divisor not be 0. Taken from "Hacker's Delight", Henry
-/// S. Warren, Jr., chapter 10.
-/// LeadingZeros can be used to simplify the calculation if the upper bits
-/// of the divided value are known zero.
-APInt::mu APInt::magicu(unsigned LeadingZeros) const {
- const APInt& d = *this;
- unsigned p;
- APInt nc, delta, q1, r1, q2, r2;
- struct mu magu;
- magu.a = 0; // initialize "add" indicator
- APInt allOnes = APInt::getAllOnesValue(d.getBitWidth()).lshr(LeadingZeros);
- APInt signedMin = APInt::getSignedMinValue(d.getBitWidth());
- APInt signedMax = APInt::getSignedMaxValue(d.getBitWidth());
-
- nc = allOnes - (allOnes - d).urem(d);
- p = d.getBitWidth() - 1; // initialize p
- q1 = signedMin.udiv(nc); // initialize q1 = 2p/nc
- r1 = signedMin - q1*nc; // initialize r1 = rem(2p,nc)
- q2 = signedMax.udiv(d); // initialize q2 = (2p-1)/d
- r2 = signedMax - q2*d; // initialize r2 = rem((2p-1),d)
- do {
- p = p + 1;
- if (r1.uge(nc - r1)) {
- q1 = q1 + q1 + 1; // update q1
- r1 = r1 + r1 - nc; // update r1
- }
- else {
- q1 = q1+q1; // update q1
- r1 = r1+r1; // update r1
- }
- if ((r2 + 1).uge(d - r2)) {
- if (q2.uge(signedMax)) magu.a = 1;
- q2 = q2+q2 + 1; // update q2
- r2 = r2+r2 + 1 - d; // update r2
- }
- else {
- if (q2.uge(signedMin)) magu.a = 1;
- q2 = q2+q2; // update q2
- r2 = r2+r2 + 1; // update r2
- }
- delta = d - 1 - r2;
- } while (p < d.getBitWidth()*2 &&
- (q1.ult(delta) || (q1 == delta && r1 == 0)));
- magu.m = q2 + 1; // resulting magic number
- magu.s = p - d.getBitWidth(); // resulting shift
- return magu;
-}
-
-/// Implementation of Knuth's Algorithm D (Division of nonnegative integers)
-/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The
-/// variables here have the same names as in the algorithm. Comments explain
-/// the algorithm and any deviation from it.
-static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
- unsigned m, unsigned n) {
- assert(u && "Must provide dividend");
- assert(v && "Must provide divisor");
- assert(q && "Must provide quotient");
- assert(u != v && u != q && v != q && "Must use different memory");
- assert(n>1 && "n must be > 1");
-
- // b denotes the base of the number system. In our case b is 2^32.
- const uint64_t b = uint64_t(1) << 32;
-
-// The DEBUG macros here tend to be spam in the debug output if you're not
-// debugging this code. Disable them unless KNUTH_DEBUG is defined.
-#ifdef KNUTH_DEBUG
-#define DEBUG_KNUTH(X) LLVM_DEBUG(X)
-#else
-#define DEBUG_KNUTH(X) do {} while(false)
-#endif
-
- DEBUG_KNUTH(dbgs() << "KnuthDiv: m=" << m << " n=" << n << '\n');
- DEBUG_KNUTH(dbgs() << "KnuthDiv: original:");
- DEBUG_KNUTH(for (int i = m + n; i >= 0; i--) dbgs() << " " << u[i]);
- DEBUG_KNUTH(dbgs() << " by");
- DEBUG_KNUTH(for (int i = n; i > 0; i--) dbgs() << " " << v[i - 1]);
- DEBUG_KNUTH(dbgs() << '\n');
- // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of
- // u and v by d. Note that we have taken Knuth's advice here to use a power
- // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of
- // 2 allows us to shift instead of multiply and it is easy to determine the
- // shift amount from the leading zeros. We are basically normalizing the u
- // and v so that its high bits are shifted to the top of v's range without
- // overflow. Note that this can require an extra word in u so that u must
- // be of length m+n+1.
- unsigned shift = countLeadingZeros(v[n-1]);
- uint32_t v_carry = 0;
- uint32_t u_carry = 0;
- if (shift) {
- for (unsigned i = 0; i < m+n; ++i) {
- uint32_t u_tmp = u[i] >> (32 - shift);
- u[i] = (u[i] << shift) | u_carry;
- u_carry = u_tmp;
- }
- for (unsigned i = 0; i < n; ++i) {
- uint32_t v_tmp = v[i] >> (32 - shift);
- v[i] = (v[i] << shift) | v_carry;
- v_carry = v_tmp;
- }
- }
- u[m+n] = u_carry;
-
- DEBUG_KNUTH(dbgs() << "KnuthDiv: normal:");
- DEBUG_KNUTH(for (int i = m + n; i >= 0; i--) dbgs() << " " << u[i]);
- DEBUG_KNUTH(dbgs() << " by");
- DEBUG_KNUTH(for (int i = n; i > 0; i--) dbgs() << " " << v[i - 1]);
- DEBUG_KNUTH(dbgs() << '\n');
-
- // D2. [Initialize j.] Set j to m. This is the loop counter over the places.
- int j = m;
- do {
- DEBUG_KNUTH(dbgs() << "KnuthDiv: quotient digit #" << j << '\n');
- // D3. [Calculate q'.].
- // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q')
- // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r')
- // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease
- // qp by 1, increase rp by v[n-1], and repeat this test if rp < b. The test
- // on v[n-2] determines at high speed most of the cases in which the trial
- // value qp is one too large, and it eliminates all cases where qp is two
- // too large.
- uint64_t dividend = Make_64(u[j+n], u[j+n-1]);
- DEBUG_KNUTH(dbgs() << "KnuthDiv: dividend == " << dividend << '\n');
- uint64_t qp = dividend / v[n-1];
- uint64_t rp = dividend % v[n-1];
- if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) {
- qp--;
- rp += v[n-1];
- if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2]))
- qp--;
- }
- DEBUG_KNUTH(dbgs() << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n');
-
- // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with
- // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation
- // consists of a simple multiplication by a one-place number, combined with
- // a subtraction.
- // The digits (u[j+n]...u[j]) should be kept positive; if the result of
- // this step is actually negative, (u[j+n]...u[j]) should be left as the
- // true value plus b**(n+1), namely as the b's complement of
- // the true value, and a "borrow" to the left should be remembered.
- int64_t borrow = 0;
- for (unsigned i = 0; i < n; ++i) {
- uint64_t p = uint64_t(qp) * uint64_t(v[i]);
- int64_t subres = int64_t(u[j+i]) - borrow - Lo_32(p);
- u[j+i] = Lo_32(subres);
- borrow = Hi_32(p) - Hi_32(subres);
- DEBUG_KNUTH(dbgs() << "KnuthDiv: u[j+i] = " << u[j + i]
- << ", borrow = " << borrow << '\n');
- }
- bool isNeg = u[j+n] < borrow;
- u[j+n] -= Lo_32(borrow);
-
- DEBUG_KNUTH(dbgs() << "KnuthDiv: after subtraction:");
- DEBUG_KNUTH(for (int i = m + n; i >= 0; i--) dbgs() << " " << u[i]);
- DEBUG_KNUTH(dbgs() << '\n');
-
- // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was
- // negative, go to step D6; otherwise go on to step D7.
- q[j] = Lo_32(qp);
- if (isNeg) {
- // D6. [Add back]. The probability that this step is necessary is very
- // small, on the order of only 2/b. Make sure that test data accounts for
- // this possibility. Decrease q[j] by 1
- q[j]--;
- // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]).
- // A carry will occur to the left of u[j+n], and it should be ignored
- // since it cancels with the borrow that occurred in D4.
- bool carry = false;
- for (unsigned i = 0; i < n; i++) {
- uint32_t limit = std::min(u[j+i],v[i]);
- u[j+i] += v[i] + carry;
- carry = u[j+i] < limit || (carry && u[j+i] == limit);
- }
- u[j+n] += carry;
- }
- DEBUG_KNUTH(dbgs() << "KnuthDiv: after correction:");
- DEBUG_KNUTH(for (int i = m + n; i >= 0; i--) dbgs() << " " << u[i]);
- DEBUG_KNUTH(dbgs() << "\nKnuthDiv: digit result = " << q[j] << '\n');
-
- // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3.
- } while (--j >= 0);
-
- DEBUG_KNUTH(dbgs() << "KnuthDiv: quotient:");
- DEBUG_KNUTH(for (int i = m; i >= 0; i--) dbgs() << " " << q[i]);
- DEBUG_KNUTH(dbgs() << '\n');
-
- // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired
- // remainder may be obtained by dividing u[...] by d. If r is non-null we
- // compute the remainder (urem uses this).
- if (r) {
- // The value d is expressed by the "shift" value above since we avoided
- // multiplication by d by using a shift left. So, all we have to do is
- // shift right here.
- if (shift) {
- uint32_t carry = 0;
- DEBUG_KNUTH(dbgs() << "KnuthDiv: remainder:");
- for (int i = n-1; i >= 0; i--) {
- r[i] = (u[i] >> shift) | carry;
- carry = u[i] << (32 - shift);
- DEBUG_KNUTH(dbgs() << " " << r[i]);
- }
- } else {
- for (int i = n-1; i >= 0; i--) {
- r[i] = u[i];
- DEBUG_KNUTH(dbgs() << " " << r[i]);
- }
- }
- DEBUG_KNUTH(dbgs() << '\n');
- }
- DEBUG_KNUTH(dbgs() << '\n');
-}
-
-void APInt::divide(const WordType *LHS, unsigned lhsWords, const WordType *RHS,
- unsigned rhsWords, WordType *Quotient, WordType *Remainder) {
- assert(lhsWords >= rhsWords && "Fractional result");
-
- // First, compose the values into an array of 32-bit words instead of
- // 64-bit words. This is a necessity of both the "short division" algorithm
- // and the Knuth "classical algorithm" which requires there to be native
- // operations for +, -, and * on an m bit value with an m*2 bit result. We
- // can't use 64-bit operands here because we don't have native results of
- // 128-bits. Furthermore, casting the 64-bit values to 32-bit values won't
- // work on large-endian machines.
- unsigned n = rhsWords * 2;
- unsigned m = (lhsWords * 2) - n;
-
- // Allocate space for the temporary values we need either on the stack, if
- // it will fit, or on the heap if it won't.
- uint32_t SPACE[128];
- uint32_t *U = nullptr;
- uint32_t *V = nullptr;
- uint32_t *Q = nullptr;
- uint32_t *R = nullptr;
- if ((Remainder?4:3)*n+2*m+1 <= 128) {
- U = &SPACE[0];
- V = &SPACE[m+n+1];
- Q = &SPACE[(m+n+1) + n];
- if (Remainder)
- R = &SPACE[(m+n+1) + n + (m+n)];
- } else {
- U = new uint32_t[m + n + 1];
- V = new uint32_t[n];
- Q = new uint32_t[m+n];
- if (Remainder)
- R = new uint32_t[n];
- }
-
- // Initialize the dividend
- memset(U, 0, (m+n+1)*sizeof(uint32_t));
- for (unsigned i = 0; i < lhsWords; ++i) {
- uint64_t tmp = LHS[i];
- U[i * 2] = Lo_32(tmp);
- U[i * 2 + 1] = Hi_32(tmp);
- }
- U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm.
-
- // Initialize the divisor
- memset(V, 0, (n)*sizeof(uint32_t));
- for (unsigned i = 0; i < rhsWords; ++i) {
- uint64_t tmp = RHS[i];
- V[i * 2] = Lo_32(tmp);
- V[i * 2 + 1] = Hi_32(tmp);
- }
-
- // initialize the quotient and remainder
- memset(Q, 0, (m+n) * sizeof(uint32_t));
- if (Remainder)
- memset(R, 0, n * sizeof(uint32_t));
-
- // Now, adjust m and n for the Knuth division. n is the number of words in
- // the divisor. m is the number of words by which the dividend exceeds the
- // divisor (i.e. m+n is the length of the dividend). These sizes must not
- // contain any zero words or the Knuth algorithm fails.
- for (unsigned i = n; i > 0 && V[i-1] == 0; i--) {
- n--;
- m++;
- }
- for (unsigned i = m+n; i > 0 && U[i-1] == 0; i--)
- m--;
-
- // If we're left with only a single word for the divisor, Knuth doesn't work
- // so we implement the short division algorithm here. This is much simpler
- // and faster because we are certain that we can divide a 64-bit quantity
- // by a 32-bit quantity at hardware speed and short division is simply a
- // series of such operations. This is just like doing short division but we
- // are using base 2^32 instead of base 10.
- assert(n != 0 && "Divide by zero?");
- if (n == 1) {
- uint32_t divisor = V[0];
- uint32_t remainder = 0;
- for (int i = m; i >= 0; i--) {
- uint64_t partial_dividend = Make_64(remainder, U[i]);
- if (partial_dividend == 0) {
- Q[i] = 0;
- remainder = 0;
- } else if (partial_dividend < divisor) {
- Q[i] = 0;
- remainder = Lo_32(partial_dividend);
- } else if (partial_dividend == divisor) {
- Q[i] = 1;
- remainder = 0;
- } else {
- Q[i] = Lo_32(partial_dividend / divisor);
- remainder = Lo_32(partial_dividend - (Q[i] * divisor));
- }
- }
- if (R)
- R[0] = remainder;
- } else {
- // Now we're ready to invoke the Knuth classical divide algorithm. In this
- // case n > 1.
- KnuthDiv(U, V, Q, R, m, n);
- }
-
- // If the caller wants the quotient
- if (Quotient) {
- for (unsigned i = 0; i < lhsWords; ++i)
- Quotient[i] = Make_64(Q[i*2+1], Q[i*2]);
- }
-
- // If the caller wants the remainder
- if (Remainder) {
- for (unsigned i = 0; i < rhsWords; ++i)
- Remainder[i] = Make_64(R[i*2+1], R[i*2]);
- }
-
- // Clean up the memory we allocated.
- if (U != &SPACE[0]) {
- delete [] U;
- delete [] V;
- delete [] Q;
- delete [] R;
- }
-}
-
-APInt APInt::udiv(const APInt &RHS) const {
- assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
-
- // First, deal with the easy case
- if (isSingleWord()) {
- assert(RHS.U.VAL != 0 && "Divide by zero?");
- return APInt(BitWidth, U.VAL / RHS.U.VAL);
- }
-
- // Get some facts about the LHS and RHS number of bits and words
- unsigned lhsWords = getNumWords(getActiveBits());
- unsigned rhsBits = RHS.getActiveBits();
- unsigned rhsWords = getNumWords(rhsBits);
- assert(rhsWords && "Divided by zero???");
-
- // Deal with some degenerate cases
- if (!lhsWords)
- // 0 / X ===> 0
- return APInt(BitWidth, 0);
- if (rhsBits == 1)
- // X / 1 ===> X
- return *this;
- if (lhsWords < rhsWords || this->ult(RHS))
- // X / Y ===> 0, iff X < Y
- return APInt(BitWidth, 0);
- if (*this == RHS)
- // X / X ===> 1
- return APInt(BitWidth, 1);
- if (lhsWords == 1) // rhsWords is 1 if lhsWords is 1.
- // All high words are zero, just use native divide
- return APInt(BitWidth, this->U.pVal[0] / RHS.U.pVal[0]);
-
- // We have to compute it the hard way. Invoke the Knuth divide algorithm.
- APInt Quotient(BitWidth, 0); // to hold result.
- divide(U.pVal, lhsWords, RHS.U.pVal, rhsWords, Quotient.U.pVal, nullptr);
- return Quotient;
-}
-
-APInt APInt::udiv(uint64_t RHS) const {
- assert(RHS != 0 && "Divide by zero?");
-
- // First, deal with the easy case
- if (isSingleWord())
- return APInt(BitWidth, U.VAL / RHS);
-
- // Get some facts about the LHS words.
- unsigned lhsWords = getNumWords(getActiveBits());
-
- // Deal with some degenerate cases
- if (!lhsWords)
- // 0 / X ===> 0
- return APInt(BitWidth, 0);
- if (RHS == 1)
- // X / 1 ===> X
- return *this;
- if (this->ult(RHS))
- // X / Y ===> 0, iff X < Y
- return APInt(BitWidth, 0);
- if (*this == RHS)
- // X / X ===> 1
- return APInt(BitWidth, 1);
- if (lhsWords == 1) // rhsWords is 1 if lhsWords is 1.
- // All high words are zero, just use native divide
- return APInt(BitWidth, this->U.pVal[0] / RHS);
-
- // We have to compute it the hard way. Invoke the Knuth divide algorithm.
- APInt Quotient(BitWidth, 0); // to hold result.
- divide(U.pVal, lhsWords, &RHS, 1, Quotient.U.pVal, nullptr);
- return Quotient;
-}
-
-APInt APInt::sdiv(const APInt &RHS) const {
- if (isNegative()) {
- if (RHS.isNegative())
- return (-(*this)).udiv(-RHS);
- return -((-(*this)).udiv(RHS));
- }
- if (RHS.isNegative())
- return -(this->udiv(-RHS));
- return this->udiv(RHS);
-}
-
-APInt APInt::sdiv(int64_t RHS) const {
- if (isNegative()) {
- if (RHS < 0)
- return (-(*this)).udiv(-RHS);
- return -((-(*this)).udiv(RHS));
- }
- if (RHS < 0)
- return -(this->udiv(-RHS));
- return this->udiv(RHS);
-}
-
-APInt APInt::urem(const APInt &RHS) const {
- assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- if (isSingleWord()) {
- assert(RHS.U.VAL != 0 && "Remainder by zero?");
- return APInt(BitWidth, U.VAL % RHS.U.VAL);
- }
-
- // Get some facts about the LHS
- unsigned lhsWords = getNumWords(getActiveBits());
-
- // Get some facts about the RHS
- unsigned rhsBits = RHS.getActiveBits();
- unsigned rhsWords = getNumWords(rhsBits);
- assert(rhsWords && "Performing remainder operation by zero ???");
-
- // Check the degenerate cases
- if (lhsWords == 0)
- // 0 % Y ===> 0
- return APInt(BitWidth, 0);
- if (rhsBits == 1)
- // X % 1 ===> 0
- return APInt(BitWidth, 0);
- if (lhsWords < rhsWords || this->ult(RHS))
- // X % Y ===> X, iff X < Y
- return *this;
- if (*this == RHS)
- // X % X == 0;
- return APInt(BitWidth, 0);
- if (lhsWords == 1)
- // All high words are zero, just use native remainder
- return APInt(BitWidth, U.pVal[0] % RHS.U.pVal[0]);
-
- // We have to compute it the hard way. Invoke the Knuth divide algorithm.
- APInt Remainder(BitWidth, 0);
- divide(U.pVal, lhsWords, RHS.U.pVal, rhsWords, nullptr, Remainder.U.pVal);
- return Remainder;
-}
-
-uint64_t APInt::urem(uint64_t RHS) const {
- assert(RHS != 0 && "Remainder by zero?");
-
- if (isSingleWord())
- return U.VAL % RHS;
-
- // Get some facts about the LHS
- unsigned lhsWords = getNumWords(getActiveBits());
-
- // Check the degenerate cases
- if (lhsWords == 0)
- // 0 % Y ===> 0
- return 0;
- if (RHS == 1)
- // X % 1 ===> 0
- return 0;
- if (this->ult(RHS))
- // X % Y ===> X, iff X < Y
- return getZExtValue();
- if (*this == RHS)
- // X % X == 0;
- return 0;
- if (lhsWords == 1)
- // All high words are zero, just use native remainder
- return U.pVal[0] % RHS;
-
- // We have to compute it the hard way. Invoke the Knuth divide algorithm.
- uint64_t Remainder;
- divide(U.pVal, lhsWords, &RHS, 1, nullptr, &Remainder);
- return Remainder;
-}
-
-APInt APInt::srem(const APInt &RHS) const {
- if (isNegative()) {
- if (RHS.isNegative())
- return -((-(*this)).urem(-RHS));
- return -((-(*this)).urem(RHS));
- }
- if (RHS.isNegative())
- return this->urem(-RHS);
- return this->urem(RHS);
-}
-
-int64_t APInt::srem(int64_t RHS) const {
- if (isNegative()) {
- if (RHS < 0)
- return -((-(*this)).urem(-RHS));
- return -((-(*this)).urem(RHS));
- }
- if (RHS < 0)
- return this->urem(-RHS);
- return this->urem(RHS);
-}
-
-void APInt::udivrem(const APInt &LHS, const APInt &RHS,
- APInt &Quotient, APInt &Remainder) {
- assert(LHS.BitWidth == RHS.BitWidth && "Bit widths must be the same");
- unsigned BitWidth = LHS.BitWidth;
-
- // First, deal with the easy case
- if (LHS.isSingleWord()) {
- assert(RHS.U.VAL != 0 && "Divide by zero?");
- uint64_t QuotVal = LHS.U.VAL / RHS.U.VAL;
- uint64_t RemVal = LHS.U.VAL % RHS.U.VAL;
- Quotient = APInt(BitWidth, QuotVal);
- Remainder = APInt(BitWidth, RemVal);
- return;
- }
-
- // Get some size facts about the dividend and divisor
- unsigned lhsWords = getNumWords(LHS.getActiveBits());
- unsigned rhsBits = RHS.getActiveBits();
- unsigned rhsWords = getNumWords(rhsBits);
- assert(rhsWords && "Performing divrem operation by zero ???");
-
- // Check the degenerate cases
- if (lhsWords == 0) {
- Quotient = APInt(BitWidth, 0); // 0 / Y ===> 0
- Remainder = APInt(BitWidth, 0); // 0 % Y ===> 0
- return;
- }
-
- if (rhsBits == 1) {
- Quotient = LHS; // X / 1 ===> X
- Remainder = APInt(BitWidth, 0); // X % 1 ===> 0
- }
-
- if (lhsWords < rhsWords || LHS.ult(RHS)) {
- Remainder = LHS; // X % Y ===> X, iff X < Y
- Quotient = APInt(BitWidth, 0); // X / Y ===> 0, iff X < Y
- return;
- }
-
- if (LHS == RHS) {
- Quotient = APInt(BitWidth, 1); // X / X ===> 1
- Remainder = APInt(BitWidth, 0); // X % X ===> 0;
- return;
- }
-
- // Make sure there is enough space to hold the results.
- // NOTE: This assumes that reallocate won't affect any bits if it doesn't
- // change the size. This is necessary if Quotient or Remainder is aliased
- // with LHS or RHS.
- Quotient.reallocate(BitWidth);
- Remainder.reallocate(BitWidth);
-
- if (lhsWords == 1) { // rhsWords is 1 if lhsWords is 1.
- // There is only one word to consider so use the native versions.
- uint64_t lhsValue = LHS.U.pVal[0];
- uint64_t rhsValue = RHS.U.pVal[0];
- Quotient = lhsValue / rhsValue;
- Remainder = lhsValue % rhsValue;
- return;
- }
-
- // Okay, lets do it the long way
- divide(LHS.U.pVal, lhsWords, RHS.U.pVal, rhsWords, Quotient.U.pVal,
- Remainder.U.pVal);
- // Clear the rest of the Quotient and Remainder.
- std::memset(Quotient.U.pVal + lhsWords, 0,
- (getNumWords(BitWidth) - lhsWords) * APINT_WORD_SIZE);
- std::memset(Remainder.U.pVal + rhsWords, 0,
- (getNumWords(BitWidth) - rhsWords) * APINT_WORD_SIZE);
-}
-
-void APInt::udivrem(const APInt &LHS, uint64_t RHS, APInt &Quotient,
- uint64_t &Remainder) {
- assert(RHS != 0 && "Divide by zero?");
- unsigned BitWidth = LHS.BitWidth;
-
- // First, deal with the easy case
- if (LHS.isSingleWord()) {
- uint64_t QuotVal = LHS.U.VAL / RHS;
- Remainder = LHS.U.VAL % RHS;
- Quotient = APInt(BitWidth, QuotVal);
- return;
- }
-
- // Get some size facts about the dividend and divisor
- unsigned lhsWords = getNumWords(LHS.getActiveBits());
-
- // Check the degenerate cases
- if (lhsWords == 0) {
- Quotient = APInt(BitWidth, 0); // 0 / Y ===> 0
- Remainder = 0; // 0 % Y ===> 0
- return;
- }
-
- if (RHS == 1) {
- Quotient = LHS; // X / 1 ===> X
- Remainder = 0; // X % 1 ===> 0
- return;
- }
-
- if (LHS.ult(RHS)) {
- Remainder = LHS.getZExtValue(); // X % Y ===> X, iff X < Y
- Quotient = APInt(BitWidth, 0); // X / Y ===> 0, iff X < Y
- return;
- }
-
- if (LHS == RHS) {
- Quotient = APInt(BitWidth, 1); // X / X ===> 1
- Remainder = 0; // X % X ===> 0;
- return;
- }
-
- // Make sure there is enough space to hold the results.
- // NOTE: This assumes that reallocate won't affect any bits if it doesn't
- // change the size. This is necessary if Quotient is aliased with LHS.
- Quotient.reallocate(BitWidth);
-
- if (lhsWords == 1) { // rhsWords is 1 if lhsWords is 1.
- // There is only one word to consider so use the native versions.
- uint64_t lhsValue = LHS.U.pVal[0];
- Quotient = lhsValue / RHS;
- Remainder = lhsValue % RHS;
- return;
- }
-
- // Okay, lets do it the long way
- divide(LHS.U.pVal, lhsWords, &RHS, 1, Quotient.U.pVal, &Remainder);
- // Clear the rest of the Quotient.
- std::memset(Quotient.U.pVal + lhsWords, 0,
- (getNumWords(BitWidth) - lhsWords) * APINT_WORD_SIZE);
-}
-
-void APInt::sdivrem(const APInt &LHS, const APInt &RHS,
- APInt &Quotient, APInt &Remainder) {
- if (LHS.isNegative()) {
- if (RHS.isNegative())
- APInt::udivrem(-LHS, -RHS, Quotient, Remainder);
- else {
- APInt::udivrem(-LHS, RHS, Quotient, Remainder);
- Quotient.negate();
- }
- Remainder.negate();
- } else if (RHS.isNegative()) {
- APInt::udivrem(LHS, -RHS, Quotient, Remainder);
- Quotient.negate();
- } else {
- APInt::udivrem(LHS, RHS, Quotient, Remainder);
- }
-}
-
-void APInt::sdivrem(const APInt &LHS, int64_t RHS,
- APInt &Quotient, int64_t &Remainder) {
- uint64_t R = Remainder;
- if (LHS.isNegative()) {
- if (RHS < 0)
- APInt::udivrem(-LHS, -RHS, Quotient, R);
- else {
- APInt::udivrem(-LHS, RHS, Quotient, R);
- Quotient.negate();
- }
- R = -R;
- } else if (RHS < 0) {
- APInt::udivrem(LHS, -RHS, Quotient, R);
- Quotient.negate();
- } else {
- APInt::udivrem(LHS, RHS, Quotient, R);
- }
- Remainder = R;
-}
-
-APInt APInt::sadd_ov(const APInt &RHS, bool &Overflow) const {
- APInt Res = *this+RHS;
- Overflow = isNonNegative() == RHS.isNonNegative() &&
- Res.isNonNegative() != isNonNegative();
- return Res;
-}
-
-APInt APInt::uadd_ov(const APInt &RHS, bool &Overflow) const {
- APInt Res = *this+RHS;
- Overflow = Res.ult(RHS);
- return Res;
-}
-
-APInt APInt::ssub_ov(const APInt &RHS, bool &Overflow) const {
- APInt Res = *this - RHS;
- Overflow = isNonNegative() != RHS.isNonNegative() &&
- Res.isNonNegative() != isNonNegative();
- return Res;
-}
-
-APInt APInt::usub_ov(const APInt &RHS, bool &Overflow) const {
- APInt Res = *this-RHS;
- Overflow = Res.ugt(*this);
- return Res;
-}
-
-APInt APInt::sdiv_ov(const APInt &RHS, bool &Overflow) const {
- // MININT/-1 --> overflow.
- Overflow = isMinSignedValue() && RHS.isAllOnesValue();
- return sdiv(RHS);
-}
-
-APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) const {
- APInt Res = *this * RHS;
-
- if (*this != 0 && RHS != 0)
- Overflow = Res.sdiv(RHS) != *this || Res.sdiv(*this) != RHS;
- else
- Overflow = false;
- return Res;
-}
-
-APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const {
- APInt Res = *this * RHS;
-
- if (*this != 0 && RHS != 0)
- Overflow = Res.udiv(RHS) != *this || Res.udiv(*this) != RHS;
- else
- Overflow = false;
- return Res;
-}
-
-APInt APInt::sshl_ov(const APInt &ShAmt, bool &Overflow) const {
- Overflow = ShAmt.uge(getBitWidth());
- if (Overflow)
- return APInt(BitWidth, 0);
-
- if (isNonNegative()) // Don't allow sign change.
- Overflow = ShAmt.uge(countLeadingZeros());
- else
- Overflow = ShAmt.uge(countLeadingOnes());
-
- return *this << ShAmt;
-}
-
-APInt APInt::ushl_ov(const APInt &ShAmt, bool &Overflow) const {
- Overflow = ShAmt.uge(getBitWidth());
- if (Overflow)
- return APInt(BitWidth, 0);
-
- Overflow = ShAmt.ugt(countLeadingZeros());
-
- return *this << ShAmt;
-}
-
-APInt APInt::sadd_sat(const APInt &RHS) const {
- bool Overflow;
- APInt Res = sadd_ov(RHS, Overflow);
- if (!Overflow)
- return Res;
-
- return isNegative() ? APInt::getSignedMinValue(BitWidth)
- : APInt::getSignedMaxValue(BitWidth);
-}
-
-APInt APInt::uadd_sat(const APInt &RHS) const {
- bool Overflow;
- APInt Res = uadd_ov(RHS, Overflow);
- if (!Overflow)
- return Res;
-
- return APInt::getMaxValue(BitWidth);
-}
-
-APInt APInt::ssub_sat(const APInt &RHS) const {
- bool Overflow;
- APInt Res = ssub_ov(RHS, Overflow);
- if (!Overflow)
- return Res;
-
- return isNegative() ? APInt::getSignedMinValue(BitWidth)
- : APInt::getSignedMaxValue(BitWidth);
-}
-
-APInt APInt::usub_sat(const APInt &RHS) const {
- bool Overflow;
- APInt Res = usub_ov(RHS, Overflow);
- if (!Overflow)
- return Res;
-
- return APInt(BitWidth, 0);
-}
-
-
-void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) {
- // Check our assumptions here
- assert(!str.empty() && "Invalid string length");
- assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 ||
- radix == 36) &&
- "Radix should be 2, 8, 10, 16, or 36!");
-
- StringRef::iterator p = str.begin();
- size_t slen = str.size();
- bool isNeg = *p == '-';
- if (*p == '-' || *p == '+') {
- p++;
- slen--;
- assert(slen && "String is only a sign, needs a value.");
- }
- assert((slen <= numbits || radix != 2) && "Insufficient bit width");
- assert(((slen-1)*3 <= numbits || radix != 8) && "Insufficient bit width");
- assert(((slen-1)*4 <= numbits || radix != 16) && "Insufficient bit width");
- assert((((slen-1)*64)/22 <= numbits || radix != 10) &&
- "Insufficient bit width");
-
- // Allocate memory if needed
- if (isSingleWord())
- U.VAL = 0;
- else
- U.pVal = getClearedMemory(getNumWords());
-
- // Figure out if we can shift instead of multiply
- unsigned shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0);
-
- // Enter digit traversal loop
- for (StringRef::iterator e = str.end(); p != e; ++p) {
- unsigned digit = getDigit(*p, radix);
- assert(digit < radix && "Invalid character in digit string");
-
- // Shift or multiply the value by the radix
- if (slen > 1) {
- if (shift)
- *this <<= shift;
- else
- *this *= radix;
- }
-
- // Add in the digit we just interpreted
- *this += digit;
- }
- // If its negative, put it in two's complement form
- if (isNeg)
- this->negate();
-}
-
-void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix,
- bool Signed, bool formatAsCLiteral) const {
- assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2 ||
- Radix == 36) &&
- "Radix should be 2, 8, 10, 16, or 36!");
-
- const char *Prefix = "";
- if (formatAsCLiteral) {
- switch (Radix) {
- case 2:
- // Binary literals are a non-standard extension added in gcc 4.3:
- // http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Binary-constants.html
- Prefix = "0b";
- break;
- case 8:
- Prefix = "0";
- break;
- case 10:
- break; // No prefix
- case 16:
- Prefix = "0x";
- break;
- default:
- llvm_unreachable("Invalid radix!");
- }
- }
-
- // First, check for a zero value and just short circuit the logic below.
- if (*this == 0) {
- while (*Prefix) {
- Str.push_back(*Prefix);
- ++Prefix;
- };
- Str.push_back('0');
- return;
- }
-
- static const char Digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
- if (isSingleWord()) {
- char Buffer[65];
- char *BufPtr = std::end(Buffer);
-
- uint64_t N;
- if (!Signed) {
- N = getZExtValue();
- } else {
- int64_t I = getSExtValue();
- if (I >= 0) {
- N = I;
- } else {
- Str.push_back('-');
- N = -(uint64_t)I;
- }
- }
-
- while (*Prefix) {
- Str.push_back(*Prefix);
- ++Prefix;
- };
-
- while (N) {
- *--BufPtr = Digits[N % Radix];
- N /= Radix;
- }
- Str.append(BufPtr, std::end(Buffer));
- return;
- }
-
- APInt Tmp(*this);
-
- if (Signed && isNegative()) {
- // They want to print the signed version and it is a negative value
- // Flip the bits and add one to turn it into the equivalent positive
- // value and put a '-' in the result.
- Tmp.negate();
- Str.push_back('-');
- }
-
- while (*Prefix) {
- Str.push_back(*Prefix);
- ++Prefix;
- };
-
- // We insert the digits backward, then reverse them to get the right order.
- unsigned StartDig = Str.size();
-
- // For the 2, 8 and 16 bit cases, we can just shift instead of divide
- // because the number of bits per digit (1, 3 and 4 respectively) divides
- // equally. We just shift until the value is zero.
- if (Radix == 2 || Radix == 8 || Radix == 16) {
- // Just shift tmp right for each digit width until it becomes zero
- unsigned ShiftAmt = (Radix == 16 ? 4 : (Radix == 8 ? 3 : 1));
- unsigned MaskAmt = Radix - 1;
-
- while (Tmp.getBoolValue()) {
- unsigned Digit = unsigned(Tmp.getRawData()[0]) & MaskAmt;
- Str.push_back(Digits[Digit]);
- Tmp.lshrInPlace(ShiftAmt);
- }
- } else {
- while (Tmp.getBoolValue()) {
- uint64_t Digit;
- udivrem(Tmp, Radix, Tmp, Digit);
- assert(Digit < Radix && "divide failed");
- Str.push_back(Digits[Digit]);
- }
- }
-
- // Reverse the digits before returning.
- std::reverse(Str.begin()+StartDig, Str.end());
-}
-
-/// Returns the APInt as a std::string. Note that this is an inefficient method.
-/// It is better to pass in a SmallVector/SmallString to the methods above.
-std::string APInt::toString(unsigned Radix = 10, bool Signed = true) const {
- SmallString<40> S;
- toString(S, Radix, Signed, /* formatAsCLiteral = */false);
- return S.str();
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void APInt::dump() const {
- SmallString<40> S, U;
- this->toStringUnsigned(U);
- this->toStringSigned(S);
- dbgs() << "APInt(" << BitWidth << "b, "
- << U << "u " << S << "s)\n";
-}
-#endif
-
-void APInt::print(raw_ostream &OS, bool isSigned) const {
- SmallString<40> S;
- this->toString(S, 10, isSigned, /* formatAsCLiteral = */false);
- OS << S;
-}
-
-// This implements a variety of operations on a representation of
-// arbitrary precision, two's-complement, bignum integer values.
-
-// Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe
-// and unrestricting assumption.
-static_assert(APInt::APINT_BITS_PER_WORD % 2 == 0,
- "Part width must be divisible by 2!");
-
-/* Some handy functions local to this file. */
-
-/* Returns the integer part with the least significant BITS set.
- BITS cannot be zero. */
-static inline APInt::WordType lowBitMask(unsigned bits) {
- assert(bits != 0 && bits <= APInt::APINT_BITS_PER_WORD);
-
- return ~(APInt::WordType) 0 >> (APInt::APINT_BITS_PER_WORD - bits);
-}
-
-/* Returns the value of the lower half of PART. */
-static inline APInt::WordType lowHalf(APInt::WordType part) {
- return part & lowBitMask(APInt::APINT_BITS_PER_WORD / 2);
-}
-
-/* Returns the value of the upper half of PART. */
-static inline APInt::WordType highHalf(APInt::WordType part) {
- return part >> (APInt::APINT_BITS_PER_WORD / 2);
-}
-
-/* Returns the bit number of the most significant set bit of a part.
- If the input number has no bits set -1U is returned. */
-static unsigned partMSB(APInt::WordType value) {
- return findLastSet(value, ZB_Max);
-}
-
-/* Returns the bit number of the least significant set bit of a
- part. If the input number has no bits set -1U is returned. */
-static unsigned partLSB(APInt::WordType value) {
- return findFirstSet(value, ZB_Max);
-}
-
-/* Sets the least significant part of a bignum to the input value, and
- zeroes out higher parts. */
-void APInt::tcSet(WordType *dst, WordType part, unsigned parts) {
- assert(parts > 0);
-
- dst[0] = part;
- for (unsigned i = 1; i < parts; i++)
- dst[i] = 0;
-}
-
-/* Assign one bignum to another. */
-void APInt::tcAssign(WordType *dst, const WordType *src, unsigned parts) {
- for (unsigned i = 0; i < parts; i++)
- dst[i] = src[i];
-}
-
-/* Returns true if a bignum is zero, false otherwise. */
-bool APInt::tcIsZero(const WordType *src, unsigned parts) {
- for (unsigned i = 0; i < parts; i++)
- if (src[i])
- return false;
-
- return true;
-}
-
-/* Extract the given bit of a bignum; returns 0 or 1. */
-int APInt::tcExtractBit(const WordType *parts, unsigned bit) {
- return (parts[whichWord(bit)] & maskBit(bit)) != 0;
-}
-
-/* Set the given bit of a bignum. */
-void APInt::tcSetBit(WordType *parts, unsigned bit) {
- parts[whichWord(bit)] |= maskBit(bit);
-}
-
-/* Clears the given bit of a bignum. */
-void APInt::tcClearBit(WordType *parts, unsigned bit) {
- parts[whichWord(bit)] &= ~maskBit(bit);
-}
-
-/* Returns the bit number of the least significant set bit of a
- number. If the input number has no bits set -1U is returned. */
-unsigned APInt::tcLSB(const WordType *parts, unsigned n) {
- for (unsigned i = 0; i < n; i++) {
- if (parts[i] != 0) {
- unsigned lsb = partLSB(parts[i]);
-
- return lsb + i * APINT_BITS_PER_WORD;
- }
- }
-
- return -1U;
-}
-
-/* Returns the bit number of the most significant set bit of a number.
- If the input number has no bits set -1U is returned. */
-unsigned APInt::tcMSB(const WordType *parts, unsigned n) {
- do {
- --n;
-
- if (parts[n] != 0) {
- unsigned msb = partMSB(parts[n]);
-
- return msb + n * APINT_BITS_PER_WORD;
- }
- } while (n);
-
- return -1U;
-}
-
-/* Copy the bit vector of width srcBITS from SRC, starting at bit
- srcLSB, to DST, of dstCOUNT parts, such that the bit srcLSB becomes
- the least significant bit of DST. All high bits above srcBITS in
- DST are zero-filled. */
-void
-APInt::tcExtract(WordType *dst, unsigned dstCount, const WordType *src,
- unsigned srcBits, unsigned srcLSB) {
- unsigned dstParts = (srcBits + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
- assert(dstParts <= dstCount);
-
- unsigned firstSrcPart = srcLSB / APINT_BITS_PER_WORD;
- tcAssign (dst, src + firstSrcPart, dstParts);
-
- unsigned shift = srcLSB % APINT_BITS_PER_WORD;
- tcShiftRight (dst, dstParts, shift);
-
- /* We now have (dstParts * APINT_BITS_PER_WORD - shift) bits from SRC
- in DST. If this is less that srcBits, append the rest, else
- clear the high bits. */
- unsigned n = dstParts * APINT_BITS_PER_WORD - shift;
- if (n < srcBits) {
- WordType mask = lowBitMask (srcBits - n);
- dst[dstParts - 1] |= ((src[firstSrcPart + dstParts] & mask)
- << n % APINT_BITS_PER_WORD);
- } else if (n > srcBits) {
- if (srcBits % APINT_BITS_PER_WORD)
- dst[dstParts - 1] &= lowBitMask (srcBits % APINT_BITS_PER_WORD);
- }
-
- /* Clear high parts. */
- while (dstParts < dstCount)
- dst[dstParts++] = 0;
-}
-
-/* DST += RHS + C where C is zero or one. Returns the carry flag. */
-APInt::WordType APInt::tcAdd(WordType *dst, const WordType *rhs,
- WordType c, unsigned parts) {
- assert(c <= 1);
-
- for (unsigned i = 0; i < parts; i++) {
- WordType l = dst[i];
- if (c) {
- dst[i] += rhs[i] + 1;
- c = (dst[i] <= l);
- } else {
- dst[i] += rhs[i];
- c = (dst[i] < l);
- }
- }
-
- return c;
-}
-
-/// This function adds a single "word" integer, src, to the multiple
-/// "word" integer array, dst[]. dst[] is modified to reflect the addition and
-/// 1 is returned if there is a carry out, otherwise 0 is returned.
-/// @returns the carry of the addition.
-APInt::WordType APInt::tcAddPart(WordType *dst, WordType src,
- unsigned parts) {
- for (unsigned i = 0; i < parts; ++i) {
- dst[i] += src;
- if (dst[i] >= src)
- return 0; // No need to carry so exit early.
- src = 1; // Carry one to next digit.
- }
-
- return 1;
-}
-
-/* DST -= RHS + C where C is zero or one. Returns the carry flag. */
-APInt::WordType APInt::tcSubtract(WordType *dst, const WordType *rhs,
- WordType c, unsigned parts) {
- assert(c <= 1);
-
- for (unsigned i = 0; i < parts; i++) {
- WordType l = dst[i];
- if (c) {
- dst[i] -= rhs[i] + 1;
- c = (dst[i] >= l);
- } else {
- dst[i] -= rhs[i];
- c = (dst[i] > l);
- }
- }
-
- return c;
-}
-
-/// This function subtracts a single "word" (64-bit word), src, from
-/// the multi-word integer array, dst[], propagating the borrowed 1 value until
-/// no further borrowing is needed or it runs out of "words" in dst. The result
-/// is 1 if "borrowing" exhausted the digits in dst, or 0 if dst was not
-/// exhausted. In other words, if src > dst then this function returns 1,
-/// otherwise 0.
-/// @returns the borrow out of the subtraction
-APInt::WordType APInt::tcSubtractPart(WordType *dst, WordType src,
- unsigned parts) {
- for (unsigned i = 0; i < parts; ++i) {
- WordType Dst = dst[i];
- dst[i] -= src;
- if (src <= Dst)
- return 0; // No need to borrow so exit early.
- src = 1; // We have to "borrow 1" from next "word"
- }
-
- return 1;
-}
-
-/* Negate a bignum in-place. */
-void APInt::tcNegate(WordType *dst, unsigned parts) {
- tcComplement(dst, parts);
- tcIncrement(dst, parts);
-}
-
-/* DST += SRC * MULTIPLIER + CARRY if add is true
- DST = SRC * MULTIPLIER + CARRY if add is false
-
- Requires 0 <= DSTPARTS <= SRCPARTS + 1. If DST overlaps SRC
- they must start at the same point, i.e. DST == SRC.
-
- If DSTPARTS == SRCPARTS + 1 no overflow occurs and zero is
- returned. Otherwise DST is filled with the least significant
- DSTPARTS parts of the result, and if all of the omitted higher
- parts were zero return zero, otherwise overflow occurred and
- return one. */
-int APInt::tcMultiplyPart(WordType *dst, const WordType *src,
- WordType multiplier, WordType carry,
- unsigned srcParts, unsigned dstParts,
- bool add) {
- /* Otherwise our writes of DST kill our later reads of SRC. */
- assert(dst <= src || dst >= src + srcParts);
- assert(dstParts <= srcParts + 1);
-
- /* N loops; minimum of dstParts and srcParts. */
- unsigned n = std::min(dstParts, srcParts);
-
- for (unsigned i = 0; i < n; i++) {
- WordType low, mid, high, srcPart;
-
- /* [ LOW, HIGH ] = MULTIPLIER * SRC[i] + DST[i] + CARRY.
-
- This cannot overflow, because
-
- (n - 1) * (n - 1) + 2 (n - 1) = (n - 1) * (n + 1)
-
- which is less than n^2. */
-
- srcPart = src[i];
-
- if (multiplier == 0 || srcPart == 0) {
- low = carry;
- high = 0;
- } else {
- low = lowHalf(srcPart) * lowHalf(multiplier);
- high = highHalf(srcPart) * highHalf(multiplier);
-
- mid = lowHalf(srcPart) * highHalf(multiplier);
- high += highHalf(mid);
- mid <<= APINT_BITS_PER_WORD / 2;
- if (low + mid < low)
- high++;
- low += mid;
-
- mid = highHalf(srcPart) * lowHalf(multiplier);
- high += highHalf(mid);
- mid <<= APINT_BITS_PER_WORD / 2;
- if (low + mid < low)
- high++;
- low += mid;
-
- /* Now add carry. */
- if (low + carry < low)
- high++;
- low += carry;
- }
-
- if (add) {
- /* And now DST[i], and store the new low part there. */
- if (low + dst[i] < low)
- high++;
- dst[i] += low;
- } else
- dst[i] = low;
-
- carry = high;
- }
-
- if (srcParts < dstParts) {
- /* Full multiplication, there is no overflow. */
- assert(srcParts + 1 == dstParts);
- dst[srcParts] = carry;
- return 0;
- }
-
- /* We overflowed if there is carry. */
- if (carry)
- return 1;
-
- /* We would overflow if any significant unwritten parts would be
- non-zero. This is true if any remaining src parts are non-zero
- and the multiplier is non-zero. */
- if (multiplier)
- for (unsigned i = dstParts; i < srcParts; i++)
- if (src[i])
- return 1;
-
- /* We fitted in the narrow destination. */
- return 0;
-}
-
-/* DST = LHS * RHS, where DST has the same width as the operands and
- is filled with the least significant parts of the result. Returns
- one if overflow occurred, otherwise zero. DST must be disjoint
- from both operands. */
-int APInt::tcMultiply(WordType *dst, const WordType *lhs,
- const WordType *rhs, unsigned parts) {
- assert(dst != lhs && dst != rhs);
-
- int overflow = 0;
- tcSet(dst, 0, parts);
-
- for (unsigned i = 0; i < parts; i++)
- overflow |= tcMultiplyPart(&dst[i], lhs, rhs[i], 0, parts,
- parts - i, true);
-
- return overflow;
-}
-
-/// DST = LHS * RHS, where DST has width the sum of the widths of the
-/// operands. No overflow occurs. DST must be disjoint from both operands.
-void APInt::tcFullMultiply(WordType *dst, const WordType *lhs,
- const WordType *rhs, unsigned lhsParts,
- unsigned rhsParts) {
- /* Put the narrower number on the LHS for less loops below. */
- if (lhsParts > rhsParts)
- return tcFullMultiply (dst, rhs, lhs, rhsParts, lhsParts);
-
- assert(dst != lhs && dst != rhs);
-
- tcSet(dst, 0, rhsParts);
-
- for (unsigned i = 0; i < lhsParts; i++)
- tcMultiplyPart(&dst[i], rhs, lhs[i], 0, rhsParts, rhsParts + 1, true);
-}
-
-/* If RHS is zero LHS and REMAINDER are left unchanged, return one.
- Otherwise set LHS to LHS / RHS with the fractional part discarded,
- set REMAINDER to the remainder, return zero. i.e.
-
- OLD_LHS = RHS * LHS + REMAINDER
-
- SCRATCH is a bignum of the same size as the operands and result for
- use by the routine; its contents need not be initialized and are
- destroyed. LHS, REMAINDER and SCRATCH must be distinct.
-*/
-int APInt::tcDivide(WordType *lhs, const WordType *rhs,
- WordType *remainder, WordType *srhs,
- unsigned parts) {
- assert(lhs != remainder && lhs != srhs && remainder != srhs);
-
- unsigned shiftCount = tcMSB(rhs, parts) + 1;
- if (shiftCount == 0)
- return true;
-
- shiftCount = parts * APINT_BITS_PER_WORD - shiftCount;
- unsigned n = shiftCount / APINT_BITS_PER_WORD;
- WordType mask = (WordType) 1 << (shiftCount % APINT_BITS_PER_WORD);
-
- tcAssign(srhs, rhs, parts);
- tcShiftLeft(srhs, parts, shiftCount);
- tcAssign(remainder, lhs, parts);
- tcSet(lhs, 0, parts);
-
- /* Loop, subtracting SRHS if REMAINDER is greater and adding that to
- the total. */
- for (;;) {
- int compare = tcCompare(remainder, srhs, parts);
- if (compare >= 0) {
- tcSubtract(remainder, srhs, 0, parts);
- lhs[n] |= mask;
- }
-
- if (shiftCount == 0)
- break;
- shiftCount--;
- tcShiftRight(srhs, parts, 1);
- if ((mask >>= 1) == 0) {
- mask = (WordType) 1 << (APINT_BITS_PER_WORD - 1);
- n--;
- }
- }
-
- return false;
-}
-
-/// Shift a bignum left Cound bits in-place. Shifted in bits are zero. There are
-/// no restrictions on Count.
-void APInt::tcShiftLeft(WordType *Dst, unsigned Words, unsigned Count) {
- // Don't bother performing a no-op shift.
- if (!Count)
- return;
-
- // WordShift is the inter-part shift; BitShift is the intra-part shift.
- unsigned WordShift = std::min(Count / APINT_BITS_PER_WORD, Words);
- unsigned BitShift = Count % APINT_BITS_PER_WORD;
-
- // Fastpath for moving by whole words.
- if (BitShift == 0) {
- std::memmove(Dst + WordShift, Dst, (Words - WordShift) * APINT_WORD_SIZE);
- } else {
- while (Words-- > WordShift) {
- Dst[Words] = Dst[Words - WordShift] << BitShift;
- if (Words > WordShift)
- Dst[Words] |=
- Dst[Words - WordShift - 1] >> (APINT_BITS_PER_WORD - BitShift);
- }
- }
-
- // Fill in the remainder with 0s.
- std::memset(Dst, 0, WordShift * APINT_WORD_SIZE);
-}
-
-/// Shift a bignum right Count bits in-place. Shifted in bits are zero. There
-/// are no restrictions on Count.
-void APInt::tcShiftRight(WordType *Dst, unsigned Words, unsigned Count) {
- // Don't bother performing a no-op shift.
- if (!Count)
- return;
-
- // WordShift is the inter-part shift; BitShift is the intra-part shift.
- unsigned WordShift = std::min(Count / APINT_BITS_PER_WORD, Words);
- unsigned BitShift = Count % APINT_BITS_PER_WORD;
-
- unsigned WordsToMove = Words - WordShift;
- // Fastpath for moving by whole words.
- if (BitShift == 0) {
- std::memmove(Dst, Dst + WordShift, WordsToMove * APINT_WORD_SIZE);
- } else {
- for (unsigned i = 0; i != WordsToMove; ++i) {
- Dst[i] = Dst[i + WordShift] >> BitShift;
- if (i + 1 != WordsToMove)
- Dst[i] |= Dst[i + WordShift + 1] << (APINT_BITS_PER_WORD - BitShift);
- }
- }
-
- // Fill in the remainder with 0s.
- std::memset(Dst + WordsToMove, 0, WordShift * APINT_WORD_SIZE);
-}
-
-/* Bitwise and of two bignums. */
-void APInt::tcAnd(WordType *dst, const WordType *rhs, unsigned parts) {
- for (unsigned i = 0; i < parts; i++)
- dst[i] &= rhs[i];
-}
-
-/* Bitwise inclusive or of two bignums. */
-void APInt::tcOr(WordType *dst, const WordType *rhs, unsigned parts) {
- for (unsigned i = 0; i < parts; i++)
- dst[i] |= rhs[i];
-}
-
-/* Bitwise exclusive or of two bignums. */
-void APInt::tcXor(WordType *dst, const WordType *rhs, unsigned parts) {
- for (unsigned i = 0; i < parts; i++)
- dst[i] ^= rhs[i];
-}
-
-/* Complement a bignum in-place. */
-void APInt::tcComplement(WordType *dst, unsigned parts) {
- for (unsigned i = 0; i < parts; i++)
- dst[i] = ~dst[i];
-}
-
-/* Comparison (unsigned) of two bignums. */
-int APInt::tcCompare(const WordType *lhs, const WordType *rhs,
- unsigned parts) {
- while (parts) {
- parts--;
- if (lhs[parts] != rhs[parts])
- return (lhs[parts] > rhs[parts]) ? 1 : -1;
- }
-
- return 0;
-}
-
-/* Set the least significant BITS bits of a bignum, clear the
- rest. */
-void APInt::tcSetLeastSignificantBits(WordType *dst, unsigned parts,
- unsigned bits) {
- unsigned i = 0;
- while (bits > APINT_BITS_PER_WORD) {
- dst[i++] = ~(WordType) 0;
- bits -= APINT_BITS_PER_WORD;
- }
-
- if (bits)
- dst[i++] = ~(WordType) 0 >> (APINT_BITS_PER_WORD - bits);
-
- while (i < parts)
- dst[i++] = 0;
-}
-
-APInt llvm::APIntOps::RoundingUDiv(const APInt &A, const APInt &B,
- APInt::Rounding RM) {
- // Currently udivrem always rounds down.
- switch (RM) {
- case APInt::Rounding::DOWN:
- case APInt::Rounding::TOWARD_ZERO:
- return A.udiv(B);
- case APInt::Rounding::UP: {
- APInt Quo, Rem;
- APInt::udivrem(A, B, Quo, Rem);
- if (Rem == 0)
- return Quo;
- return Quo + 1;
- }
- }
- llvm_unreachable("Unknown APInt::Rounding enum");
-}
-
-APInt llvm::APIntOps::RoundingSDiv(const APInt &A, const APInt &B,
- APInt::Rounding RM) {
- switch (RM) {
- case APInt::Rounding::DOWN:
- case APInt::Rounding::UP: {
- APInt Quo, Rem;
- APInt::sdivrem(A, B, Quo, Rem);
- if (Rem == 0)
- return Quo;
- // This algorithm deals with arbitrary rounding mode used by sdivrem.
- // We want to check whether the non-integer part of the mathematical value
- // is negative or not. If the non-integer part is negative, we need to round
- // down from Quo; otherwise, if it's positive or 0, we return Quo, as it's
- // already rounded down.
- if (RM == APInt::Rounding::DOWN) {
- if (Rem.isNegative() != B.isNegative())
- return Quo - 1;
- return Quo;
- }
- if (Rem.isNegative() != B.isNegative())
- return Quo;
- return Quo + 1;
- }
- // Currently sdiv rounds twards zero.
- case APInt::Rounding::TOWARD_ZERO:
- return A.sdiv(B);
- }
- llvm_unreachable("Unknown APInt::Rounding enum");
-}
-
-Optional<APInt>
-llvm::APIntOps::SolveQuadraticEquationWrap(APInt A, APInt B, APInt C,
- unsigned RangeWidth) {
- unsigned CoeffWidth = A.getBitWidth();
- assert(CoeffWidth == B.getBitWidth() && CoeffWidth == C.getBitWidth());
- assert(RangeWidth <= CoeffWidth &&
- "Value range width should be less than coefficient width");
- assert(RangeWidth > 1 && "Value range bit width should be > 1");
-
- LLVM_DEBUG(dbgs() << __func__ << ": solving " << A << "x^2 + " << B
- << "x + " << C << ", rw:" << RangeWidth << '\n');
-
- // Identify 0 as a (non)solution immediately.
- if (C.sextOrTrunc(RangeWidth).isNullValue() ) {
- LLVM_DEBUG(dbgs() << __func__ << ": zero solution\n");
- return APInt(CoeffWidth, 0);
- }
-
- // The result of APInt arithmetic has the same bit width as the operands,
- // so it can actually lose high bits. A product of two n-bit integers needs
- // 2n-1 bits to represent the full value.
- // The operation done below (on quadratic coefficients) that can produce
- // the largest value is the evaluation of the equation during bisection,
- // which needs 3 times the bitwidth of the coefficient, so the total number
- // of required bits is 3n.
- //
- // The purpose of this extension is to simulate the set Z of all integers,
- // where n+1 > n for all n in Z. In Z it makes sense to talk about positive
- // and negative numbers (not so much in a modulo arithmetic). The method
- // used to solve the equation is based on the standard formula for real
- // numbers, and uses the concepts of "positive" and "negative" with their
- // usual meanings.
- CoeffWidth *= 3;
- A = A.sext(CoeffWidth);
- B = B.sext(CoeffWidth);
- C = C.sext(CoeffWidth);
-
- // Make A > 0 for simplicity. Negate cannot overflow at this point because
- // the bit width has increased.
- if (A.isNegative()) {
- A.negate();
- B.negate();
- C.negate();
- }
-
- // Solving an equation q(x) = 0 with coefficients in modular arithmetic
- // is really solving a set of equations q(x) = kR for k = 0, 1, 2, ...,
- // and R = 2^BitWidth.
- // Since we're trying not only to find exact solutions, but also values
- // that "wrap around", such a set will always have a solution, i.e. an x
- // that satisfies at least one of the equations, or such that |q(x)|
- // exceeds kR, while |q(x-1)| for the same k does not.
- //
- // We need to find a value k, such that Ax^2 + Bx + C = kR will have a
- // positive solution n (in the above sense), and also such that the n
- // will be the least among all solutions corresponding to k = 0, 1, ...
- // (more precisely, the least element in the set
- // { n(k) | k is such that a solution n(k) exists }).
- //
- // Consider the parabola (over real numbers) that corresponds to the
- // quadratic equation. Since A > 0, the arms of the parabola will point
- // up. Picking different values of k will shift it up and down by R.
- //
- // We want to shift the parabola in such a way as to reduce the problem
- // of solving q(x) = kR to solving shifted_q(x) = 0.
- // (The interesting solutions are the ceilings of the real number
- // solutions.)
- APInt R = APInt::getOneBitSet(CoeffWidth, RangeWidth);
- APInt TwoA = 2 * A;
- APInt SqrB = B * B;
- bool PickLow;
-
- auto RoundUp = [] (const APInt &V, const APInt &A) -> APInt {
- assert(A.isStrictlyPositive());
- APInt T = V.abs().urem(A);
- if (T.isNullValue())
- return V;
- return V.isNegative() ? V+T : V+(A-T);
- };
-
- // The vertex of the parabola is at -B/2A, but since A > 0, it's negative
- // iff B is positive.
- if (B.isNonNegative()) {
- // If B >= 0, the vertex it at a negative location (or at 0), so in
- // order to have a non-negative solution we need to pick k that makes
- // C-kR negative. To satisfy all the requirements for the solution
- // that we are looking for, it needs to be closest to 0 of all k.
- C = C.srem(R);
- if (C.isStrictlyPositive())
- C -= R;
- // Pick the greater solution.
- PickLow = false;
- } else {
- // If B < 0, the vertex is at a positive location. For any solution
- // to exist, the discriminant must be non-negative. This means that
- // C-kR <= B^2/4A is a necessary condition for k, i.e. there is a
- // lower bound on values of k: kR >= C - B^2/4A.
- APInt LowkR = C - SqrB.udiv(2*TwoA); // udiv because all values > 0.
- // Round LowkR up (towards +inf) to the nearest kR.
- LowkR = RoundUp(LowkR, R);
-
- // If there exists k meeting the condition above, and such that
- // C-kR > 0, there will be two positive real number solutions of
- // q(x) = kR. Out of all such values of k, pick the one that makes
- // C-kR closest to 0, (i.e. pick maximum k such that C-kR > 0).
- // In other words, find maximum k such that LowkR <= kR < C.
- if (C.sgt(LowkR)) {
- // If LowkR < C, then such a k is guaranteed to exist because
- // LowkR itself is a multiple of R.
- C -= -RoundUp(-C, R); // C = C - RoundDown(C, R)
- // Pick the smaller solution.
- PickLow = true;
- } else {
- // If C-kR < 0 for all potential k's, it means that one solution
- // will be negative, while the other will be positive. The positive
- // solution will shift towards 0 if the parabola is moved up.
- // Pick the kR closest to the lower bound (i.e. make C-kR closest
- // to 0, or in other words, out of all parabolas that have solutions,
- // pick the one that is the farthest "up").
- // Since LowkR is itself a multiple of R, simply take C-LowkR.
- C -= LowkR;
- // Pick the greater solution.
- PickLow = false;
- }
- }
-
- LLVM_DEBUG(dbgs() << __func__ << ": updated coefficients " << A << "x^2 + "
- << B << "x + " << C << ", rw:" << RangeWidth << '\n');
-
- APInt D = SqrB - 4*A*C;
- assert(D.isNonNegative() && "Negative discriminant");
- APInt SQ = D.sqrt();
-
- APInt Q = SQ * SQ;
- bool InexactSQ = Q != D;
- // The calculated SQ may actually be greater than the exact (non-integer)
- // value. If that's the case, decremement SQ to get a value that is lower.
- if (Q.sgt(D))
- SQ -= 1;
-
- APInt X;
- APInt Rem;
-
- // SQ is rounded down (i.e SQ * SQ <= D), so the roots may be inexact.
- // When using the quadratic formula directly, the calculated low root
- // may be greater than the exact one, since we would be subtracting SQ.
- // To make sure that the calculated root is not greater than the exact
- // one, subtract SQ+1 when calculating the low root (for inexact value
- // of SQ).
- if (PickLow)
- APInt::sdivrem(-B - (SQ+InexactSQ), TwoA, X, Rem);
- else
- APInt::sdivrem(-B + SQ, TwoA, X, Rem);
-
- // The updated coefficients should be such that the (exact) solution is
- // positive. Since APInt division rounds towards 0, the calculated one
- // can be 0, but cannot be negative.
- assert(X.isNonNegative() && "Solution should be non-negative");
-
- if (!InexactSQ && Rem.isNullValue()) {
- LLVM_DEBUG(dbgs() << __func__ << ": solution (root): " << X << '\n');
- return X;
- }
-
- assert((SQ*SQ).sle(D) && "SQ = |_sqrt(D)_|, so SQ*SQ <= D");
- // The exact value of the square root of D should be between SQ and SQ+1.
- // This implies that the solution should be between that corresponding to
- // SQ (i.e. X) and that corresponding to SQ+1.
- //
- // The calculated X cannot be greater than the exact (real) solution.
- // Actually it must be strictly less than the exact solution, while
- // X+1 will be greater than or equal to it.
-
- APInt VX = (A*X + B)*X + C;
- APInt VY = VX + TwoA*X + A + B;
- bool SignChange = VX.isNegative() != VY.isNegative() ||
- VX.isNullValue() != VY.isNullValue();
- // If the sign did not change between X and X+1, X is not a valid solution.
- // This could happen when the actual (exact) roots don't have an integer
- // between them, so they would both be contained between X and X+1.
- if (!SignChange) {
- LLVM_DEBUG(dbgs() << __func__ << ": no valid solution\n");
- return None;
- }
-
- X += 1;
- LLVM_DEBUG(dbgs() << __func__ << ": solution (wrap): " << X << '\n');
- return X;
-}
diff --git a/gnu/llvm/lib/Support/APSInt.cpp b/gnu/llvm/lib/Support/APSInt.cpp
deleted file mode 100644
index 46c0f70ff66..00000000000
--- a/gnu/llvm/lib/Support/APSInt.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//===-- llvm/ADT/APSInt.cpp - Arbitrary Precision Signed Int ---*- C++ -*--===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the APSInt class, which is a simple class that
-// represents an arbitrary sized integer that knows its signedness.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/StringRef.h"
-
-using namespace llvm;
-
-APSInt::APSInt(StringRef Str) {
- assert(!Str.empty() && "Invalid string length");
-
- // (Over-)estimate the required number of bits.
- unsigned NumBits = ((Str.size() * 64) / 19) + 2;
- APInt Tmp(NumBits, Str, /*Radix=*/10);
- if (Str[0] == '-') {
- unsigned MinBits = Tmp.getMinSignedBits();
- if (MinBits > 0 && MinBits < NumBits)
- Tmp = Tmp.trunc(MinBits);
- *this = APSInt(Tmp, /*IsUnsigned=*/false);
- return;
- }
- unsigned ActiveBits = Tmp.getActiveBits();
- if (ActiveBits > 0 && ActiveBits < NumBits)
- Tmp = Tmp.trunc(ActiveBits);
- *this = APSInt(Tmp, /*IsUnsigned=*/true);
-}
-
-void APSInt::Profile(FoldingSetNodeID& ID) const {
- ID.AddInteger((unsigned) (IsUnsigned ? 1 : 0));
- APInt::Profile(ID);
-}
diff --git a/gnu/llvm/lib/Support/ARMAttributeParser.cpp b/gnu/llvm/lib/Support/ARMAttributeParser.cpp
deleted file mode 100644
index 1f98ac2f40b..00000000000
--- a/gnu/llvm/lib/Support/ARMAttributeParser.cpp
+++ /dev/null
@@ -1,707 +0,0 @@
-//===--- ARMAttributeParser.cpp - ARM Attribute Information Printer -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ARMAttributeParser.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/ScopedPrinter.h"
-
-using namespace llvm;
-using namespace llvm::ARMBuildAttrs;
-
-
-static const EnumEntry<unsigned> TagNames[] = {
- { "Tag_File", ARMBuildAttrs::File },
- { "Tag_Section", ARMBuildAttrs::Section },
- { "Tag_Symbol", ARMBuildAttrs::Symbol },
-};
-
-namespace llvm {
-#define ATTRIBUTE_HANDLER(Attr_) \
- { ARMBuildAttrs::Attr_, &ARMAttributeParser::Attr_ }
-
-const ARMAttributeParser::DisplayHandler
-ARMAttributeParser::DisplayRoutines[] = {
- { ARMBuildAttrs::CPU_raw_name, &ARMAttributeParser::StringAttribute, },
- { ARMBuildAttrs::CPU_name, &ARMAttributeParser::StringAttribute },
- ATTRIBUTE_HANDLER(CPU_arch),
- ATTRIBUTE_HANDLER(CPU_arch_profile),
- ATTRIBUTE_HANDLER(ARM_ISA_use),
- ATTRIBUTE_HANDLER(THUMB_ISA_use),
- ATTRIBUTE_HANDLER(FP_arch),
- ATTRIBUTE_HANDLER(WMMX_arch),
- ATTRIBUTE_HANDLER(Advanced_SIMD_arch),
- ATTRIBUTE_HANDLER(PCS_config),
- ATTRIBUTE_HANDLER(ABI_PCS_R9_use),
- ATTRIBUTE_HANDLER(ABI_PCS_RW_data),
- ATTRIBUTE_HANDLER(ABI_PCS_RO_data),
- ATTRIBUTE_HANDLER(ABI_PCS_GOT_use),
- ATTRIBUTE_HANDLER(ABI_PCS_wchar_t),
- ATTRIBUTE_HANDLER(ABI_FP_rounding),
- ATTRIBUTE_HANDLER(ABI_FP_denormal),
- ATTRIBUTE_HANDLER(ABI_FP_exceptions),
- ATTRIBUTE_HANDLER(ABI_FP_user_exceptions),
- ATTRIBUTE_HANDLER(ABI_FP_number_model),
- ATTRIBUTE_HANDLER(ABI_align_needed),
- ATTRIBUTE_HANDLER(ABI_align_preserved),
- ATTRIBUTE_HANDLER(ABI_enum_size),
- ATTRIBUTE_HANDLER(ABI_HardFP_use),
- ATTRIBUTE_HANDLER(ABI_VFP_args),
- ATTRIBUTE_HANDLER(ABI_WMMX_args),
- ATTRIBUTE_HANDLER(ABI_optimization_goals),
- ATTRIBUTE_HANDLER(ABI_FP_optimization_goals),
- ATTRIBUTE_HANDLER(compatibility),
- ATTRIBUTE_HANDLER(CPU_unaligned_access),
- ATTRIBUTE_HANDLER(FP_HP_extension),
- ATTRIBUTE_HANDLER(ABI_FP_16bit_format),
- ATTRIBUTE_HANDLER(MPextension_use),
- ATTRIBUTE_HANDLER(DIV_use),
- ATTRIBUTE_HANDLER(DSP_extension),
- ATTRIBUTE_HANDLER(T2EE_use),
- ATTRIBUTE_HANDLER(Virtualization_use),
- ATTRIBUTE_HANDLER(nodefaults)
-};
-
-#undef ATTRIBUTE_HANDLER
-
-uint64_t ARMAttributeParser::ParseInteger(const uint8_t *Data,
- uint32_t &Offset) {
- unsigned Length;
- uint64_t Value = decodeULEB128(Data + Offset, &Length);
- Offset = Offset + Length;
- return Value;
-}
-
-StringRef ARMAttributeParser::ParseString(const uint8_t *Data,
- uint32_t &Offset) {
- const char *String = reinterpret_cast<const char*>(Data + Offset);
- size_t Length = std::strlen(String);
- Offset = Offset + Length + 1;
- return StringRef(String, Length);
-}
-
-void ARMAttributeParser::IntegerAttribute(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
-
- uint64_t Value = ParseInteger(Data, Offset);
- Attributes.insert(std::make_pair(Tag, Value));
-
- if (SW)
- SW->printNumber(ARMBuildAttrs::AttrTypeAsString(Tag), Value);
-}
-
-void ARMAttributeParser::StringAttribute(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag, /*TagPrefix*/false);
- StringRef ValueDesc = ParseString(Data, Offset);
-
- if (SW) {
- DictScope AS(*SW, "Attribute");
- SW->printNumber("Tag", Tag);
- if (!TagName.empty())
- SW->printString("TagName", TagName);
- SW->printString("Value", ValueDesc);
- }
-}
-
-void ARMAttributeParser::PrintAttribute(unsigned Tag, unsigned Value,
- StringRef ValueDesc) {
- Attributes.insert(std::make_pair(Tag, Value));
-
- if (SW) {
- StringRef TagName = ARMBuildAttrs::AttrTypeAsString(Tag,
- /*TagPrefix*/false);
- DictScope AS(*SW, "Attribute");
- SW->printNumber("Tag", Tag);
- SW->printNumber("Value", Value);
- if (!TagName.empty())
- SW->printString("TagName", TagName);
- if (!ValueDesc.empty())
- SW->printString("Description", ValueDesc);
- }
-}
-
-void ARMAttributeParser::CPU_arch(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", "ARM v6",
- "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", "ARM v6S-M",
- "ARM v7E-M", "ARM v8"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::CPU_arch_profile(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- uint64_t Encoded = ParseInteger(Data, Offset);
-
- StringRef Profile;
- switch (Encoded) {
- default: Profile = "Unknown"; break;
- case 'A': Profile = "Application"; break;
- case 'R': Profile = "Real-time"; break;
- case 'M': Profile = "Microcontroller"; break;
- case 'S': Profile = "Classic"; break;
- case 0: Profile = "None"; break;
- }
-
- PrintAttribute(Tag, Encoded, Profile);
-}
-
-void ARMAttributeParser::ARM_ISA_use(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "Not Permitted", "Permitted" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::THUMB_ISA_use(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "Not Permitted", "Thumb-1", "Thumb-2" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::FP_arch(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Not Permitted", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4",
- "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::WMMX_arch(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "Not Permitted", "WMMXv1", "WMMXv2" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::Advanced_SIMD_arch(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Not Permitted", "NEONv1", "NEONv2+FMA", "ARMv8-a NEON", "ARMv8.1-a NEON"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::PCS_config(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "None", "Bare Platform", "Linux Application", "Linux DSO", "Palm OS 2004",
- "Reserved (Palm OS)", "Symbian OS 2004", "Reserved (Symbian OS)"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_PCS_R9_use(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "v6", "Static Base", "TLS", "Unused" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_PCS_RW_data(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Absolute", "PC-relative", "SB-relative", "Not Permitted"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_PCS_RO_data(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Absolute", "PC-relative", "Not Permitted"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_PCS_GOT_use(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Not Permitted", "Direct", "GOT-Indirect"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_PCS_wchar_t(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Not Permitted", "Unknown", "2-byte", "Unknown", "4-byte"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_FP_rounding(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "IEEE-754", "Runtime" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_FP_denormal(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Unsupported", "IEEE-754", "Sign Only"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_FP_exceptions(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "Not Permitted", "IEEE-754" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_FP_user_exceptions(AttrType Tag,
- const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "Not Permitted", "IEEE-754" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_FP_number_model(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Not Permitted", "Finite Only", "RTABI", "IEEE-754"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_align_needed(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Not Permitted", "8-byte alignment", "4-byte alignment", "Reserved"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
-
- std::string Description;
- if (Value < array_lengthof(Strings))
- Description = std::string(Strings[Value]);
- else if (Value <= 12)
- Description = std::string("8-byte alignment, ") + utostr(1ULL << Value)
- + std::string("-byte extended alignment");
- else
- Description = "Invalid";
-
- PrintAttribute(Tag, Value, Description);
-}
-
-void ARMAttributeParser::ABI_align_preserved(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Not Required", "8-byte data alignment", "8-byte data and code alignment",
- "Reserved"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
-
- std::string Description;
- if (Value < array_lengthof(Strings))
- Description = std::string(Strings[Value]);
- else if (Value <= 12)
- Description = std::string("8-byte stack alignment, ") +
- utostr(1ULL << Value) + std::string("-byte data alignment");
- else
- Description = "Invalid";
-
- PrintAttribute(Tag, Value, Description);
-}
-
-void ARMAttributeParser::ABI_enum_size(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Not Permitted", "Packed", "Int32", "External Int32"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_HardFP_use(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Tag_FP_arch", "Single-Precision", "Reserved", "Tag_FP_arch (deprecated)"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_VFP_args(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "AAPCS", "AAPCS VFP", "Custom", "Not Permitted"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_WMMX_args(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "AAPCS", "iWMMX", "Custom" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_optimization_goals(AttrType Tag,
- const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Debugging",
- "Best Debugging"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_FP_optimization_goals(AttrType Tag,
- const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Accuracy",
- "Best Accuracy"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::compatibility(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- uint64_t Integer = ParseInteger(Data, Offset);
- StringRef String = ParseString(Data, Offset);
-
- if (SW) {
- DictScope AS(*SW, "Attribute");
- SW->printNumber("Tag", Tag);
- SW->startLine() << "Value: " << Integer << ", " << String << '\n';
- SW->printString("TagName", AttrTypeAsString(Tag, /*TagPrefix*/false));
- switch (Integer) {
- case 0:
- SW->printString("Description", StringRef("No Specific Requirements"));
- break;
- case 1:
- SW->printString("Description", StringRef("AEABI Conformant"));
- break;
- default:
- SW->printString("Description", StringRef("AEABI Non-Conformant"));
- break;
- }
- }
-}
-
-void ARMAttributeParser::CPU_unaligned_access(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "Not Permitted", "v6-style" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::FP_HP_extension(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "If Available", "Permitted" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::ABI_FP_16bit_format(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "Not Permitted", "IEEE-754", "VFPv3" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::MPextension_use(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "Not Permitted", "Permitted" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::DIV_use(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "If Available", "Not Permitted", "Permitted"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::DSP_extension(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "Not Permitted", "Permitted" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::T2EE_use(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = { "Not Permitted", "Permitted" };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::Virtualization_use(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- static const char *const Strings[] = {
- "Not Permitted", "TrustZone", "Virtualization Extensions",
- "TrustZone + Virtualization Extensions"
- };
-
- uint64_t Value = ParseInteger(Data, Offset);
- StringRef ValueDesc =
- (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
- PrintAttribute(Tag, Value, ValueDesc);
-}
-
-void ARMAttributeParser::nodefaults(AttrType Tag, const uint8_t *Data,
- uint32_t &Offset) {
- uint64_t Value = ParseInteger(Data, Offset);
- PrintAttribute(Tag, Value, "Unspecified Tags UNDEFINED");
-}
-
-void ARMAttributeParser::ParseIndexList(const uint8_t *Data, uint32_t &Offset,
- SmallVectorImpl<uint8_t> &IndexList) {
- for (;;) {
- unsigned Length;
- uint64_t Value = decodeULEB128(Data + Offset, &Length);
- Offset = Offset + Length;
- if (Value == 0)
- break;
- IndexList.push_back(Value);
- }
-}
-
-void ARMAttributeParser::ParseAttributeList(const uint8_t *Data,
- uint32_t &Offset, uint32_t Length) {
- while (Offset < Length) {
- unsigned Length;
- uint64_t Tag = decodeULEB128(Data + Offset, &Length);
- Offset += Length;
-
- bool Handled = false;
- for (unsigned AHI = 0, AHE = array_lengthof(DisplayRoutines);
- AHI != AHE && !Handled; ++AHI) {
- if (uint64_t(DisplayRoutines[AHI].Attribute) == Tag) {
- (this->*DisplayRoutines[AHI].Routine)(ARMBuildAttrs::AttrType(Tag),
- Data, Offset);
- Handled = true;
- break;
- }
- }
- if (!Handled) {
- if (Tag < 32) {
- errs() << "unhandled AEABI Tag " << Tag
- << " (" << ARMBuildAttrs::AttrTypeAsString(Tag) << ")\n";
- continue;
- }
-
- if (Tag % 2 == 0)
- IntegerAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset);
- else
- StringAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset);
- }
- }
-}
-
-void ARMAttributeParser::ParseSubsection(const uint8_t *Data, uint32_t Length) {
- uint32_t Offset = sizeof(uint32_t); /* SectionLength */
-
- const char *VendorName = reinterpret_cast<const char*>(Data + Offset);
- size_t VendorNameLength = std::strlen(VendorName);
- Offset = Offset + VendorNameLength + 1;
-
- if (SW) {
- SW->printNumber("SectionLength", Length);
- SW->printString("Vendor", StringRef(VendorName, VendorNameLength));
- }
-
- if (StringRef(VendorName, VendorNameLength).lower() != "aeabi") {
- return;
- }
-
- while (Offset < Length) {
- /// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size
- uint8_t Tag = Data[Offset];
- Offset = Offset + sizeof(Tag);
-
- uint32_t Size =
- *reinterpret_cast<const support::ulittle32_t*>(Data + Offset);
- Offset = Offset + sizeof(Size);
-
- if (SW) {
- SW->printEnum("Tag", Tag, makeArrayRef(TagNames));
- SW->printNumber("Size", Size);
- }
-
- if (Size > Length) {
- errs() << "subsection length greater than section length\n";
- return;
- }
-
- StringRef ScopeName, IndexName;
- SmallVector<uint8_t, 8> Indicies;
- switch (Tag) {
- case ARMBuildAttrs::File:
- ScopeName = "FileAttributes";
- break;
- case ARMBuildAttrs::Section:
- ScopeName = "SectionAttributes";
- IndexName = "Sections";
- ParseIndexList(Data, Offset, Indicies);
- break;
- case ARMBuildAttrs::Symbol:
- ScopeName = "SymbolAttributes";
- IndexName = "Symbols";
- ParseIndexList(Data, Offset, Indicies);
- break;
- default:
- errs() << "unrecognised tag: 0x" << Twine::utohexstr(Tag) << '\n';
- return;
- }
-
- if (SW) {
- DictScope ASS(*SW, ScopeName);
- if (!Indicies.empty())
- SW->printList(IndexName, Indicies);
- ParseAttributeList(Data, Offset, Length);
- } else {
- ParseAttributeList(Data, Offset, Length);
- }
- }
-}
-
-void ARMAttributeParser::Parse(ArrayRef<uint8_t> Section, bool isLittle) {
- size_t Offset = 1;
- unsigned SectionNumber = 0;
-
- while (Offset < Section.size()) {
- uint32_t SectionLength = isLittle ?
- support::endian::read32le(Section.data() + Offset) :
- support::endian::read32be(Section.data() + Offset);
-
- if (SW) {
- SW->startLine() << "Section " << ++SectionNumber << " {\n";
- SW->indent();
- }
-
- ParseSubsection(Section.data() + Offset, SectionLength);
- Offset = Offset + SectionLength;
-
- if (SW) {
- SW->unindent();
- SW->startLine() << "}\n";
- }
- }
-}
-}
diff --git a/gnu/llvm/lib/Support/ARMBuildAttrs.cpp b/gnu/llvm/lib/Support/ARMBuildAttrs.cpp
deleted file mode 100644
index 8f18e9eb24e..00000000000
--- a/gnu/llvm/lib/Support/ARMBuildAttrs.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-//===-- ARMBuildAttrs.cpp - ARM Build Attributes --------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/ARMBuildAttributes.h"
-
-using namespace llvm;
-
-namespace {
-const struct {
- ARMBuildAttrs::AttrType Attr;
- StringRef TagName;
-} ARMAttributeTags[] = {
- { ARMBuildAttrs::File, "Tag_File" },
- { ARMBuildAttrs::Section, "Tag_Section" },
- { ARMBuildAttrs::Symbol, "Tag_Symbol" },
- { ARMBuildAttrs::CPU_raw_name, "Tag_CPU_raw_name" },
- { ARMBuildAttrs::CPU_name, "Tag_CPU_name" },
- { ARMBuildAttrs::CPU_arch, "Tag_CPU_arch" },
- { ARMBuildAttrs::CPU_arch_profile, "Tag_CPU_arch_profile" },
- { ARMBuildAttrs::ARM_ISA_use, "Tag_ARM_ISA_use" },
- { ARMBuildAttrs::THUMB_ISA_use, "Tag_THUMB_ISA_use" },
- { ARMBuildAttrs::FP_arch, "Tag_FP_arch" },
- { ARMBuildAttrs::WMMX_arch, "Tag_WMMX_arch" },
- { ARMBuildAttrs::Advanced_SIMD_arch, "Tag_Advanced_SIMD_arch" },
- { ARMBuildAttrs::PCS_config, "Tag_PCS_config" },
- { ARMBuildAttrs::ABI_PCS_R9_use, "Tag_ABI_PCS_R9_use" },
- { ARMBuildAttrs::ABI_PCS_RW_data, "Tag_ABI_PCS_RW_data" },
- { ARMBuildAttrs::ABI_PCS_RO_data, "Tag_ABI_PCS_RO_data" },
- { ARMBuildAttrs::ABI_PCS_GOT_use, "Tag_ABI_PCS_GOT_use" },
- { ARMBuildAttrs::ABI_PCS_wchar_t, "Tag_ABI_PCS_wchar_t" },
- { ARMBuildAttrs::ABI_FP_rounding, "Tag_ABI_FP_rounding" },
- { ARMBuildAttrs::ABI_FP_denormal, "Tag_ABI_FP_denormal" },
- { ARMBuildAttrs::ABI_FP_exceptions, "Tag_ABI_FP_exceptions" },
- { ARMBuildAttrs::ABI_FP_user_exceptions, "Tag_ABI_FP_user_exceptions" },
- { ARMBuildAttrs::ABI_FP_number_model, "Tag_ABI_FP_number_model" },
- { ARMBuildAttrs::ABI_align_needed, "Tag_ABI_align_needed" },
- { ARMBuildAttrs::ABI_align_preserved, "Tag_ABI_align_preserved" },
- { ARMBuildAttrs::ABI_enum_size, "Tag_ABI_enum_size" },
- { ARMBuildAttrs::ABI_HardFP_use, "Tag_ABI_HardFP_use" },
- { ARMBuildAttrs::ABI_VFP_args, "Tag_ABI_VFP_args" },
- { ARMBuildAttrs::ABI_WMMX_args, "Tag_ABI_WMMX_args" },
- { ARMBuildAttrs::ABI_optimization_goals, "Tag_ABI_optimization_goals" },
- { ARMBuildAttrs::ABI_FP_optimization_goals, "Tag_ABI_FP_optimization_goals" },
- { ARMBuildAttrs::compatibility, "Tag_compatibility" },
- { ARMBuildAttrs::CPU_unaligned_access, "Tag_CPU_unaligned_access" },
- { ARMBuildAttrs::FP_HP_extension, "Tag_FP_HP_extension" },
- { ARMBuildAttrs::ABI_FP_16bit_format, "Tag_ABI_FP_16bit_format" },
- { ARMBuildAttrs::MPextension_use, "Tag_MPextension_use" },
- { ARMBuildAttrs::DIV_use, "Tag_DIV_use" },
- { ARMBuildAttrs::DSP_extension, "Tag_DSP_extension" },
- { ARMBuildAttrs::nodefaults, "Tag_nodefaults" },
- { ARMBuildAttrs::also_compatible_with, "Tag_also_compatible_with" },
- { ARMBuildAttrs::T2EE_use, "Tag_T2EE_use" },
- { ARMBuildAttrs::conformance, "Tag_conformance" },
- { ARMBuildAttrs::Virtualization_use, "Tag_Virtualization_use" },
-
- // Legacy Names
- { ARMBuildAttrs::FP_arch, "Tag_VFP_arch" },
- { ARMBuildAttrs::FP_HP_extension, "Tag_VFP_HP_extension" },
- { ARMBuildAttrs::ABI_align_needed, "Tag_ABI_align8_needed" },
- { ARMBuildAttrs::ABI_align_preserved, "Tag_ABI_align8_preserved" },
-};
-}
-
-namespace llvm {
-namespace ARMBuildAttrs {
-StringRef AttrTypeAsString(unsigned Attr, bool HasTagPrefix) {
- return AttrTypeAsString(static_cast<AttrType>(Attr), HasTagPrefix);
-}
-
-StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix) {
- for (unsigned TI = 0, TE = sizeof(ARMAttributeTags) / sizeof(*ARMAttributeTags);
- TI != TE; ++TI)
- if (ARMAttributeTags[TI].Attr == Attr) {
- auto TagName = ARMAttributeTags[TI].TagName;
- return HasTagPrefix ? TagName : TagName.drop_front(4);
- }
- return "";
-}
-
-int AttrTypeFromString(StringRef Tag) {
- bool HasTagPrefix = Tag.startswith("Tag_");
- for (unsigned TI = 0,
- TE = sizeof(ARMAttributeTags) / sizeof(*ARMAttributeTags);
- TI != TE; ++TI) {
- auto TagName = ARMAttributeTags[TI].TagName;
- if (TagName.drop_front(HasTagPrefix ? 0 : 4) == Tag) {
- return ARMAttributeTags[TI].Attr;
- }
- }
- return -1;
-}
-}
-}
-
diff --git a/gnu/llvm/lib/Support/ARMTargetParser.cpp b/gnu/llvm/lib/Support/ARMTargetParser.cpp
deleted file mode 100644
index 07294b0c09a..00000000000
--- a/gnu/llvm/lib/Support/ARMTargetParser.cpp
+++ /dev/null
@@ -1,577 +0,0 @@
-//===-- ARMTargetParser - Parser for ARM target features --------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a target parser to recognise ARM hardware features
-// such as FPU/CPU/ARCH/extensions and specific support such as HWDIV.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ARMTargetParser.h"
-#include "llvm/ADT/StringSwitch.h"
-#include <cctype>
-
-using namespace llvm;
-
-static StringRef getHWDivSynonym(StringRef HWDiv) {
- return StringSwitch<StringRef>(HWDiv)
- .Case("thumb,arm", "arm,thumb")
- .Default(HWDiv);
-}
-
-// Allows partial match, ex. "v7a" matches "armv7a".
-ARM::ArchKind ARM::parseArch(StringRef Arch) {
- Arch = getCanonicalArchName(Arch);
- StringRef Syn = getArchSynonym(Arch);
- for (const auto A : ARCHNames) {
- if (A.getName().endswith(Syn))
- return A.ID;
- }
- return ArchKind::INVALID;
-}
-
-// Version number (ex. v7 = 7).
-unsigned ARM::parseArchVersion(StringRef Arch) {
- Arch = getCanonicalArchName(Arch);
- switch (parseArch(Arch)) {
- case ArchKind::ARMV2:
- case ArchKind::ARMV2A:
- return 2;
- case ArchKind::ARMV3:
- case ArchKind::ARMV3M:
- return 3;
- case ArchKind::ARMV4:
- case ArchKind::ARMV4T:
- return 4;
- case ArchKind::ARMV5T:
- case ArchKind::ARMV5TE:
- case ArchKind::IWMMXT:
- case ArchKind::IWMMXT2:
- case ArchKind::XSCALE:
- case ArchKind::ARMV5TEJ:
- return 5;
- case ArchKind::ARMV6:
- case ArchKind::ARMV6K:
- case ArchKind::ARMV6T2:
- case ArchKind::ARMV6KZ:
- case ArchKind::ARMV6M:
- return 6;
- case ArchKind::ARMV7A:
- case ArchKind::ARMV7VE:
- case ArchKind::ARMV7R:
- case ArchKind::ARMV7M:
- case ArchKind::ARMV7S:
- case ArchKind::ARMV7EM:
- case ArchKind::ARMV7K:
- return 7;
- case ArchKind::ARMV8A:
- case ArchKind::ARMV8_1A:
- case ArchKind::ARMV8_2A:
- case ArchKind::ARMV8_3A:
- case ArchKind::ARMV8_4A:
- case ArchKind::ARMV8_5A:
- case ArchKind::ARMV8R:
- case ArchKind::ARMV8MBaseline:
- case ArchKind::ARMV8MMainline:
- return 8;
- case ArchKind::INVALID:
- return 0;
- }
- llvm_unreachable("Unhandled architecture");
-}
-
-// Profile A/R/M
-ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) {
- Arch = getCanonicalArchName(Arch);
- switch (parseArch(Arch)) {
- case ArchKind::ARMV6M:
- case ArchKind::ARMV7M:
- case ArchKind::ARMV7EM:
- case ArchKind::ARMV8MMainline:
- case ArchKind::ARMV8MBaseline:
- return ProfileKind::M;
- case ArchKind::ARMV7R:
- case ArchKind::ARMV8R:
- return ProfileKind::R;
- case ArchKind::ARMV7A:
- case ArchKind::ARMV7VE:
- case ArchKind::ARMV7K:
- case ArchKind::ARMV8A:
- case ArchKind::ARMV8_1A:
- case ArchKind::ARMV8_2A:
- case ArchKind::ARMV8_3A:
- case ArchKind::ARMV8_4A:
- case ArchKind::ARMV8_5A:
- return ProfileKind::A;
- case ArchKind::ARMV2:
- case ArchKind::ARMV2A:
- case ArchKind::ARMV3:
- case ArchKind::ARMV3M:
- case ArchKind::ARMV4:
- case ArchKind::ARMV4T:
- case ArchKind::ARMV5T:
- case ArchKind::ARMV5TE:
- case ArchKind::ARMV5TEJ:
- case ArchKind::ARMV6:
- case ArchKind::ARMV6K:
- case ArchKind::ARMV6T2:
- case ArchKind::ARMV6KZ:
- case ArchKind::ARMV7S:
- case ArchKind::IWMMXT:
- case ArchKind::IWMMXT2:
- case ArchKind::XSCALE:
- case ArchKind::INVALID:
- return ProfileKind::INVALID;
- }
- llvm_unreachable("Unhandled architecture");
-}
-
-StringRef ARM::getArchSynonym(StringRef Arch) {
- return StringSwitch<StringRef>(Arch)
- .Case("v5", "v5t")
- .Case("v5e", "v5te")
- .Case("v6j", "v6")
- .Case("v6hl", "v6k")
- .Cases("v6m", "v6sm", "v6s-m", "v6-m")
- .Cases("v6z", "v6zk", "v6kz")
- .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
- .Case("v7r", "v7-r")
- .Case("v7m", "v7-m")
- .Case("v7em", "v7e-m")
- .Cases("v8", "v8a", "v8l", "aarch64", "arm64", "v8-a")
- .Case("v8.1a", "v8.1-a")
- .Case("v8.2a", "v8.2-a")
- .Case("v8.3a", "v8.3-a")
- .Case("v8.4a", "v8.4-a")
- .Case("v8.5a", "v8.5-a")
- .Case("v8r", "v8-r")
- .Case("v8m.base", "v8-m.base")
- .Case("v8m.main", "v8-m.main")
- .Default(Arch);
-}
-
-bool ARM::getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features) {
-
- if (FPUKind >= FK_LAST || FPUKind == FK_INVALID)
- return false;
-
- // fp-only-sp and d16 subtarget features are independent of each other, so we
- // must enable/disable both.
- switch (FPUNames[FPUKind].Restriction) {
- case FPURestriction::SP_D16:
- Features.push_back("+fp-only-sp");
- Features.push_back("+d16");
- break;
- case FPURestriction::D16:
- Features.push_back("-fp-only-sp");
- Features.push_back("+d16");
- break;
- case FPURestriction::None:
- Features.push_back("-fp-only-sp");
- Features.push_back("-d16");
- break;
- }
-
- // FPU version subtarget features are inclusive of lower-numbered ones, so
- // enable the one corresponding to this version and disable all that are
- // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
- // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
- switch (FPUNames[FPUKind].FPUVer) {
- case FPUVersion::VFPV5:
- Features.push_back("+fp-armv8");
- break;
- case FPUVersion::VFPV4:
- Features.push_back("+vfp4");
- Features.push_back("-fp-armv8");
- break;
- case FPUVersion::VFPV3_FP16:
- Features.push_back("+vfp3");
- Features.push_back("+fp16");
- Features.push_back("-vfp4");
- Features.push_back("-fp-armv8");
- break;
- case FPUVersion::VFPV3:
- Features.push_back("+vfp3");
- Features.push_back("-fp16");
- Features.push_back("-vfp4");
- Features.push_back("-fp-armv8");
- break;
- case FPUVersion::VFPV2:
- Features.push_back("+vfp2");
- Features.push_back("-vfp3");
- Features.push_back("-fp16");
- Features.push_back("-vfp4");
- Features.push_back("-fp-armv8");
- break;
- case FPUVersion::NONE:
- Features.push_back("-vfp2");
- Features.push_back("-vfp3");
- Features.push_back("-fp16");
- Features.push_back("-vfp4");
- Features.push_back("-fp-armv8");
- break;
- }
-
- // crypto includes neon, so we handle this similarly to FPU version.
- switch (FPUNames[FPUKind].NeonSupport) {
- case NeonSupportLevel::Crypto:
- Features.push_back("+neon");
- Features.push_back("+crypto");
- break;
- case NeonSupportLevel::Neon:
- Features.push_back("+neon");
- Features.push_back("-crypto");
- break;
- case NeonSupportLevel::None:
- Features.push_back("-neon");
- Features.push_back("-crypto");
- break;
- }
-
- return true;
-}
-
-// Little/Big endian
-ARM::EndianKind ARM::parseArchEndian(StringRef Arch) {
- if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
- Arch.startswith("aarch64_be"))
- return EndianKind::BIG;
-
- if (Arch.startswith("arm") || Arch.startswith("thumb")) {
- if (Arch.endswith("eb"))
- return EndianKind::BIG;
- else
- return EndianKind::LITTLE;
- }
-
- if (Arch.startswith("aarch64"))
- return EndianKind::LITTLE;
-
- return EndianKind::INVALID;
-}
-
-// ARM, Thumb, AArch64
-ARM::ISAKind ARM::parseArchISA(StringRef Arch) {
- return StringSwitch<ISAKind>(Arch)
- .StartsWith("aarch64", ISAKind::AARCH64)
- .StartsWith("arm64", ISAKind::AARCH64)
- .StartsWith("thumb", ISAKind::THUMB)
- .StartsWith("arm", ISAKind::ARM)
- .Default(ISAKind::INVALID);
-}
-
-unsigned ARM::parseFPU(StringRef FPU) {
- StringRef Syn = getFPUSynonym(FPU);
- for (const auto F : FPUNames) {
- if (Syn == F.getName())
- return F.ID;
- }
- return FK_INVALID;
-}
-
-ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
- if (FPUKind >= FK_LAST)
- return NeonSupportLevel::None;
- return FPUNames[FPUKind].NeonSupport;
-}
-
-// MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
-// (iwmmxt|xscale)(eb)? is also permitted. If the former, return
-// "v.+", if the latter, return unmodified string, minus 'eb'.
-// If invalid, return empty string.
-StringRef ARM::getCanonicalArchName(StringRef Arch) {
- size_t offset = StringRef::npos;
- StringRef A = Arch;
- StringRef Error = "";
-
- // Begins with "arm" / "thumb", move past it.
- if (A.startswith("arm64"))
- offset = 5;
- else if (A.startswith("arm"))
- offset = 3;
- else if (A.startswith("thumb"))
- offset = 5;
- else if (A.startswith("aarch64")) {
- offset = 7;
- // AArch64 uses "_be", not "eb" suffix.
- if (A.find("eb") != StringRef::npos)
- return Error;
- if (A.substr(offset, 3) == "_be")
- offset += 3;
- }
-
- // Ex. "armebv7", move past the "eb".
- if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
- offset += 2;
- // Or, if it ends with eb ("armv7eb"), chop it off.
- else if (A.endswith("eb"))
- A = A.substr(0, A.size() - 2);
- // Trim the head
- if (offset != StringRef::npos)
- A = A.substr(offset);
-
- // Empty string means offset reached the end, which means it's valid.
- if (A.empty())
- return Arch;
-
- // Only match non-marketing names
- if (offset != StringRef::npos) {
- // Must start with 'vN'.
- if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1])))
- return Error;
- // Can't have an extra 'eb'.
- if (A.find("eb") != StringRef::npos)
- return Error;
- }
-
- // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
- return A;
-}
-
-StringRef ARM::getFPUSynonym(StringRef FPU) {
- return StringSwitch<StringRef>(FPU)
- .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
- .Case("vfp2", "vfpv2")
- .Case("vfp3", "vfpv3")
- .Case("vfp4", "vfpv4")
- .Case("vfp3-d16", "vfpv3-d16")
- .Case("vfp4-d16", "vfpv4-d16")
- .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
- .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
- .Case("fp5-sp-d16", "fpv5-sp-d16")
- .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
- // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
- .Case("neon-vfpv3", "neon")
- .Default(FPU);
-}
-
-StringRef ARM::getFPUName(unsigned FPUKind) {
- if (FPUKind >= FK_LAST)
- return StringRef();
- return FPUNames[FPUKind].getName();
-}
-
-ARM::FPUVersion ARM::getFPUVersion(unsigned FPUKind) {
- if (FPUKind >= FK_LAST)
- return FPUVersion::NONE;
- return FPUNames[FPUKind].FPUVer;
-}
-
-ARM::FPURestriction ARM::getFPURestriction(unsigned FPUKind) {
- if (FPUKind >= FK_LAST)
- return FPURestriction::None;
- return FPUNames[FPUKind].Restriction;
-}
-
-unsigned ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) {
- if (CPU == "generic")
- return ARM::ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
-
- return StringSwitch<unsigned>(CPU)
-#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
- .Case(NAME, DEFAULT_FPU)
-#include "llvm/Support/ARMTargetParser.def"
- .Default(ARM::FK_INVALID);
-}
-
-unsigned ARM::getDefaultExtensions(StringRef CPU, ARM::ArchKind AK) {
- if (CPU == "generic")
- return ARM::ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
-
- return StringSwitch<unsigned>(CPU)
-#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
- .Case(NAME, \
- ARCHNames[static_cast<unsigned>(ArchKind::ID)].ArchBaseExtensions | \
- DEFAULT_EXT)
-#include "llvm/Support/ARMTargetParser.def"
- .Default(ARM::AEK_INVALID);
-}
-
-bool ARM::getHWDivFeatures(unsigned HWDivKind,
- std::vector<StringRef> &Features) {
-
- if (HWDivKind == AEK_INVALID)
- return false;
-
- if (HWDivKind & AEK_HWDIVARM)
- Features.push_back("+hwdiv-arm");
- else
- Features.push_back("-hwdiv-arm");
-
- if (HWDivKind & AEK_HWDIVTHUMB)
- Features.push_back("+hwdiv");
- else
- Features.push_back("-hwdiv");
-
- return true;
-}
-
-bool ARM::getExtensionFeatures(unsigned Extensions,
- std::vector<StringRef> &Features) {
-
- if (Extensions == AEK_INVALID)
- return false;
-
- if (Extensions & AEK_CRC)
- Features.push_back("+crc");
- else
- Features.push_back("-crc");
-
- if (Extensions & AEK_DSP)
- Features.push_back("+dsp");
- else
- Features.push_back("-dsp");
-
- if (Extensions & AEK_FP16FML)
- Features.push_back("+fp16fml");
- else
- Features.push_back("-fp16fml");
-
- if (Extensions & AEK_RAS)
- Features.push_back("+ras");
- else
- Features.push_back("-ras");
-
- if (Extensions & AEK_DOTPROD)
- Features.push_back("+dotprod");
- else
- Features.push_back("-dotprod");
-
- return getHWDivFeatures(Extensions, Features);
-}
-
-StringRef ARM::getArchName(ARM::ArchKind AK) {
- return ARCHNames[static_cast<unsigned>(AK)].getName();
-}
-
-StringRef ARM::getCPUAttr(ARM::ArchKind AK) {
- return ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
-}
-
-StringRef ARM::getSubArch(ARM::ArchKind AK) {
- return ARCHNames[static_cast<unsigned>(AK)].getSubArch();
-}
-
-unsigned ARM::getArchAttr(ARM::ArchKind AK) {
- return ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
-}
-
-StringRef ARM::getArchExtName(unsigned ArchExtKind) {
- for (const auto AE : ARCHExtNames) {
- if (ArchExtKind == AE.ID)
- return AE.getName();
- }
- return StringRef();
-}
-
-StringRef ARM::getArchExtFeature(StringRef ArchExt) {
- if (ArchExt.startswith("no")) {
- StringRef ArchExtBase(ArchExt.substr(2));
- for (const auto AE : ARCHExtNames) {
- if (AE.NegFeature && ArchExtBase == AE.getName())
- return StringRef(AE.NegFeature);
- }
- }
- for (const auto AE : ARCHExtNames) {
- if (AE.Feature && ArchExt == AE.getName())
- return StringRef(AE.Feature);
- }
-
- return StringRef();
-}
-
-StringRef ARM::getHWDivName(unsigned HWDivKind) {
- for (const auto D : HWDivNames) {
- if (HWDivKind == D.ID)
- return D.getName();
- }
- return StringRef();
-}
-
-StringRef ARM::getDefaultCPU(StringRef Arch) {
- ArchKind AK = parseArch(Arch);
- if (AK == ArchKind::INVALID)
- return StringRef();
-
- // Look for multiple AKs to find the default for pair AK+Name.
- for (const auto CPU : CPUNames) {
- if (CPU.ArchID == AK && CPU.Default)
- return CPU.getName();
- }
-
- // If we can't find a default then target the architecture instead
- return "generic";
-}
-
-unsigned ARM::parseHWDiv(StringRef HWDiv) {
- StringRef Syn = getHWDivSynonym(HWDiv);
- for (const auto D : HWDivNames) {
- if (Syn == D.getName())
- return D.ID;
- }
- return AEK_INVALID;
-}
-
-unsigned ARM::parseArchExt(StringRef ArchExt) {
- for (const auto A : ARCHExtNames) {
- if (ArchExt == A.getName())
- return A.ID;
- }
- return AEK_INVALID;
-}
-
-ARM::ArchKind ARM::parseCPUArch(StringRef CPU) {
- for (const auto C : CPUNames) {
- if (CPU == C.getName())
- return C.ArchID;
- }
- return ArchKind::INVALID;
-}
-
-void ARM::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
- for (const CpuNames<ArchKind> &Arch : CPUNames) {
- if (Arch.ArchID != ArchKind::INVALID)
- Values.push_back(Arch.getName());
- }
-}
-
-StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
- StringRef ArchName =
- CPU.empty() ? TT.getArchName() : getArchName(parseCPUArch(CPU));
-
- if (TT.isOSBinFormatMachO()) {
- if (TT.getEnvironment() == Triple::EABI ||
- TT.getOS() == Triple::UnknownOS ||
- parseArchProfile(ArchName) == ProfileKind::M)
- return "aapcs";
- if (TT.isWatchABI())
- return "aapcs16";
- return "apcs-gnu";
- } else if (TT.isOSWindows())
- // FIXME: this is invalid for WindowsCE.
- return "aapcs";
-
- // Select the default based on the platform.
- switch (TT.getEnvironment()) {
- case Triple::Android:
- case Triple::GNUEABI:
- case Triple::GNUEABIHF:
- case Triple::MuslEABI:
- case Triple::MuslEABIHF:
- return "aapcs-linux";
- case Triple::EABIHF:
- case Triple::EABI:
- return "aapcs";
- default:
- if (TT.isOSNetBSD())
- return "apcs-gnu";
- if (TT.isOSOpenBSD())
- return "aapcs-linux";
- return "aapcs";
- }
-}
diff --git a/gnu/llvm/lib/Support/ARMWinEH.cpp b/gnu/llvm/lib/Support/ARMWinEH.cpp
deleted file mode 100644
index 03c150f1150..00000000000
--- a/gnu/llvm/lib/Support/ARMWinEH.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//===-- ARMWinEH.cpp - Windows on ARM EH Support Functions ------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ARMWinEH.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-namespace ARM {
-namespace WinEH {
-std::pair<uint16_t, uint32_t> SavedRegisterMask(const RuntimeFunction &RF) {
- uint8_t NumRegisters = RF.Reg();
- uint8_t RegistersVFP = RF.R();
- uint8_t LinkRegister = RF.L();
- uint8_t ChainedFrame = RF.C();
-
- uint16_t GPRMask = (ChainedFrame << 11) | (LinkRegister << 14);
- uint32_t VFPMask = 0;
-
- if (RegistersVFP)
- VFPMask |= (((1 << ((NumRegisters + 1) % 8)) - 1) << 8);
- else
- GPRMask |= (((1 << (NumRegisters + 1)) - 1) << 4);
-
- if (PrologueFolding(RF))
- GPRMask |= (((1 << (NumRegisters + 1)) - 1) << (~RF.StackAdjust() & 0x3));
-
- return std::make_pair(GPRMask, VFPMask);
-}
-}
-}
-}
-
diff --git a/gnu/llvm/lib/Support/Allocator.cpp b/gnu/llvm/lib/Support/Allocator.cpp
deleted file mode 100644
index f48edac0598..00000000000
--- a/gnu/llvm/lib/Support/Allocator.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//===--- Allocator.cpp - Simple memory allocation abstraction -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the BumpPtrAllocator interface.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-namespace detail {
-
-void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated,
- size_t TotalMemory) {
- errs() << "\nNumber of memory regions: " << NumSlabs << '\n'
- << "Bytes used: " << BytesAllocated << '\n'
- << "Bytes allocated: " << TotalMemory << '\n'
- << "Bytes wasted: " << (TotalMemory - BytesAllocated)
- << " (includes alignment, etc)\n";
-}
-
-} // End namespace detail.
-
-void PrintRecyclerStats(size_t Size,
- size_t Align,
- size_t FreeListSize) {
- errs() << "Recycler element size: " << Size << '\n'
- << "Recycler element alignment: " << Align << '\n'
- << "Number of elements free for recycling: " << FreeListSize << '\n';
-}
-
-}
diff --git a/gnu/llvm/lib/Support/Atomic.cpp b/gnu/llvm/lib/Support/Atomic.cpp
deleted file mode 100644
index 7328a93052c..00000000000
--- a/gnu/llvm/lib/Support/Atomic.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-//===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements atomic operations.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Atomic.h"
-#include "llvm/Config/llvm-config.h"
-
-using namespace llvm;
-
-#if defined(_MSC_VER)
-#include <intrin.h>
-
-// We must include windows.h after intrin.h.
-#include <windows.h>
-#undef MemoryFence
-#endif
-
-#if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210)
-#define GNU_ATOMICS
-#endif
-
-void sys::MemoryFence() {
-#if LLVM_HAS_ATOMICS == 0
- return;
-#else
-# if defined(GNU_ATOMICS)
- __sync_synchronize();
-# elif defined(_MSC_VER)
- MemoryBarrier();
-# else
-# error No memory fence implementation for your platform!
-# endif
-#endif
-}
-
-sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
- sys::cas_flag new_value,
- sys::cas_flag old_value) {
-#if LLVM_HAS_ATOMICS == 0
- sys::cas_flag result = *ptr;
- if (result == old_value)
- *ptr = new_value;
- return result;
-#elif defined(GNU_ATOMICS)
- return __sync_val_compare_and_swap(ptr, old_value, new_value);
-#elif defined(_MSC_VER)
- return InterlockedCompareExchange(ptr, new_value, old_value);
-#else
-# error No compare-and-swap implementation for your platform!
-#endif
-}
diff --git a/gnu/llvm/lib/Support/BinaryStreamError.cpp b/gnu/llvm/lib/Support/BinaryStreamError.cpp
deleted file mode 100644
index cdc811d78d6..00000000000
--- a/gnu/llvm/lib/Support/BinaryStreamError.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-//===- BinaryStreamError.cpp - Error extensions for streams -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/BinaryStreamError.h"
-#include "llvm/Support/ErrorHandling.h"
-
-using namespace llvm;
-
-char BinaryStreamError::ID = 0;
-
-BinaryStreamError::BinaryStreamError(stream_error_code C)
- : BinaryStreamError(C, "") {}
-
-BinaryStreamError::BinaryStreamError(StringRef Context)
- : BinaryStreamError(stream_error_code::unspecified, Context) {}
-
-BinaryStreamError::BinaryStreamError(stream_error_code C, StringRef Context)
- : Code(C) {
- ErrMsg = "Stream Error: ";
- switch (C) {
- case stream_error_code::unspecified:
- ErrMsg += "An unspecified error has occurred.";
- break;
- case stream_error_code::stream_too_short:
- ErrMsg += "The stream is too short to perform the requested operation.";
- break;
- case stream_error_code::invalid_array_size:
- ErrMsg += "The buffer size is not a multiple of the array element size.";
- break;
- case stream_error_code::invalid_offset:
- ErrMsg += "The specified offset is invalid for the current stream.";
- break;
- case stream_error_code::filesystem_error:
- ErrMsg += "An I/O error occurred on the file system.";
- break;
- }
-
- if (!Context.empty()) {
- ErrMsg += " ";
- ErrMsg += Context;
- }
-}
-
-void BinaryStreamError::log(raw_ostream &OS) const { OS << ErrMsg; }
-
-StringRef BinaryStreamError::getErrorMessage() const { return ErrMsg; }
-
-std::error_code BinaryStreamError::convertToErrorCode() const {
- return inconvertibleErrorCode();
-}
diff --git a/gnu/llvm/lib/Support/BinaryStreamReader.cpp b/gnu/llvm/lib/Support/BinaryStreamReader.cpp
deleted file mode 100644
index e00527f2519..00000000000
--- a/gnu/llvm/lib/Support/BinaryStreamReader.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-//===- BinaryStreamReader.cpp - Reads objects from a binary stream --------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/BinaryStreamReader.h"
-
-#include "llvm/Support/BinaryStreamError.h"
-#include "llvm/Support/BinaryStreamRef.h"
-
-using namespace llvm;
-using endianness = llvm::support::endianness;
-
-BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref) : Stream(Ref) {}
-
-BinaryStreamReader::BinaryStreamReader(BinaryStream &Stream) : Stream(Stream) {}
-
-BinaryStreamReader::BinaryStreamReader(ArrayRef<uint8_t> Data,
- endianness Endian)
- : Stream(Data, Endian) {}
-
-BinaryStreamReader::BinaryStreamReader(StringRef Data, endianness Endian)
- : Stream(Data, Endian) {}
-
-Error BinaryStreamReader::readLongestContiguousChunk(
- ArrayRef<uint8_t> &Buffer) {
- if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
- return EC;
- Offset += Buffer.size();
- return Error::success();
-}
-
-Error BinaryStreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
- if (auto EC = Stream.readBytes(Offset, Size, Buffer))
- return EC;
- Offset += Size;
- return Error::success();
-}
-
-Error BinaryStreamReader::readCString(StringRef &Dest) {
- uint32_t OriginalOffset = getOffset();
- uint32_t FoundOffset = 0;
- while (true) {
- uint32_t ThisOffset = getOffset();
- ArrayRef<uint8_t> Buffer;
- if (auto EC = readLongestContiguousChunk(Buffer))
- return EC;
- StringRef S(reinterpret_cast<const char *>(Buffer.begin()), Buffer.size());
- size_t Pos = S.find_first_of('\0');
- if (LLVM_LIKELY(Pos != StringRef::npos)) {
- FoundOffset = Pos + ThisOffset;
- break;
- }
- }
- assert(FoundOffset >= OriginalOffset);
-
- setOffset(OriginalOffset);
- size_t Length = FoundOffset - OriginalOffset;
-
- if (auto EC = readFixedString(Dest, Length))
- return EC;
-
- // Now set the offset back to after the null terminator.
- setOffset(FoundOffset + 1);
- return Error::success();
-}
-
-Error BinaryStreamReader::readWideString(ArrayRef<UTF16> &Dest) {
- uint32_t Length = 0;
- uint32_t OriginalOffset = getOffset();
- const UTF16 *C;
- while (true) {
- if (auto EC = readObject(C))
- return EC;
- if (*C == 0x0000)
- break;
- ++Length;
- }
- uint32_t NewOffset = getOffset();
- setOffset(OriginalOffset);
-
- if (auto EC = readArray(Dest, Length))
- return EC;
- setOffset(NewOffset);
- return Error::success();
-}
-
-Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
- ArrayRef<uint8_t> Bytes;
- if (auto EC = readBytes(Bytes, Length))
- return EC;
- Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
- return Error::success();
-}
-
-Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref) {
- return readStreamRef(Ref, bytesRemaining());
-}
-
-Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
- if (bytesRemaining() < Length)
- return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
- Ref = Stream.slice(Offset, Length);
- Offset += Length;
- return Error::success();
-}
-
-Error BinaryStreamReader::readSubstream(BinarySubstreamRef &Stream,
- uint32_t Size) {
- Stream.Offset = getOffset();
- return readStreamRef(Stream.StreamData, Size);
-}
-
-Error BinaryStreamReader::skip(uint32_t Amount) {
- if (Amount > bytesRemaining())
- return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
- Offset += Amount;
- return Error::success();
-}
-
-Error BinaryStreamReader::padToAlignment(uint32_t Align) {
- uint32_t NewOffset = alignTo(Offset, Align);
- return skip(NewOffset - Offset);
-}
-
-uint8_t BinaryStreamReader::peek() const {
- ArrayRef<uint8_t> Buffer;
- auto EC = Stream.readBytes(Offset, 1, Buffer);
- assert(!EC && "Cannot peek an empty buffer!");
- llvm::consumeError(std::move(EC));
- return Buffer[0];
-}
-
-std::pair<BinaryStreamReader, BinaryStreamReader>
-BinaryStreamReader::split(uint32_t Off) const {
- assert(getLength() >= Off);
-
- BinaryStreamRef First = Stream.drop_front(Offset);
-
- BinaryStreamRef Second = First.drop_front(Off);
- First = First.keep_front(Off);
- BinaryStreamReader W1{First};
- BinaryStreamReader W2{Second};
- return std::make_pair(W1, W2);
-} \ No newline at end of file
diff --git a/gnu/llvm/lib/Support/BinaryStreamRef.cpp b/gnu/llvm/lib/Support/BinaryStreamRef.cpp
deleted file mode 100644
index bdc0f54bf25..00000000000
--- a/gnu/llvm/lib/Support/BinaryStreamRef.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-//===- BinaryStreamRef.cpp - ----------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/BinaryStreamRef.h"
-#include "llvm/Support/BinaryByteStream.h"
-
-using namespace llvm;
-using namespace llvm::support;
-
-namespace {
-
-class ArrayRefImpl : public BinaryStream {
-public:
- ArrayRefImpl(ArrayRef<uint8_t> Data, endianness Endian) : BBS(Data, Endian) {}
-
- llvm::support::endianness getEndian() const override {
- return BBS.getEndian();
- }
- Error readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) override {
- return BBS.readBytes(Offset, Size, Buffer);
- }
- Error readLongestContiguousChunk(uint32_t Offset,
- ArrayRef<uint8_t> &Buffer) override {
- return BBS.readLongestContiguousChunk(Offset, Buffer);
- }
- uint32_t getLength() override { return BBS.getLength(); }
-
-private:
- BinaryByteStream BBS;
-};
-
-class MutableArrayRefImpl : public WritableBinaryStream {
-public:
- MutableArrayRefImpl(MutableArrayRef<uint8_t> Data, endianness Endian)
- : BBS(Data, Endian) {}
-
- // Inherited via WritableBinaryStream
- llvm::support::endianness getEndian() const override {
- return BBS.getEndian();
- }
- Error readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) override {
- return BBS.readBytes(Offset, Size, Buffer);
- }
- Error readLongestContiguousChunk(uint32_t Offset,
- ArrayRef<uint8_t> &Buffer) override {
- return BBS.readLongestContiguousChunk(Offset, Buffer);
- }
- uint32_t getLength() override { return BBS.getLength(); }
-
- Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) override {
- return BBS.writeBytes(Offset, Data);
- }
- Error commit() override { return BBS.commit(); }
-
-private:
- MutableBinaryByteStream BBS;
-};
-}
-
-BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream)
- : BinaryStreamRefBase(Stream) {}
-BinaryStreamRef::BinaryStreamRef(BinaryStream &Stream, uint32_t Offset,
- Optional<uint32_t> Length)
- : BinaryStreamRefBase(Stream, Offset, Length) {}
-BinaryStreamRef::BinaryStreamRef(ArrayRef<uint8_t> Data, endianness Endian)
- : BinaryStreamRefBase(std::make_shared<ArrayRefImpl>(Data, Endian), 0,
- Data.size()) {}
-BinaryStreamRef::BinaryStreamRef(StringRef Data, endianness Endian)
- : BinaryStreamRef(makeArrayRef(Data.bytes_begin(), Data.bytes_end()),
- Endian) {}
-
-Error BinaryStreamRef::readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const {
- if (auto EC = checkOffsetForRead(Offset, Size))
- return EC;
- return BorrowedImpl->readBytes(ViewOffset + Offset, Size, Buffer);
-}
-
-Error BinaryStreamRef::readLongestContiguousChunk(
- uint32_t Offset, ArrayRef<uint8_t> &Buffer) const {
- if (auto EC = checkOffsetForRead(Offset, 1))
- return EC;
-
- if (auto EC =
- BorrowedImpl->readLongestContiguousChunk(ViewOffset + Offset, Buffer))
- return EC;
- // This StreamRef might refer to a smaller window over a larger stream. In
- // that case we will have read out more bytes than we should return, because
- // we should not read past the end of the current view.
- uint32_t MaxLength = getLength() - Offset;
- if (Buffer.size() > MaxLength)
- Buffer = Buffer.slice(0, MaxLength);
- return Error::success();
-}
-
-WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream)
- : BinaryStreamRefBase(Stream) {}
-
-WritableBinaryStreamRef::WritableBinaryStreamRef(WritableBinaryStream &Stream,
- uint32_t Offset,
- Optional<uint32_t> Length)
- : BinaryStreamRefBase(Stream, Offset, Length) {}
-
-WritableBinaryStreamRef::WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data,
- endianness Endian)
- : BinaryStreamRefBase(std::make_shared<MutableArrayRefImpl>(Data, Endian),
- 0, Data.size()) {}
-
-
-Error WritableBinaryStreamRef::writeBytes(uint32_t Offset,
- ArrayRef<uint8_t> Data) const {
- if (auto EC = checkOffsetForWrite(Offset, Data.size()))
- return EC;
-
- return BorrowedImpl->writeBytes(ViewOffset + Offset, Data);
-}
-
-WritableBinaryStreamRef::operator BinaryStreamRef() const {
- return BinaryStreamRef(*BorrowedImpl, ViewOffset, Length);
-}
-
-/// For buffered streams, commits changes to the backing store.
-Error WritableBinaryStreamRef::commit() { return BorrowedImpl->commit(); }
diff --git a/gnu/llvm/lib/Support/BinaryStreamWriter.cpp b/gnu/llvm/lib/Support/BinaryStreamWriter.cpp
deleted file mode 100644
index bfad1280b92..00000000000
--- a/gnu/llvm/lib/Support/BinaryStreamWriter.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-//===- BinaryStreamWriter.cpp - Writes objects to a BinaryStream ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/BinaryStreamWriter.h"
-
-#include "llvm/Support/BinaryStreamError.h"
-#include "llvm/Support/BinaryStreamReader.h"
-#include "llvm/Support/BinaryStreamRef.h"
-
-using namespace llvm;
-
-BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStreamRef Ref)
- : Stream(Ref) {}
-
-BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStream &Stream)
- : Stream(Stream) {}
-
-BinaryStreamWriter::BinaryStreamWriter(MutableArrayRef<uint8_t> Data,
- llvm::support::endianness Endian)
- : Stream(Data, Endian) {}
-
-Error BinaryStreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
- if (auto EC = Stream.writeBytes(Offset, Buffer))
- return EC;
- Offset += Buffer.size();
- return Error::success();
-}
-
-Error BinaryStreamWriter::writeCString(StringRef Str) {
- if (auto EC = writeFixedString(Str))
- return EC;
- if (auto EC = writeObject('\0'))
- return EC;
-
- return Error::success();
-}
-
-Error BinaryStreamWriter::writeFixedString(StringRef Str) {
-
- return writeBytes(arrayRefFromStringRef(Str));
-}
-
-Error BinaryStreamWriter::writeStreamRef(BinaryStreamRef Ref) {
- return writeStreamRef(Ref, Ref.getLength());
-}
-
-Error BinaryStreamWriter::writeStreamRef(BinaryStreamRef Ref, uint32_t Length) {
- BinaryStreamReader SrcReader(Ref.slice(0, Length));
- // This is a bit tricky. If we just call readBytes, we are requiring that it
- // return us the entire stream as a contiguous buffer. There is no guarantee
- // this can be satisfied by returning a reference straight from the buffer, as
- // an implementation may not store all data in a single contiguous buffer. So
- // we iterate over each contiguous chunk, writing each one in succession.
- while (SrcReader.bytesRemaining() > 0) {
- ArrayRef<uint8_t> Chunk;
- if (auto EC = SrcReader.readLongestContiguousChunk(Chunk))
- return EC;
- if (auto EC = writeBytes(Chunk))
- return EC;
- }
- return Error::success();
-}
-
-std::pair<BinaryStreamWriter, BinaryStreamWriter>
-BinaryStreamWriter::split(uint32_t Off) const {
- assert(getLength() >= Off);
-
- WritableBinaryStreamRef First = Stream.drop_front(Offset);
-
- WritableBinaryStreamRef Second = First.drop_front(Off);
- First = First.keep_front(Off);
- BinaryStreamWriter W1{First};
- BinaryStreamWriter W2{Second};
- return std::make_pair(W1, W2);
-}
-
-Error BinaryStreamWriter::padToAlignment(uint32_t Align) {
- uint32_t NewOffset = alignTo(Offset, Align);
- if (NewOffset > getLength())
- return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
- while (Offset < NewOffset)
- if (auto EC = writeInteger('\0'))
- return EC;
- return Error::success();
-}
diff --git a/gnu/llvm/lib/Support/BlockFrequency.cpp b/gnu/llvm/lib/Support/BlockFrequency.cpp
deleted file mode 100644
index 34fcbde23a2..00000000000
--- a/gnu/llvm/lib/Support/BlockFrequency.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-//====--------------- lib/Support/BlockFrequency.cpp -----------*- C++ -*-====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements Block Frequency class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/BlockFrequency.h"
-#include <cassert>
-
-using namespace llvm;
-
-BlockFrequency &BlockFrequency::operator*=(BranchProbability Prob) {
- Frequency = Prob.scale(Frequency);
- return *this;
-}
-
-BlockFrequency BlockFrequency::operator*(BranchProbability Prob) const {
- BlockFrequency Freq(Frequency);
- Freq *= Prob;
- return Freq;
-}
-
-BlockFrequency &BlockFrequency::operator/=(BranchProbability Prob) {
- Frequency = Prob.scaleByInverse(Frequency);
- return *this;
-}
-
-BlockFrequency BlockFrequency::operator/(BranchProbability Prob) const {
- BlockFrequency Freq(Frequency);
- Freq /= Prob;
- return Freq;
-}
-
-BlockFrequency &BlockFrequency::operator+=(BlockFrequency Freq) {
- uint64_t Before = Freq.Frequency;
- Frequency += Freq.Frequency;
-
- // If overflow, set frequency to the maximum value.
- if (Frequency < Before)
- Frequency = UINT64_MAX;
-
- return *this;
-}
-
-BlockFrequency BlockFrequency::operator+(BlockFrequency Freq) const {
- BlockFrequency NewFreq(Frequency);
- NewFreq += Freq;
- return NewFreq;
-}
-
-BlockFrequency &BlockFrequency::operator-=(BlockFrequency Freq) {
- // If underflow, set frequency to 0.
- if (Frequency <= Freq.Frequency)
- Frequency = 0;
- else
- Frequency -= Freq.Frequency;
- return *this;
-}
-
-BlockFrequency BlockFrequency::operator-(BlockFrequency Freq) const {
- BlockFrequency NewFreq(Frequency);
- NewFreq -= Freq;
- return NewFreq;
-}
-
-BlockFrequency &BlockFrequency::operator>>=(const unsigned count) {
- // Frequency can never be 0 by design.
- assert(Frequency != 0);
-
- // Shift right by count.
- Frequency >>= count;
-
- // Saturate to 1 if we are 0.
- Frequency |= Frequency == 0;
- return *this;
-}
diff --git a/gnu/llvm/lib/Support/BranchProbability.cpp b/gnu/llvm/lib/Support/BranchProbability.cpp
deleted file mode 100644
index 31dee9561f4..00000000000
--- a/gnu/llvm/lib/Support/BranchProbability.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-//===-------------- lib/Support/BranchProbability.cpp -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements Branch Probability class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/BranchProbability.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-
-using namespace llvm;
-
-const uint32_t BranchProbability::D;
-
-raw_ostream &BranchProbability::print(raw_ostream &OS) const {
- if (isUnknown())
- return OS << "?%";
-
- // Get a percentage rounded to two decimal digits. This avoids
- // implementation-defined rounding inside printf.
- double Percent = rint(((double)N / D) * 100.0 * 100.0) / 100.0;
- return OS << format("0x%08" PRIx32 " / 0x%08" PRIx32 " = %.2f%%", N, D,
- Percent);
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void BranchProbability::dump() const { print(dbgs()) << '\n'; }
-#endif
-
-BranchProbability::BranchProbability(uint32_t Numerator, uint32_t Denominator) {
- assert(Denominator > 0 && "Denominator cannot be 0!");
- assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");
- if (Denominator == D)
- N = Numerator;
- else {
- uint64_t Prob64 =
- (Numerator * static_cast<uint64_t>(D) + Denominator / 2) / Denominator;
- N = static_cast<uint32_t>(Prob64);
- }
-}
-
-BranchProbability
-BranchProbability::getBranchProbability(uint64_t Numerator,
- uint64_t Denominator) {
- assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");
- // Scale down Denominator to fit in a 32-bit integer.
- int Scale = 0;
- while (Denominator > UINT32_MAX) {
- Denominator >>= 1;
- Scale++;
- }
- return BranchProbability(Numerator >> Scale, Denominator);
-}
-
-// If ConstD is not zero, then replace D by ConstD so that division and modulo
-// operations by D can be optimized, in case this function is not inlined by the
-// compiler.
-template <uint32_t ConstD>
-static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D) {
- if (ConstD > 0)
- D = ConstD;
-
- assert(D && "divide by 0");
-
- // Fast path for multiplying by 1.0.
- if (!Num || D == N)
- return Num;
-
- // Split Num into upper and lower parts to multiply, then recombine.
- uint64_t ProductHigh = (Num >> 32) * N;
- uint64_t ProductLow = (Num & UINT32_MAX) * N;
-
- // Split into 32-bit digits.
- uint32_t Upper32 = ProductHigh >> 32;
- uint32_t Lower32 = ProductLow & UINT32_MAX;
- uint32_t Mid32Partial = ProductHigh & UINT32_MAX;
- uint32_t Mid32 = Mid32Partial + (ProductLow >> 32);
-
- // Carry.
- Upper32 += Mid32 < Mid32Partial;
-
- // Check for overflow.
- if (Upper32 >= D)
- return UINT64_MAX;
-
- uint64_t Rem = (uint64_t(Upper32) << 32) | Mid32;
- uint64_t UpperQ = Rem / D;
-
- // Check for overflow.
- if (UpperQ > UINT32_MAX)
- return UINT64_MAX;
-
- Rem = ((Rem % D) << 32) | Lower32;
- uint64_t LowerQ = Rem / D;
- uint64_t Q = (UpperQ << 32) + LowerQ;
-
- // Check for overflow.
- return Q < LowerQ ? UINT64_MAX : Q;
-}
-
-uint64_t BranchProbability::scale(uint64_t Num) const {
- return ::scale<D>(Num, N, D);
-}
-
-uint64_t BranchProbability::scaleByInverse(uint64_t Num) const {
- return ::scale<0>(Num, D, N);
-}
diff --git a/gnu/llvm/lib/Support/BuryPointer.cpp b/gnu/llvm/lib/Support/BuryPointer.cpp
deleted file mode 100644
index 6c988b4a0ab..00000000000
--- a/gnu/llvm/lib/Support/BuryPointer.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- BuryPointer.cpp - Memory Manipulation/Leak ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/BuryPointer.h"
-#include "llvm/Support/Compiler.h"
-#include <atomic>
-
-namespace llvm {
-
-void BuryPointer(const void *Ptr) {
- // This function may be called only a small fixed amount of times per each
- // invocation, otherwise we do actually have a leak which we want to report.
- // If this function is called more than kGraveYardMaxSize times, the pointers
- // will not be properly buried and a leak detector will report a leak, which
- // is what we want in such case.
- static const size_t kGraveYardMaxSize = 16;
- LLVM_ATTRIBUTE_UNUSED static const void *GraveYard[kGraveYardMaxSize];
- static std::atomic<unsigned> GraveYardSize;
- unsigned Idx = GraveYardSize++;
- if (Idx >= kGraveYardMaxSize)
- return;
- GraveYard[Idx] = Ptr;
-}
-
-}
diff --git a/gnu/llvm/lib/Support/CMakeLists.txt b/gnu/llvm/lib/Support/CMakeLists.txt
deleted file mode 100644
index 2a6810672b1..00000000000
--- a/gnu/llvm/lib/Support/CMakeLists.txt
+++ /dev/null
@@ -1,181 +0,0 @@
-set(system_libs)
-if ( LLVM_ENABLE_ZLIB AND HAVE_LIBZ )
- set(system_libs ${system_libs} ${ZLIB_LIBRARIES})
-endif()
-if( MSVC OR MINGW )
- # libuuid required for FOLDERID_Profile usage in lib/Support/Windows/Path.inc.
- # advapi32 required for CryptAcquireContextW in lib/Support/Windows/Path.inc.
- set(system_libs ${system_libs} psapi shell32 ole32 uuid advapi32)
-elseif( CMAKE_HOST_UNIX )
- if( HAVE_LIBRT )
- set(system_libs ${system_libs} rt)
- endif()
- if( HAVE_LIBDL )
- set(system_libs ${system_libs} ${CMAKE_DL_LIBS})
- endif()
- if( HAVE_BACKTRACE AND NOT "${Backtrace_LIBRARIES}" STREQUAL "" )
- # On BSDs, CMake returns a fully qualified path to the backtrace library.
- # We need to remove the path and the 'lib' prefix, to make it look like a
- # regular short library name, suitable for appending to a -l link flag.
- get_filename_component(Backtrace_LIBFILE ${Backtrace_LIBRARIES} NAME_WE)
- STRING(REGEX REPLACE "^lib" "" Backtrace_LIBFILE ${Backtrace_LIBFILE})
- set(system_libs ${system_libs} ${Backtrace_LIBFILE})
- endif()
- if(LLVM_ENABLE_TERMINFO)
- if(HAVE_TERMINFO)
- set(system_libs ${system_libs} ${TERMINFO_LIBS})
- endif()
- endif()
- if( LLVM_ENABLE_THREADS AND HAVE_LIBATOMIC )
- set(system_libs ${system_libs} atomic)
- endif()
- set(system_libs ${system_libs} ${LLVM_PTHREAD_LIB})
- if( UNIX AND NOT (BEOS OR HAIKU) )
- set(system_libs ${system_libs} m)
- endif()
- if( FUCHSIA )
- set(system_libs ${system_libs} zircon)
- endif()
-endif( MSVC OR MINGW )
-
-# Delay load shell32.dll if possible to speed up process startup.
-set (delayload_flags)
-if (MSVC)
- set (delayload_flags delayimp -delayload:shell32.dll -delayload:ole32.dll)
-endif()
-
-add_llvm_library(LLVMSupport
- AArch64TargetParser.cpp
- ARMTargetParser.cpp
- AMDGPUMetadata.cpp
- APFloat.cpp
- APInt.cpp
- APSInt.cpp
- ARMBuildAttrs.cpp
- ARMAttributeParser.cpp
- ARMWinEH.cpp
- Allocator.cpp
- BinaryStreamError.cpp
- BinaryStreamReader.cpp
- BinaryStreamRef.cpp
- BinaryStreamWriter.cpp
- BlockFrequency.cpp
- BranchProbability.cpp
- BuryPointer.cpp
- CachePruning.cpp
- circular_raw_ostream.cpp
- Chrono.cpp
- COM.cpp
- CodeGenCoverage.cpp
- CommandLine.cpp
- Compression.cpp
- ConvertUTF.cpp
- ConvertUTFWrapper.cpp
- CrashRecoveryContext.cpp
- DataExtractor.cpp
- Debug.cpp
- DebugCounter.cpp
- DeltaAlgorithm.cpp
- DAGDeltaAlgorithm.cpp
- DJB.cpp
- Error.cpp
- ErrorHandling.cpp
- FileCheck.cpp
- FileUtilities.cpp
- FileOutputBuffer.cpp
- FoldingSet.cpp
- FormattedStream.cpp
- FormatVariadic.cpp
- GlobPattern.cpp
- GraphWriter.cpp
- Hashing.cpp
- InitLLVM.cpp
- IntEqClasses.cpp
- IntervalMap.cpp
- ItaniumManglingCanonicalizer.cpp
- JamCRC.cpp
- JSON.cpp
- KnownBits.cpp
- LEB128.cpp
- LineIterator.cpp
- Locale.cpp
- LockFileManager.cpp
- LowLevelType.cpp
- ManagedStatic.cpp
- MathExtras.cpp
- MemoryBuffer.cpp
- MD5.cpp
- NativeFormatting.cpp
- Options.cpp
- Parallel.cpp
- PluginLoader.cpp
- PrettyStackTrace.cpp
- RandomNumberGenerator.cpp
- Regex.cpp
- ScaledNumber.cpp
- ScopedPrinter.cpp
- SHA1.cpp
- SmallPtrSet.cpp
- SmallVector.cpp
- SourceMgr.cpp
- SpecialCaseList.cpp
- Statistic.cpp
- StringExtras.cpp
- StringMap.cpp
- StringPool.cpp
- StringSaver.cpp
- StringRef.cpp
- SymbolRemappingReader.cpp
- SystemUtils.cpp
- TarWriter.cpp
- TargetParser.cpp
- ThreadPool.cpp
- Timer.cpp
- ToolOutputFile.cpp
- TrigramIndex.cpp
- Triple.cpp
- Twine.cpp
- Unicode.cpp
- UnicodeCaseFold.cpp
- VersionTuple.cpp
- VirtualFileSystem.cpp
- WithColor.cpp
- YAMLParser.cpp
- YAMLTraits.cpp
- raw_os_ostream.cpp
- raw_ostream.cpp
- regcomp.c
- regerror.c
- regexec.c
- regfree.c
- regstrlcpy.c
- xxhash.cpp
-
-# System
- Atomic.cpp
- DynamicLibrary.cpp
- Errno.cpp
- Host.cpp
- Memory.cpp
- Mutex.cpp
- Path.cpp
- Process.cpp
- Program.cpp
- RWMutex.cpp
- Signals.cpp
- TargetRegistry.cpp
- ThreadLocal.cpp
- Threading.cpp
- Valgrind.cpp
- Watchdog.cpp
-
- ADDITIONAL_HEADER_DIRS
- Unix
- Windows
- ${LLVM_MAIN_INCLUDE_DIR}/llvm/ADT
- ${LLVM_MAIN_INCLUDE_DIR}/llvm/Support
- ${Backtrace_INCLUDE_DIRS}
- LINK_LIBS ${system_libs} ${delayload_flags}
- )
-
-set_property(TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS "${system_libs}")
diff --git a/gnu/llvm/lib/Support/COM.cpp b/gnu/llvm/lib/Support/COM.cpp
deleted file mode 100644
index 97cd085853b..00000000000
--- a/gnu/llvm/lib/Support/COM.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//===-- COM.cpp - Implement COM utility classes -----------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements utility classes related to COM.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/COM.h"
-
-#include "llvm/Config/llvm-config.h"
-
-// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
-#include "Unix/COM.inc"
-#elif defined(_WIN32)
-#include "Windows/COM.inc"
-#endif
diff --git a/gnu/llvm/lib/Support/COPYRIGHT.regex b/gnu/llvm/lib/Support/COPYRIGHT.regex
deleted file mode 100644
index 36fd346e08b..00000000000
--- a/gnu/llvm/lib/Support/COPYRIGHT.regex
+++ /dev/null
@@ -1,54 +0,0 @@
-$OpenBSD: COPYRIGHT.regex,v 1.1.1.1 2016/09/03 22:47:02 pascal Exp $
-
-Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved.
-This software is not subject to any license of the American Telephone
-and Telegraph Company or of the Regents of the University of California.
-
-Permission is granted to anyone to use this software for any purpose on
-any computer system, and to alter it and redistribute it, subject
-to the following restrictions:
-
-1. The author is not responsible for the consequences of use of this
- software, no matter how awful, even if they arise from flaws in it.
-
-2. The origin of this software must not be misrepresented, either by
- explicit claim or by omission. Since few users ever read sources,
- credits must appear in the documentation.
-
-3. Altered versions must be plainly marked as such, and must not be
- misrepresented as being the original software. Since few users
- ever read sources, credits must appear in the documentation.
-
-4. This notice may not be removed or altered.
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-/*-
- * Copyright (c) 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)COPYRIGHT 8.1 (Berkeley) 3/16/94
- */
diff --git a/gnu/llvm/lib/Support/CachePruning.cpp b/gnu/llvm/lib/Support/CachePruning.cpp
deleted file mode 100644
index a0aa6024b3e..00000000000
--- a/gnu/llvm/lib/Support/CachePruning.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-//===-CachePruning.cpp - LLVM Cache Directory Pruning ---------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the pruning of a directory based on least recently used.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/CachePruning.h"
-
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-
-#define DEBUG_TYPE "cache-pruning"
-
-#include <set>
-#include <system_error>
-
-using namespace llvm;
-
-namespace {
-struct FileInfo {
- sys::TimePoint<> Time;
- uint64_t Size;
- std::string Path;
-
- /// Used to determine which files to prune first. Also used to determine
- /// set membership, so must take into account all fields.
- bool operator<(const FileInfo &Other) const {
- if (Time < Other.Time)
- return true;
- else if (Other.Time < Time)
- return false;
- if (Other.Size < Size)
- return true;
- else if (Size < Other.Size)
- return false;
- return Path < Other.Path;
- }
-};
-} // anonymous namespace
-
-/// Write a new timestamp file with the given path. This is used for the pruning
-/// interval option.
-static void writeTimestampFile(StringRef TimestampFile) {
- std::error_code EC;
- raw_fd_ostream Out(TimestampFile.str(), EC, sys::fs::F_None);
-}
-
-static Expected<std::chrono::seconds> parseDuration(StringRef Duration) {
- if (Duration.empty())
- return make_error<StringError>("Duration must not be empty",
- inconvertibleErrorCode());
-
- StringRef NumStr = Duration.slice(0, Duration.size()-1);
- uint64_t Num;
- if (NumStr.getAsInteger(0, Num))
- return make_error<StringError>("'" + NumStr + "' not an integer",
- inconvertibleErrorCode());
-
- switch (Duration.back()) {
- case 's':
- return std::chrono::seconds(Num);
- case 'm':
- return std::chrono::minutes(Num);
- case 'h':
- return std::chrono::hours(Num);
- default:
- return make_error<StringError>("'" + Duration +
- "' must end with one of 's', 'm' or 'h'",
- inconvertibleErrorCode());
- }
-}
-
-Expected<CachePruningPolicy>
-llvm::parseCachePruningPolicy(StringRef PolicyStr) {
- CachePruningPolicy Policy;
- std::pair<StringRef, StringRef> P = {"", PolicyStr};
- while (!P.second.empty()) {
- P = P.second.split(':');
-
- StringRef Key, Value;
- std::tie(Key, Value) = P.first.split('=');
- if (Key == "prune_interval") {
- auto DurationOrErr = parseDuration(Value);
- if (!DurationOrErr)
- return DurationOrErr.takeError();
- Policy.Interval = *DurationOrErr;
- } else if (Key == "prune_after") {
- auto DurationOrErr = parseDuration(Value);
- if (!DurationOrErr)
- return DurationOrErr.takeError();
- Policy.Expiration = *DurationOrErr;
- } else if (Key == "cache_size") {
- if (Value.back() != '%')
- return make_error<StringError>("'" + Value + "' must be a percentage",
- inconvertibleErrorCode());
- StringRef SizeStr = Value.drop_back();
- uint64_t Size;
- if (SizeStr.getAsInteger(0, Size))
- return make_error<StringError>("'" + SizeStr + "' not an integer",
- inconvertibleErrorCode());
- if (Size > 100)
- return make_error<StringError>("'" + SizeStr +
- "' must be between 0 and 100",
- inconvertibleErrorCode());
- Policy.MaxSizePercentageOfAvailableSpace = Size;
- } else if (Key == "cache_size_bytes") {
- uint64_t Mult = 1;
- switch (tolower(Value.back())) {
- case 'k':
- Mult = 1024;
- Value = Value.drop_back();
- break;
- case 'm':
- Mult = 1024 * 1024;
- Value = Value.drop_back();
- break;
- case 'g':
- Mult = 1024 * 1024 * 1024;
- Value = Value.drop_back();
- break;
- }
- uint64_t Size;
- if (Value.getAsInteger(0, Size))
- return make_error<StringError>("'" + Value + "' not an integer",
- inconvertibleErrorCode());
- Policy.MaxSizeBytes = Size * Mult;
- } else if (Key == "cache_size_files") {
- if (Value.getAsInteger(0, Policy.MaxSizeFiles))
- return make_error<StringError>("'" + Value + "' not an integer",
- inconvertibleErrorCode());
- } else {
- return make_error<StringError>("Unknown key: '" + Key + "'",
- inconvertibleErrorCode());
- }
- }
-
- return Policy;
-}
-
-/// Prune the cache of files that haven't been accessed in a long time.
-bool llvm::pruneCache(StringRef Path, CachePruningPolicy Policy) {
- using namespace std::chrono;
-
- if (Path.empty())
- return false;
-
- bool isPathDir;
- if (sys::fs::is_directory(Path, isPathDir))
- return false;
-
- if (!isPathDir)
- return false;
-
- Policy.MaxSizePercentageOfAvailableSpace =
- std::min(Policy.MaxSizePercentageOfAvailableSpace, 100u);
-
- if (Policy.Expiration == seconds(0) &&
- Policy.MaxSizePercentageOfAvailableSpace == 0 &&
- Policy.MaxSizeBytes == 0 && Policy.MaxSizeFiles == 0) {
- LLVM_DEBUG(dbgs() << "No pruning settings set, exit early\n");
- // Nothing will be pruned, early exit
- return false;
- }
-
- // Try to stat() the timestamp file.
- SmallString<128> TimestampFile(Path);
- sys::path::append(TimestampFile, "llvmcache.timestamp");
- sys::fs::file_status FileStatus;
- const auto CurrentTime = system_clock::now();
- if (auto EC = sys::fs::status(TimestampFile, FileStatus)) {
- if (EC == errc::no_such_file_or_directory) {
- // If the timestamp file wasn't there, create one now.
- writeTimestampFile(TimestampFile);
- } else {
- // Unknown error?
- return false;
- }
- } else {
- if (!Policy.Interval)
- return false;
- if (Policy.Interval != seconds(0)) {
- // Check whether the time stamp is older than our pruning interval.
- // If not, do nothing.
- const auto TimeStampModTime = FileStatus.getLastModificationTime();
- auto TimeStampAge = CurrentTime - TimeStampModTime;
- if (TimeStampAge <= *Policy.Interval) {
- LLVM_DEBUG(dbgs() << "Timestamp file too recent ("
- << duration_cast<seconds>(TimeStampAge).count()
- << "s old), do not prune.\n");
- return false;
- }
- }
- // Write a new timestamp file so that nobody else attempts to prune.
- // There is a benign race condition here, if two processes happen to
- // notice at the same time that the timestamp is out-of-date.
- writeTimestampFile(TimestampFile);
- }
-
- // Keep track of files to delete to get below the size limit.
- // Order by time of last use so that recently used files are preserved.
- std::set<FileInfo> FileInfos;
- uint64_t TotalSize = 0;
-
- // Walk the entire directory cache, looking for unused files.
- std::error_code EC;
- SmallString<128> CachePathNative;
- sys::path::native(Path, CachePathNative);
- // Walk all of the files within this directory.
- for (sys::fs::directory_iterator File(CachePathNative, EC), FileEnd;
- File != FileEnd && !EC; File.increment(EC)) {
- // Ignore any files not beginning with the string "llvmcache-". This
- // includes the timestamp file as well as any files created by the user.
- // This acts as a safeguard against data loss if the user specifies the
- // wrong directory as their cache directory.
- if (!sys::path::filename(File->path()).startswith("llvmcache-"))
- continue;
-
- // Look at this file. If we can't stat it, there's nothing interesting
- // there.
- ErrorOr<sys::fs::basic_file_status> StatusOrErr = File->status();
- if (!StatusOrErr) {
- LLVM_DEBUG(dbgs() << "Ignore " << File->path() << " (can't stat)\n");
- continue;
- }
-
- // If the file hasn't been used recently enough, delete it
- const auto FileAccessTime = StatusOrErr->getLastAccessedTime();
- auto FileAge = CurrentTime - FileAccessTime;
- if (Policy.Expiration != seconds(0) && FileAge > Policy.Expiration) {
- LLVM_DEBUG(dbgs() << "Remove " << File->path() << " ("
- << duration_cast<seconds>(FileAge).count()
- << "s old)\n");
- sys::fs::remove(File->path());
- continue;
- }
-
- // Leave it here for now, but add it to the list of size-based pruning.
- TotalSize += StatusOrErr->getSize();
- FileInfos.insert({FileAccessTime, StatusOrErr->getSize(), File->path()});
- }
-
- auto FileInfo = FileInfos.begin();
- size_t NumFiles = FileInfos.size();
-
- auto RemoveCacheFile = [&]() {
- // Remove the file.
- sys::fs::remove(FileInfo->Path);
- // Update size
- TotalSize -= FileInfo->Size;
- NumFiles--;
- LLVM_DEBUG(dbgs() << " - Remove " << FileInfo->Path << " (size "
- << FileInfo->Size << "), new occupancy is " << TotalSize
- << "%\n");
- ++FileInfo;
- };
-
- // Prune for number of files.
- if (Policy.MaxSizeFiles)
- while (NumFiles > Policy.MaxSizeFiles)
- RemoveCacheFile();
-
- // Prune for size now if needed
- if (Policy.MaxSizePercentageOfAvailableSpace > 0 || Policy.MaxSizeBytes > 0) {
- auto ErrOrSpaceInfo = sys::fs::disk_space(Path);
- if (!ErrOrSpaceInfo) {
- report_fatal_error("Can't get available size");
- }
- sys::fs::space_info SpaceInfo = ErrOrSpaceInfo.get();
- auto AvailableSpace = TotalSize + SpaceInfo.free;
-
- if (Policy.MaxSizePercentageOfAvailableSpace == 0)
- Policy.MaxSizePercentageOfAvailableSpace = 100;
- if (Policy.MaxSizeBytes == 0)
- Policy.MaxSizeBytes = AvailableSpace;
- auto TotalSizeTarget = std::min<uint64_t>(
- AvailableSpace * Policy.MaxSizePercentageOfAvailableSpace / 100ull,
- Policy.MaxSizeBytes);
-
- LLVM_DEBUG(dbgs() << "Occupancy: " << ((100 * TotalSize) / AvailableSpace)
- << "% target is: "
- << Policy.MaxSizePercentageOfAvailableSpace << "%, "
- << Policy.MaxSizeBytes << " bytes\n");
-
- // Remove the oldest accessed files first, till we get below the threshold.
- while (TotalSize > TotalSizeTarget && FileInfo != FileInfos.end())
- RemoveCacheFile();
- }
- return true;
-}
diff --git a/gnu/llvm/lib/Support/Chrono.cpp b/gnu/llvm/lib/Support/Chrono.cpp
deleted file mode 100644
index a2626a89eb6..00000000000
--- a/gnu/llvm/lib/Support/Chrono.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-//===- Support/Chrono.cpp - Utilities for Timing Manipulation ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Chrono.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-using namespace sys;
-
-const char llvm::detail::unit<std::ratio<3600>>::value[] = "h";
-const char llvm::detail::unit<std::ratio<60>>::value[] = "m";
-const char llvm::detail::unit<std::ratio<1>>::value[] = "s";
-const char llvm::detail::unit<std::milli>::value[] = "ms";
-const char llvm::detail::unit<std::micro>::value[] = "us";
-const char llvm::detail::unit<std::nano>::value[] = "ns";
-
-static inline struct tm getStructTM(TimePoint<> TP) {
- struct tm Storage;
- std::time_t OurTime = toTimeT(TP);
-
-#if defined(LLVM_ON_UNIX)
- struct tm *LT = ::localtime_r(&OurTime, &Storage);
- assert(LT);
- (void)LT;
-#endif
-#if defined(_WIN32)
- int Error = ::localtime_s(&Storage, &OurTime);
- assert(!Error);
- (void)Error;
-#endif
-
- return Storage;
-}
-
-raw_ostream &operator<<(raw_ostream &OS, TimePoint<> TP) {
- struct tm LT = getStructTM(TP);
- char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")];
- strftime(Buffer, sizeof(Buffer), "%Y-%m-%d %H:%M:%S", &LT);
- return OS << Buffer << '.'
- << format("%.9lu",
- long((TP.time_since_epoch() % std::chrono::seconds(1))
- .count()));
-}
-
-void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
- StringRef Style) {
- using namespace std::chrono;
- TimePoint<seconds> Truncated = time_point_cast<seconds>(T);
- auto Fractional = T - Truncated;
- struct tm LT = getStructTM(Truncated);
- // Handle extensions first. strftime mangles unknown %x on some platforms.
- if (Style.empty()) Style = "%Y-%m-%d %H:%M:%S.%N";
- std::string Format;
- raw_string_ostream FStream(Format);
- for (unsigned I = 0; I < Style.size(); ++I) {
- if (Style[I] == '%' && Style.size() > I + 1) switch (Style[I + 1]) {
- case 'L': // Milliseconds, from Ruby.
- FStream << llvm::format(
- "%.3lu", (long)duration_cast<milliseconds>(Fractional).count());
- ++I;
- continue;
- case 'f': // Microseconds, from Python.
- FStream << llvm::format(
- "%.6lu", (long)duration_cast<microseconds>(Fractional).count());
- ++I;
- continue;
- case 'N': // Nanoseconds, from date(1).
- FStream << llvm::format(
- "%.6lu", (long)duration_cast<nanoseconds>(Fractional).count());
- ++I;
- continue;
- case '%': // Consume %%, so %%f parses as (%%)f not %(%f)
- FStream << "%%";
- ++I;
- continue;
- }
- FStream << Style[I];
- }
- FStream.flush();
- char Buffer[256]; // Should be enough for anywhen.
- size_t Len = strftime(Buffer, sizeof(Buffer), Format.c_str(), &LT);
- OS << (Len ? Buffer : "BAD-DATE-FORMAT");
-}
-
-} // namespace llvm
diff --git a/gnu/llvm/lib/Support/CodeGenCoverage.cpp b/gnu/llvm/lib/Support/CodeGenCoverage.cpp
deleted file mode 100644
index 811020e3254..00000000000
--- a/gnu/llvm/lib/Support/CodeGenCoverage.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-//===- lib/Support/CodeGenCoverage.cpp -------------------------------------==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-/// \file
-/// This file implements the CodeGenCoverage class.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/CodeGenCoverage.h"
-
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/ScopedPrinter.h"
-#include "llvm/Support/ToolOutputFile.h"
-
-#if LLVM_ON_UNIX
-#include <unistd.h>
-#elif defined(_WIN32)
-#include <windows.h>
-#endif
-
-using namespace llvm;
-
-static sys::SmartMutex<true> OutputMutex;
-
-CodeGenCoverage::CodeGenCoverage() {}
-
-void CodeGenCoverage::setCovered(uint64_t RuleID) {
- if (RuleCoverage.size() <= RuleID)
- RuleCoverage.resize(RuleID + 1, 0);
- RuleCoverage[RuleID] = true;
-}
-
-bool CodeGenCoverage::isCovered(uint64_t RuleID) const {
- if (RuleCoverage.size() <= RuleID)
- return false;
- return RuleCoverage[RuleID];
-}
-
-iterator_range<CodeGenCoverage::const_covered_iterator>
-CodeGenCoverage::covered() const {
- return RuleCoverage.set_bits();
-}
-
-bool CodeGenCoverage::parse(MemoryBuffer &Buffer, StringRef BackendName) {
- const char *CurPtr = Buffer.getBufferStart();
-
- while (CurPtr != Buffer.getBufferEnd()) {
- // Read the backend name from the input.
- const char *LexedBackendName = CurPtr;
- while (*CurPtr++ != 0)
- ;
- if (CurPtr == Buffer.getBufferEnd())
- return false; // Data is invalid, expected rule id's to follow.
-
- bool IsForThisBackend = BackendName.equals(LexedBackendName);
- while (CurPtr != Buffer.getBufferEnd()) {
- if (std::distance(CurPtr, Buffer.getBufferEnd()) < 8)
- return false; // Data is invalid. Not enough bytes for another rule id.
-
- uint64_t RuleID = support::endian::read64(CurPtr, support::native);
- CurPtr += 8;
-
- // ~0ull terminates the rule id list.
- if (RuleID == ~0ull)
- break;
-
- // Anything else, is recorded or ignored depending on whether it's
- // intended for the backend we're interested in.
- if (IsForThisBackend)
- setCovered(RuleID);
- }
- }
-
- return true;
-}
-
-bool CodeGenCoverage::emit(StringRef CoveragePrefix,
- StringRef BackendName) const {
- if (!CoveragePrefix.empty() && !RuleCoverage.empty()) {
- sys::SmartScopedLock<true> Lock(OutputMutex);
-
- // We can handle locking within a process easily enough but we don't want to
- // manage it between multiple processes. Use the process ID to ensure no
- // more than one process is ever writing to the same file at the same time.
- std::string Pid =
-#if LLVM_ON_UNIX
- llvm::to_string(::getpid());
-#elif defined(_WIN32)
- llvm::to_string(::GetCurrentProcessId());
-#else
- "";
-#endif
-
- std::string CoverageFilename = (CoveragePrefix + Pid).str();
-
- std::error_code EC;
- sys::fs::OpenFlags OpenFlags = sys::fs::F_Append;
- std::unique_ptr<ToolOutputFile> CoverageFile =
- llvm::make_unique<ToolOutputFile>(CoverageFilename, EC, OpenFlags);
- if (EC)
- return false;
-
- uint64_t Zero = 0;
- uint64_t InvZero = ~0ull;
- CoverageFile->os() << BackendName;
- CoverageFile->os().write((const char *)&Zero, sizeof(unsigned char));
- for (uint64_t I : RuleCoverage.set_bits())
- CoverageFile->os().write((const char *)&I, sizeof(uint64_t));
- CoverageFile->os().write((const char *)&InvZero, sizeof(uint64_t));
-
- CoverageFile->keep();
- }
-
- return true;
-}
-
-void CodeGenCoverage::reset() { RuleCoverage.resize(0); }
diff --git a/gnu/llvm/lib/Support/CommandLine.cpp b/gnu/llvm/lib/Support/CommandLine.cpp
deleted file mode 100644
index f7290b54dcf..00000000000
--- a/gnu/llvm/lib/Support/CommandLine.cpp
+++ /dev/null
@@ -1,2272 +0,0 @@
-//===-- CommandLine.cpp - Command line parser implementation --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements a command line argument processor that is useful when
-// creating a tool. It provides a simple, minimalistic interface that is easily
-// extensible and supports nonlocal (library) command line options.
-//
-// Note that rather than trying to figure out what this code does, you could try
-// reading the library documentation located in docs/CommandLine.html
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/CommandLine.h"
-#include "llvm-c/Support.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/StringSaver.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstdlib>
-#include <map>
-using namespace llvm;
-using namespace cl;
-
-#define DEBUG_TYPE "commandline"
-
-//===----------------------------------------------------------------------===//
-// Template instantiations and anchors.
-//
-namespace llvm {
-namespace cl {
-template class basic_parser<bool>;
-template class basic_parser<boolOrDefault>;
-template class basic_parser<int>;
-template class basic_parser<unsigned>;
-template class basic_parser<unsigned long long>;
-template class basic_parser<double>;
-template class basic_parser<float>;
-template class basic_parser<std::string>;
-template class basic_parser<char>;
-
-template class opt<unsigned>;
-template class opt<int>;
-template class opt<std::string>;
-template class opt<char>;
-template class opt<bool>;
-}
-} // end namespace llvm::cl
-
-// Pin the vtables to this file.
-void GenericOptionValue::anchor() {}
-void OptionValue<boolOrDefault>::anchor() {}
-void OptionValue<std::string>::anchor() {}
-void Option::anchor() {}
-void basic_parser_impl::anchor() {}
-void parser<bool>::anchor() {}
-void parser<boolOrDefault>::anchor() {}
-void parser<int>::anchor() {}
-void parser<unsigned>::anchor() {}
-void parser<unsigned long long>::anchor() {}
-void parser<double>::anchor() {}
-void parser<float>::anchor() {}
-void parser<std::string>::anchor() {}
-void parser<char>::anchor() {}
-
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class CommandLineParser {
-public:
- // Globals for name and overview of program. Program name is not a string to
- // avoid static ctor/dtor issues.
- std::string ProgramName;
- StringRef ProgramOverview;
-
- // This collects additional help to be printed.
- std::vector<StringRef> MoreHelp;
-
- // This collects the different option categories that have been registered.
- SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories;
-
- // This collects the different subcommands that have been registered.
- SmallPtrSet<SubCommand *, 4> RegisteredSubCommands;
-
- CommandLineParser() : ActiveSubCommand(nullptr) {
- registerSubCommand(&*TopLevelSubCommand);
- registerSubCommand(&*AllSubCommands);
- }
-
- void ResetAllOptionOccurrences();
-
- bool ParseCommandLineOptions(int argc, const char *const *argv,
- StringRef Overview, raw_ostream *Errs = nullptr);
-
- void addLiteralOption(Option &Opt, SubCommand *SC, StringRef Name) {
- if (Opt.hasArgStr())
- return;
- if (!SC->OptionsMap.insert(std::make_pair(Name, &Opt)).second) {
- errs() << ProgramName << ": CommandLine Error: Option '" << Name
- << "' registered more than once!\n";
- report_fatal_error("inconsistency in registered CommandLine options");
- }
-
- // If we're adding this to all sub-commands, add it to the ones that have
- // already been registered.
- if (SC == &*AllSubCommands) {
- for (const auto &Sub : RegisteredSubCommands) {
- if (SC == Sub)
- continue;
- addLiteralOption(Opt, Sub, Name);
- }
- }
- }
-
- void addLiteralOption(Option &Opt, StringRef Name) {
- if (Opt.Subs.empty())
- addLiteralOption(Opt, &*TopLevelSubCommand, Name);
- else {
- for (auto SC : Opt.Subs)
- addLiteralOption(Opt, SC, Name);
- }
- }
-
- void addOption(Option *O, SubCommand *SC) {
- bool HadErrors = false;
- if (O->hasArgStr()) {
- // Add argument to the argument map!
- if (!SC->OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {
- errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
- << "' registered more than once!\n";
- HadErrors = true;
- }
- }
-
- // Remember information about positional options.
- if (O->getFormattingFlag() == cl::Positional)
- SC->PositionalOpts.push_back(O);
- else if (O->getMiscFlags() & cl::Sink) // Remember sink options
- SC->SinkOpts.push_back(O);
- else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) {
- if (SC->ConsumeAfterOpt) {
- O->error("Cannot specify more than one option with cl::ConsumeAfter!");
- HadErrors = true;
- }
- SC->ConsumeAfterOpt = O;
- }
-
- // Fail hard if there were errors. These are strictly unrecoverable and
- // indicate serious issues such as conflicting option names or an
- // incorrectly
- // linked LLVM distribution.
- if (HadErrors)
- report_fatal_error("inconsistency in registered CommandLine options");
-
- // If we're adding this to all sub-commands, add it to the ones that have
- // already been registered.
- if (SC == &*AllSubCommands) {
- for (const auto &Sub : RegisteredSubCommands) {
- if (SC == Sub)
- continue;
- addOption(O, Sub);
- }
- }
- }
-
- void addOption(Option *O) {
- if (O->Subs.empty()) {
- addOption(O, &*TopLevelSubCommand);
- } else {
- for (auto SC : O->Subs)
- addOption(O, SC);
- }
- }
-
- void removeOption(Option *O, SubCommand *SC) {
- SmallVector<StringRef, 16> OptionNames;
- O->getExtraOptionNames(OptionNames);
- if (O->hasArgStr())
- OptionNames.push_back(O->ArgStr);
-
- SubCommand &Sub = *SC;
- for (auto Name : OptionNames)
- Sub.OptionsMap.erase(Name);
-
- if (O->getFormattingFlag() == cl::Positional)
- for (auto Opt = Sub.PositionalOpts.begin();
- Opt != Sub.PositionalOpts.end(); ++Opt) {
- if (*Opt == O) {
- Sub.PositionalOpts.erase(Opt);
- break;
- }
- }
- else if (O->getMiscFlags() & cl::Sink)
- for (auto Opt = Sub.SinkOpts.begin(); Opt != Sub.SinkOpts.end(); ++Opt) {
- if (*Opt == O) {
- Sub.SinkOpts.erase(Opt);
- break;
- }
- }
- else if (O == Sub.ConsumeAfterOpt)
- Sub.ConsumeAfterOpt = nullptr;
- }
-
- void removeOption(Option *O) {
- if (O->Subs.empty())
- removeOption(O, &*TopLevelSubCommand);
- else {
- if (O->isInAllSubCommands()) {
- for (auto SC : RegisteredSubCommands)
- removeOption(O, SC);
- } else {
- for (auto SC : O->Subs)
- removeOption(O, SC);
- }
- }
- }
-
- bool hasOptions(const SubCommand &Sub) const {
- return (!Sub.OptionsMap.empty() || !Sub.PositionalOpts.empty() ||
- nullptr != Sub.ConsumeAfterOpt);
- }
-
- bool hasOptions() const {
- for (const auto &S : RegisteredSubCommands) {
- if (hasOptions(*S))
- return true;
- }
- return false;
- }
-
- SubCommand *getActiveSubCommand() { return ActiveSubCommand; }
-
- void updateArgStr(Option *O, StringRef NewName, SubCommand *SC) {
- SubCommand &Sub = *SC;
- if (!Sub.OptionsMap.insert(std::make_pair(NewName, O)).second) {
- errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
- << "' registered more than once!\n";
- report_fatal_error("inconsistency in registered CommandLine options");
- }
- Sub.OptionsMap.erase(O->ArgStr);
- }
-
- void updateArgStr(Option *O, StringRef NewName) {
- if (O->Subs.empty())
- updateArgStr(O, NewName, &*TopLevelSubCommand);
- else {
- for (auto SC : O->Subs)
- updateArgStr(O, NewName, SC);
- }
- }
-
- void printOptionValues();
-
- void registerCategory(OptionCategory *cat) {
- assert(count_if(RegisteredOptionCategories,
- [cat](const OptionCategory *Category) {
- return cat->getName() == Category->getName();
- }) == 0 &&
- "Duplicate option categories");
-
- RegisteredOptionCategories.insert(cat);
- }
-
- void registerSubCommand(SubCommand *sub) {
- assert(count_if(RegisteredSubCommands,
- [sub](const SubCommand *Sub) {
- return (!sub->getName().empty()) &&
- (Sub->getName() == sub->getName());
- }) == 0 &&
- "Duplicate subcommands");
- RegisteredSubCommands.insert(sub);
-
- // For all options that have been registered for all subcommands, add the
- // option to this subcommand now.
- if (sub != &*AllSubCommands) {
- for (auto &E : AllSubCommands->OptionsMap) {
- Option *O = E.second;
- if ((O->isPositional() || O->isSink() || O->isConsumeAfter()) ||
- O->hasArgStr())
- addOption(O, sub);
- else
- addLiteralOption(*O, sub, E.first());
- }
- }
- }
-
- void unregisterSubCommand(SubCommand *sub) {
- RegisteredSubCommands.erase(sub);
- }
-
- iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator>
- getRegisteredSubcommands() {
- return make_range(RegisteredSubCommands.begin(),
- RegisteredSubCommands.end());
- }
-
- void reset() {
- ActiveSubCommand = nullptr;
- ProgramName.clear();
- ProgramOverview = StringRef();
-
- MoreHelp.clear();
- RegisteredOptionCategories.clear();
-
- ResetAllOptionOccurrences();
- RegisteredSubCommands.clear();
-
- TopLevelSubCommand->reset();
- AllSubCommands->reset();
- registerSubCommand(&*TopLevelSubCommand);
- registerSubCommand(&*AllSubCommands);
- }
-
-private:
- SubCommand *ActiveSubCommand;
-
- Option *LookupOption(SubCommand &Sub, StringRef &Arg, StringRef &Value);
- SubCommand *LookupSubCommand(StringRef Name);
-};
-
-} // namespace
-
-static ManagedStatic<CommandLineParser> GlobalParser;
-
-void cl::AddLiteralOption(Option &O, StringRef Name) {
- GlobalParser->addLiteralOption(O, Name);
-}
-
-extrahelp::extrahelp(StringRef Help) : morehelp(Help) {
- GlobalParser->MoreHelp.push_back(Help);
-}
-
-void Option::addArgument() {
- GlobalParser->addOption(this);
- FullyInitialized = true;
-}
-
-void Option::removeArgument() { GlobalParser->removeOption(this); }
-
-void Option::setArgStr(StringRef S) {
- if (FullyInitialized)
- GlobalParser->updateArgStr(this, S);
- assert((S.empty() || S[0] != '-') && "Option can't start with '-");
- ArgStr = S;
-}
-
-// Initialise the general option category.
-OptionCategory llvm::cl::GeneralCategory("General options");
-
-void OptionCategory::registerCategory() {
- GlobalParser->registerCategory(this);
-}
-
-// A special subcommand representing no subcommand
-ManagedStatic<SubCommand> llvm::cl::TopLevelSubCommand;
-
-// A special subcommand that can be used to put an option into all subcommands.
-ManagedStatic<SubCommand> llvm::cl::AllSubCommands;
-
-void SubCommand::registerSubCommand() {
- GlobalParser->registerSubCommand(this);
-}
-
-void SubCommand::unregisterSubCommand() {
- GlobalParser->unregisterSubCommand(this);
-}
-
-void SubCommand::reset() {
- PositionalOpts.clear();
- SinkOpts.clear();
- OptionsMap.clear();
-
- ConsumeAfterOpt = nullptr;
-}
-
-SubCommand::operator bool() const {
- return (GlobalParser->getActiveSubCommand() == this);
-}
-
-//===----------------------------------------------------------------------===//
-// Basic, shared command line option processing machinery.
-//
-
-/// LookupOption - Lookup the option specified by the specified option on the
-/// command line. If there is a value specified (after an equal sign) return
-/// that as well. This assumes that leading dashes have already been stripped.
-Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg,
- StringRef &Value) {
- // Reject all dashes.
- if (Arg.empty())
- return nullptr;
- assert(&Sub != &*AllSubCommands);
-
- size_t EqualPos = Arg.find('=');
-
- // If we have an equals sign, remember the value.
- if (EqualPos == StringRef::npos) {
- // Look up the option.
- auto I = Sub.OptionsMap.find(Arg);
- if (I == Sub.OptionsMap.end())
- return nullptr;
-
- return I != Sub.OptionsMap.end() ? I->second : nullptr;
- }
-
- // If the argument before the = is a valid option name and the option allows
- // non-prefix form (ie is not AlwaysPrefix), we match. If not, signal match
- // failure by returning nullptr.
- auto I = Sub.OptionsMap.find(Arg.substr(0, EqualPos));
- if (I == Sub.OptionsMap.end())
- return nullptr;
-
- auto O = I->second;
- if (O->getFormattingFlag() == cl::AlwaysPrefix)
- return nullptr;
-
- Value = Arg.substr(EqualPos + 1);
- Arg = Arg.substr(0, EqualPos);
- return I->second;
-}
-
-SubCommand *CommandLineParser::LookupSubCommand(StringRef Name) {
- if (Name.empty())
- return &*TopLevelSubCommand;
- for (auto S : RegisteredSubCommands) {
- if (S == &*AllSubCommands)
- continue;
- if (S->getName().empty())
- continue;
-
- if (StringRef(S->getName()) == StringRef(Name))
- return S;
- }
- return &*TopLevelSubCommand;
-}
-
-/// LookupNearestOption - Lookup the closest match to the option specified by
-/// the specified option on the command line. If there is a value specified
-/// (after an equal sign) return that as well. This assumes that leading dashes
-/// have already been stripped.
-static Option *LookupNearestOption(StringRef Arg,
- const StringMap<Option *> &OptionsMap,
- std::string &NearestString) {
- // Reject all dashes.
- if (Arg.empty())
- return nullptr;
-
- // Split on any equal sign.
- std::pair<StringRef, StringRef> SplitArg = Arg.split('=');
- StringRef &LHS = SplitArg.first; // LHS == Arg when no '=' is present.
- StringRef &RHS = SplitArg.second;
-
- // Find the closest match.
- Option *Best = nullptr;
- unsigned BestDistance = 0;
- for (StringMap<Option *>::const_iterator it = OptionsMap.begin(),
- ie = OptionsMap.end();
- it != ie; ++it) {
- Option *O = it->second;
- SmallVector<StringRef, 16> OptionNames;
- O->getExtraOptionNames(OptionNames);
- if (O->hasArgStr())
- OptionNames.push_back(O->ArgStr);
-
- bool PermitValue = O->getValueExpectedFlag() != cl::ValueDisallowed;
- StringRef Flag = PermitValue ? LHS : Arg;
- for (auto Name : OptionNames) {
- unsigned Distance = StringRef(Name).edit_distance(
- Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance);
- if (!Best || Distance < BestDistance) {
- Best = O;
- BestDistance = Distance;
- if (RHS.empty() || !PermitValue)
- NearestString = Name;
- else
- NearestString = (Twine(Name) + "=" + RHS).str();
- }
- }
- }
-
- return Best;
-}
-
-/// CommaSeparateAndAddOccurrence - A wrapper around Handler->addOccurrence()
-/// that does special handling of cl::CommaSeparated options.
-static bool CommaSeparateAndAddOccurrence(Option *Handler, unsigned pos,
- StringRef ArgName, StringRef Value,
- bool MultiArg = false) {
- // Check to see if this option accepts a comma separated list of values. If
- // it does, we have to split up the value into multiple values.
- if (Handler->getMiscFlags() & CommaSeparated) {
- StringRef Val(Value);
- StringRef::size_type Pos = Val.find(',');
-
- while (Pos != StringRef::npos) {
- // Process the portion before the comma.
- if (Handler->addOccurrence(pos, ArgName, Val.substr(0, Pos), MultiArg))
- return true;
- // Erase the portion before the comma, AND the comma.
- Val = Val.substr(Pos + 1);
- // Check for another comma.
- Pos = Val.find(',');
- }
-
- Value = Val;
- }
-
- return Handler->addOccurrence(pos, ArgName, Value, MultiArg);
-}
-
-/// ProvideOption - For Value, this differentiates between an empty value ("")
-/// and a null value (StringRef()). The later is accepted for arguments that
-/// don't allow a value (-foo) the former is rejected (-foo=).
-static inline bool ProvideOption(Option *Handler, StringRef ArgName,
- StringRef Value, int argc,
- const char *const *argv, int &i) {
- // Is this a multi-argument option?
- unsigned NumAdditionalVals = Handler->getNumAdditionalVals();
-
- // Enforce value requirements
- switch (Handler->getValueExpectedFlag()) {
- case ValueRequired:
- if (!Value.data()) { // No value specified?
- // If no other argument or the option only supports prefix form, we
- // cannot look at the next argument.
- if (i + 1 >= argc || Handler->getFormattingFlag() == cl::AlwaysPrefix)
- return Handler->error("requires a value!");
- // Steal the next argument, like for '-o filename'
- assert(argv && "null check");
- Value = StringRef(argv[++i]);
- }
- break;
- case ValueDisallowed:
- if (NumAdditionalVals > 0)
- return Handler->error("multi-valued option specified"
- " with ValueDisallowed modifier!");
-
- if (Value.data())
- return Handler->error("does not allow a value! '" + Twine(Value) +
- "' specified.");
- break;
- case ValueOptional:
- break;
- }
-
- // If this isn't a multi-arg option, just run the handler.
- if (NumAdditionalVals == 0)
- return CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value);
-
- // If it is, run the handle several times.
- bool MultiArg = false;
-
- if (Value.data()) {
- if (CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value, MultiArg))
- return true;
- --NumAdditionalVals;
- MultiArg = true;
- }
-
- while (NumAdditionalVals > 0) {
- if (i + 1 >= argc)
- return Handler->error("not enough values!");
- assert(argv && "null check");
- Value = StringRef(argv[++i]);
-
- if (CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value, MultiArg))
- return true;
- MultiArg = true;
- --NumAdditionalVals;
- }
- return false;
-}
-
-static bool ProvidePositionalOption(Option *Handler, StringRef Arg, int i) {
- int Dummy = i;
- return ProvideOption(Handler, Handler->ArgStr, Arg, 0, nullptr, Dummy);
-}
-
-// Option predicates...
-static inline bool isGrouping(const Option *O) {
- return O->getFormattingFlag() == cl::Grouping;
-}
-static inline bool isPrefixedOrGrouping(const Option *O) {
- return isGrouping(O) || O->getFormattingFlag() == cl::Prefix ||
- O->getFormattingFlag() == cl::AlwaysPrefix;
-}
-
-// getOptionPred - Check to see if there are any options that satisfy the
-// specified predicate with names that are the prefixes in Name. This is
-// checked by progressively stripping characters off of the name, checking to
-// see if there options that satisfy the predicate. If we find one, return it,
-// otherwise return null.
-//
-static Option *getOptionPred(StringRef Name, size_t &Length,
- bool (*Pred)(const Option *),
- const StringMap<Option *> &OptionsMap) {
-
- StringMap<Option *>::const_iterator OMI = OptionsMap.find(Name);
-
- // Loop while we haven't found an option and Name still has at least two
- // characters in it (so that the next iteration will not be the empty
- // string.
- while (OMI == OptionsMap.end() && Name.size() > 1) {
- Name = Name.substr(0, Name.size() - 1); // Chop off the last character.
- OMI = OptionsMap.find(Name);
- }
-
- if (OMI != OptionsMap.end() && Pred(OMI->second)) {
- Length = Name.size();
- return OMI->second; // Found one!
- }
- return nullptr; // No option found!
-}
-
-/// HandlePrefixedOrGroupedOption - The specified argument string (which started
-/// with at least one '-') does not fully match an available option. Check to
-/// see if this is a prefix or grouped option. If so, split arg into output an
-/// Arg/Value pair and return the Option to parse it with.
-static Option *
-HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value,
- bool &ErrorParsing,
- const StringMap<Option *> &OptionsMap) {
- if (Arg.size() == 1)
- return nullptr;
-
- // Do the lookup!
- size_t Length = 0;
- Option *PGOpt = getOptionPred(Arg, Length, isPrefixedOrGrouping, OptionsMap);
- if (!PGOpt)
- return nullptr;
-
- // If the option is a prefixed option, then the value is simply the
- // rest of the name... so fall through to later processing, by
- // setting up the argument name flags and value fields.
- if (PGOpt->getFormattingFlag() == cl::Prefix ||
- PGOpt->getFormattingFlag() == cl::AlwaysPrefix) {
- Value = Arg.substr(Length);
- Arg = Arg.substr(0, Length);
- assert(OptionsMap.count(Arg) && OptionsMap.find(Arg)->second == PGOpt);
- return PGOpt;
- }
-
- // This must be a grouped option... handle them now. Grouping options can't
- // have values.
- assert(isGrouping(PGOpt) && "Broken getOptionPred!");
-
- do {
- // Move current arg name out of Arg into OneArgName.
- StringRef OneArgName = Arg.substr(0, Length);
- Arg = Arg.substr(Length);
-
- // Because ValueRequired is an invalid flag for grouped arguments,
- // we don't need to pass argc/argv in.
- assert(PGOpt->getValueExpectedFlag() != cl::ValueRequired &&
- "Option can not be cl::Grouping AND cl::ValueRequired!");
- int Dummy = 0;
- ErrorParsing |=
- ProvideOption(PGOpt, OneArgName, StringRef(), 0, nullptr, Dummy);
-
- // Get the next grouping option.
- PGOpt = getOptionPred(Arg, Length, isGrouping, OptionsMap);
- } while (PGOpt && Length != Arg.size());
-
- // Return the last option with Arg cut down to just the last one.
- return PGOpt;
-}
-
-static bool RequiresValue(const Option *O) {
- return O->getNumOccurrencesFlag() == cl::Required ||
- O->getNumOccurrencesFlag() == cl::OneOrMore;
-}
-
-static bool EatsUnboundedNumberOfValues(const Option *O) {
- return O->getNumOccurrencesFlag() == cl::ZeroOrMore ||
- O->getNumOccurrencesFlag() == cl::OneOrMore;
-}
-
-static bool isWhitespace(char C) {
- return C == ' ' || C == '\t' || C == '\r' || C == '\n';
-}
-
-static bool isWhitespaceOrNull(char C) {
- return isWhitespace(C) || C == '\0';
-}
-
-static bool isQuote(char C) { return C == '\"' || C == '\''; }
-
-void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver,
- SmallVectorImpl<const char *> &NewArgv,
- bool MarkEOLs) {
- SmallString<128> Token;
- for (size_t I = 0, E = Src.size(); I != E; ++I) {
- // Consume runs of whitespace.
- if (Token.empty()) {
- while (I != E && isWhitespace(Src[I])) {
- // Mark the end of lines in response files
- if (MarkEOLs && Src[I] == '\n')
- NewArgv.push_back(nullptr);
- ++I;
- }
- if (I == E)
- break;
- }
-
- char C = Src[I];
-
- // Backslash escapes the next character.
- if (I + 1 < E && C == '\\') {
- ++I; // Skip the escape.
- Token.push_back(Src[I]);
- continue;
- }
-
- // Consume a quoted string.
- if (isQuote(C)) {
- ++I;
- while (I != E && Src[I] != C) {
- // Backslash escapes the next character.
- if (Src[I] == '\\' && I + 1 != E)
- ++I;
- Token.push_back(Src[I]);
- ++I;
- }
- if (I == E)
- break;
- continue;
- }
-
- // End the token if this is whitespace.
- if (isWhitespace(C)) {
- if (!Token.empty())
- NewArgv.push_back(Saver.save(StringRef(Token)).data());
- Token.clear();
- continue;
- }
-
- // This is a normal character. Append it.
- Token.push_back(C);
- }
-
- // Append the last token after hitting EOF with no whitespace.
- if (!Token.empty())
- NewArgv.push_back(Saver.save(StringRef(Token)).data());
- // Mark the end of response files
- if (MarkEOLs)
- NewArgv.push_back(nullptr);
-}
-
-/// Backslashes are interpreted in a rather complicated way in the Windows-style
-/// command line, because backslashes are used both to separate path and to
-/// escape double quote. This method consumes runs of backslashes as well as the
-/// following double quote if it's escaped.
-///
-/// * If an even number of backslashes is followed by a double quote, one
-/// backslash is output for every pair of backslashes, and the last double
-/// quote remains unconsumed. The double quote will later be interpreted as
-/// the start or end of a quoted string in the main loop outside of this
-/// function.
-///
-/// * If an odd number of backslashes is followed by a double quote, one
-/// backslash is output for every pair of backslashes, and a double quote is
-/// output for the last pair of backslash-double quote. The double quote is
-/// consumed in this case.
-///
-/// * Otherwise, backslashes are interpreted literally.
-static size_t parseBackslash(StringRef Src, size_t I, SmallString<128> &Token) {
- size_t E = Src.size();
- int BackslashCount = 0;
- // Skip the backslashes.
- do {
- ++I;
- ++BackslashCount;
- } while (I != E && Src[I] == '\\');
-
- bool FollowedByDoubleQuote = (I != E && Src[I] == '"');
- if (FollowedByDoubleQuote) {
- Token.append(BackslashCount / 2, '\\');
- if (BackslashCount % 2 == 0)
- return I - 1;
- Token.push_back('"');
- return I;
- }
- Token.append(BackslashCount, '\\');
- return I - 1;
-}
-
-void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver,
- SmallVectorImpl<const char *> &NewArgv,
- bool MarkEOLs) {
- SmallString<128> Token;
-
- // This is a small state machine to consume characters until it reaches the
- // end of the source string.
- enum { INIT, UNQUOTED, QUOTED } State = INIT;
- for (size_t I = 0, E = Src.size(); I != E; ++I) {
- char C = Src[I];
-
- // INIT state indicates that the current input index is at the start of
- // the string or between tokens.
- if (State == INIT) {
- if (isWhitespaceOrNull(C)) {
- // Mark the end of lines in response files
- if (MarkEOLs && C == '\n')
- NewArgv.push_back(nullptr);
- continue;
- }
- if (C == '"') {
- State = QUOTED;
- continue;
- }
- if (C == '\\') {
- I = parseBackslash(Src, I, Token);
- State = UNQUOTED;
- continue;
- }
- Token.push_back(C);
- State = UNQUOTED;
- continue;
- }
-
- // UNQUOTED state means that it's reading a token not quoted by double
- // quotes.
- if (State == UNQUOTED) {
- // Whitespace means the end of the token.
- if (isWhitespaceOrNull(C)) {
- NewArgv.push_back(Saver.save(StringRef(Token)).data());
- Token.clear();
- State = INIT;
- // Mark the end of lines in response files
- if (MarkEOLs && C == '\n')
- NewArgv.push_back(nullptr);
- continue;
- }
- if (C == '"') {
- State = QUOTED;
- continue;
- }
- if (C == '\\') {
- I = parseBackslash(Src, I, Token);
- continue;
- }
- Token.push_back(C);
- continue;
- }
-
- // QUOTED state means that it's reading a token quoted by double quotes.
- if (State == QUOTED) {
- if (C == '"') {
- State = UNQUOTED;
- continue;
- }
- if (C == '\\') {
- I = parseBackslash(Src, I, Token);
- continue;
- }
- Token.push_back(C);
- }
- }
- // Append the last token after hitting EOF with no whitespace.
- if (!Token.empty())
- NewArgv.push_back(Saver.save(StringRef(Token)).data());
- // Mark the end of response files
- if (MarkEOLs)
- NewArgv.push_back(nullptr);
-}
-
-void cl::tokenizeConfigFile(StringRef Source, StringSaver &Saver,
- SmallVectorImpl<const char *> &NewArgv,
- bool MarkEOLs) {
- for (const char *Cur = Source.begin(); Cur != Source.end();) {
- SmallString<128> Line;
- // Check for comment line.
- if (isWhitespace(*Cur)) {
- while (Cur != Source.end() && isWhitespace(*Cur))
- ++Cur;
- continue;
- }
- if (*Cur == '#') {
- while (Cur != Source.end() && *Cur != '\n')
- ++Cur;
- continue;
- }
- // Find end of the current line.
- const char *Start = Cur;
- for (const char *End = Source.end(); Cur != End; ++Cur) {
- if (*Cur == '\\') {
- if (Cur + 1 != End) {
- ++Cur;
- if (*Cur == '\n' ||
- (*Cur == '\r' && (Cur + 1 != End) && Cur[1] == '\n')) {
- Line.append(Start, Cur - 1);
- if (*Cur == '\r')
- ++Cur;
- Start = Cur + 1;
- }
- }
- } else if (*Cur == '\n')
- break;
- }
- // Tokenize line.
- Line.append(Start, Cur);
- cl::TokenizeGNUCommandLine(Line, Saver, NewArgv, MarkEOLs);
- }
-}
-
-// It is called byte order marker but the UTF-8 BOM is actually not affected
-// by the host system's endianness.
-static bool hasUTF8ByteOrderMark(ArrayRef<char> S) {
- return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf');
-}
-
-static bool ExpandResponseFile(StringRef FName, StringSaver &Saver,
- TokenizerCallback Tokenizer,
- SmallVectorImpl<const char *> &NewArgv,
- bool MarkEOLs, bool RelativeNames) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
- MemoryBuffer::getFile(FName);
- if (!MemBufOrErr)
- return false;
- MemoryBuffer &MemBuf = *MemBufOrErr.get();
- StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize());
-
- // If we have a UTF-16 byte order mark, convert to UTF-8 for parsing.
- ArrayRef<char> BufRef(MemBuf.getBufferStart(), MemBuf.getBufferEnd());
- std::string UTF8Buf;
- if (hasUTF16ByteOrderMark(BufRef)) {
- if (!convertUTF16ToUTF8String(BufRef, UTF8Buf))
- return false;
- Str = StringRef(UTF8Buf);
- }
- // If we see UTF-8 BOM sequence at the beginning of a file, we shall remove
- // these bytes before parsing.
- // Reference: http://en.wikipedia.org/wiki/UTF-8#Byte_order_mark
- else if (hasUTF8ByteOrderMark(BufRef))
- Str = StringRef(BufRef.data() + 3, BufRef.size() - 3);
-
- // Tokenize the contents into NewArgv.
- Tokenizer(Str, Saver, NewArgv, MarkEOLs);
-
- // If names of nested response files should be resolved relative to including
- // file, replace the included response file names with their full paths
- // obtained by required resolution.
- if (RelativeNames)
- for (unsigned I = 0; I < NewArgv.size(); ++I)
- if (NewArgv[I]) {
- StringRef Arg = NewArgv[I];
- if (Arg.front() == '@') {
- StringRef FileName = Arg.drop_front();
- if (llvm::sys::path::is_relative(FileName)) {
- SmallString<128> ResponseFile;
- ResponseFile.append(1, '@');
- if (llvm::sys::path::is_relative(FName)) {
- SmallString<128> curr_dir;
- llvm::sys::fs::current_path(curr_dir);
- ResponseFile.append(curr_dir.str());
- }
- llvm::sys::path::append(
- ResponseFile, llvm::sys::path::parent_path(FName), FileName);
- NewArgv[I] = Saver.save(ResponseFile.c_str()).data();
- }
- }
- }
-
- return true;
-}
-
-/// Expand response files on a command line recursively using the given
-/// StringSaver and tokenization strategy.
-bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
- SmallVectorImpl<const char *> &Argv,
- bool MarkEOLs, bool RelativeNames) {
- unsigned RspFiles = 0;
- bool AllExpanded = true;
-
- // Don't cache Argv.size() because it can change.
- for (unsigned I = 0; I != Argv.size();) {
- const char *Arg = Argv[I];
- // Check if it is an EOL marker
- if (Arg == nullptr) {
- ++I;
- continue;
- }
- if (Arg[0] != '@') {
- ++I;
- continue;
- }
-
- // If we have too many response files, leave some unexpanded. This avoids
- // crashing on self-referential response files.
- if (RspFiles++ > 20)
- return false;
-
- // Replace this response file argument with the tokenization of its
- // contents. Nested response files are expanded in subsequent iterations.
- SmallVector<const char *, 0> ExpandedArgv;
- if (!ExpandResponseFile(Arg + 1, Saver, Tokenizer, ExpandedArgv,
- MarkEOLs, RelativeNames)) {
- // We couldn't read this file, so we leave it in the argument stream and
- // move on.
- AllExpanded = false;
- ++I;
- continue;
- }
- Argv.erase(Argv.begin() + I);
- Argv.insert(Argv.begin() + I, ExpandedArgv.begin(), ExpandedArgv.end());
- }
- return AllExpanded;
-}
-
-bool cl::readConfigFile(StringRef CfgFile, StringSaver &Saver,
- SmallVectorImpl<const char *> &Argv) {
- if (!ExpandResponseFile(CfgFile, Saver, cl::tokenizeConfigFile, Argv,
- /*MarkEOLs*/ false, /*RelativeNames*/ true))
- return false;
- return ExpandResponseFiles(Saver, cl::tokenizeConfigFile, Argv,
- /*MarkEOLs*/ false, /*RelativeNames*/ true);
-}
-
-/// ParseEnvironmentOptions - An alternative entry point to the
-/// CommandLine library, which allows you to read the program's name
-/// from the caller (as PROGNAME) and its command-line arguments from
-/// an environment variable (whose name is given in ENVVAR).
-///
-void cl::ParseEnvironmentOptions(const char *progName, const char *envVar,
- const char *Overview) {
- // Check args.
- assert(progName && "Program name not specified");
- assert(envVar && "Environment variable name missing");
-
- // Get the environment variable they want us to parse options out of.
- llvm::Optional<std::string> envValue = sys::Process::GetEnv(StringRef(envVar));
- if (!envValue)
- return;
-
- // Get program's "name", which we wouldn't know without the caller
- // telling us.
- SmallVector<const char *, 20> newArgv;
- BumpPtrAllocator A;
- StringSaver Saver(A);
- newArgv.push_back(Saver.save(progName).data());
-
- // Parse the value of the environment variable into a "command line"
- // and hand it off to ParseCommandLineOptions().
- TokenizeGNUCommandLine(*envValue, Saver, newArgv);
- int newArgc = static_cast<int>(newArgv.size());
- ParseCommandLineOptions(newArgc, &newArgv[0], StringRef(Overview));
-}
-
-bool cl::ParseCommandLineOptions(int argc, const char *const *argv,
- StringRef Overview, raw_ostream *Errs,
- const char *EnvVar) {
- SmallVector<const char *, 20> NewArgv;
- BumpPtrAllocator A;
- StringSaver Saver(A);
- NewArgv.push_back(argv[0]);
-
- // Parse options from environment variable.
- if (EnvVar) {
- if (llvm::Optional<std::string> EnvValue =
- sys::Process::GetEnv(StringRef(EnvVar)))
- TokenizeGNUCommandLine(*EnvValue, Saver, NewArgv);
- }
-
- // Append options from command line.
- for (int I = 1; I < argc; ++I)
- NewArgv.push_back(argv[I]);
- int NewArgc = static_cast<int>(NewArgv.size());
-
- // Parse all options.
- return GlobalParser->ParseCommandLineOptions(NewArgc, &NewArgv[0], Overview,
- Errs);
-}
-
-void CommandLineParser::ResetAllOptionOccurrences() {
- // So that we can parse different command lines multiple times in succession
- // we reset all option values to look like they have never been seen before.
- for (auto SC : RegisteredSubCommands) {
- for (auto &O : SC->OptionsMap)
- O.second->reset();
- }
-}
-
-bool CommandLineParser::ParseCommandLineOptions(int argc,
- const char *const *argv,
- StringRef Overview,
- raw_ostream *Errs) {
- assert(hasOptions() && "No options specified!");
-
- // Expand response files.
- SmallVector<const char *, 20> newArgv(argv, argv + argc);
- BumpPtrAllocator A;
- StringSaver Saver(A);
- ExpandResponseFiles(Saver,
- Triple(sys::getProcessTriple()).isOSWindows() ?
- cl::TokenizeWindowsCommandLine : cl::TokenizeGNUCommandLine,
- newArgv);
- argv = &newArgv[0];
- argc = static_cast<int>(newArgv.size());
-
- // Copy the program name into ProgName, making sure not to overflow it.
- ProgramName = sys::path::filename(StringRef(argv[0]));
-
- ProgramOverview = Overview;
- bool IgnoreErrors = Errs;
- if (!Errs)
- Errs = &errs();
- bool ErrorParsing = false;
-
- // Check out the positional arguments to collect information about them.
- unsigned NumPositionalRequired = 0;
-
- // Determine whether or not there are an unlimited number of positionals
- bool HasUnlimitedPositionals = false;
-
- int FirstArg = 1;
- SubCommand *ChosenSubCommand = &*TopLevelSubCommand;
- if (argc >= 2 && argv[FirstArg][0] != '-') {
- // If the first argument specifies a valid subcommand, start processing
- // options from the second argument.
- ChosenSubCommand = LookupSubCommand(StringRef(argv[FirstArg]));
- if (ChosenSubCommand != &*TopLevelSubCommand)
- FirstArg = 2;
- }
- GlobalParser->ActiveSubCommand = ChosenSubCommand;
-
- assert(ChosenSubCommand);
- auto &ConsumeAfterOpt = ChosenSubCommand->ConsumeAfterOpt;
- auto &PositionalOpts = ChosenSubCommand->PositionalOpts;
- auto &SinkOpts = ChosenSubCommand->SinkOpts;
- auto &OptionsMap = ChosenSubCommand->OptionsMap;
-
- if (ConsumeAfterOpt) {
- assert(PositionalOpts.size() > 0 &&
- "Cannot specify cl::ConsumeAfter without a positional argument!");
- }
- if (!PositionalOpts.empty()) {
-
- // Calculate how many positional values are _required_.
- bool UnboundedFound = false;
- for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) {
- Option *Opt = PositionalOpts[i];
- if (RequiresValue(Opt))
- ++NumPositionalRequired;
- else if (ConsumeAfterOpt) {
- // ConsumeAfter cannot be combined with "optional" positional options
- // unless there is only one positional argument...
- if (PositionalOpts.size() > 1) {
- if (!IgnoreErrors)
- Opt->error("error - this positional option will never be matched, "
- "because it does not Require a value, and a "
- "cl::ConsumeAfter option is active!");
- ErrorParsing = true;
- }
- } else if (UnboundedFound && !Opt->hasArgStr()) {
- // This option does not "require" a value... Make sure this option is
- // not specified after an option that eats all extra arguments, or this
- // one will never get any!
- //
- if (!IgnoreErrors)
- Opt->error("error - option can never match, because "
- "another positional argument will match an "
- "unbounded number of values, and this option"
- " does not require a value!");
- *Errs << ProgramName << ": CommandLine Error: Option '" << Opt->ArgStr
- << "' is all messed up!\n";
- *Errs << PositionalOpts.size();
- ErrorParsing = true;
- }
- UnboundedFound |= EatsUnboundedNumberOfValues(Opt);
- }
- HasUnlimitedPositionals = UnboundedFound || ConsumeAfterOpt;
- }
-
- // PositionalVals - A vector of "positional" arguments we accumulate into
- // the process at the end.
- //
- SmallVector<std::pair<StringRef, unsigned>, 4> PositionalVals;
-
- // If the program has named positional arguments, and the name has been run
- // across, keep track of which positional argument was named. Otherwise put
- // the positional args into the PositionalVals list...
- Option *ActivePositionalArg = nullptr;
-
- // Loop over all of the arguments... processing them.
- bool DashDashFound = false; // Have we read '--'?
- for (int i = FirstArg; i < argc; ++i) {
- Option *Handler = nullptr;
- Option *NearestHandler = nullptr;
- std::string NearestHandlerString;
- StringRef Value;
- StringRef ArgName = "";
-
- // Check to see if this is a positional argument. This argument is
- // considered to be positional if it doesn't start with '-', if it is "-"
- // itself, or if we have seen "--" already.
- //
- if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) {
- // Positional argument!
- if (ActivePositionalArg) {
- ProvidePositionalOption(ActivePositionalArg, StringRef(argv[i]), i);
- continue; // We are done!
- }
-
- if (!PositionalOpts.empty()) {
- PositionalVals.push_back(std::make_pair(StringRef(argv[i]), i));
-
- // All of the positional arguments have been fulfulled, give the rest to
- // the consume after option... if it's specified...
- //
- if (PositionalVals.size() >= NumPositionalRequired && ConsumeAfterOpt) {
- for (++i; i < argc; ++i)
- PositionalVals.push_back(std::make_pair(StringRef(argv[i]), i));
- break; // Handle outside of the argument processing loop...
- }
-
- // Delay processing positional arguments until the end...
- continue;
- }
- } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 &&
- !DashDashFound) {
- DashDashFound = true; // This is the mythical "--"?
- continue; // Don't try to process it as an argument itself.
- } else if (ActivePositionalArg &&
- (ActivePositionalArg->getMiscFlags() & PositionalEatsArgs)) {
- // If there is a positional argument eating options, check to see if this
- // option is another positional argument. If so, treat it as an argument,
- // otherwise feed it to the eating positional.
- ArgName = StringRef(argv[i] + 1);
- // Eat leading dashes.
- while (!ArgName.empty() && ArgName[0] == '-')
- ArgName = ArgName.substr(1);
-
- Handler = LookupOption(*ChosenSubCommand, ArgName, Value);
- if (!Handler || Handler->getFormattingFlag() != cl::Positional) {
- ProvidePositionalOption(ActivePositionalArg, StringRef(argv[i]), i);
- continue; // We are done!
- }
-
- } else { // We start with a '-', must be an argument.
- ArgName = StringRef(argv[i] + 1);
- // Eat leading dashes.
- while (!ArgName.empty() && ArgName[0] == '-')
- ArgName = ArgName.substr(1);
-
- Handler = LookupOption(*ChosenSubCommand, ArgName, Value);
-
- // Check to see if this "option" is really a prefixed or grouped argument.
- if (!Handler)
- Handler = HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing,
- OptionsMap);
-
- // Otherwise, look for the closest available option to report to the user
- // in the upcoming error.
- if (!Handler && SinkOpts.empty())
- NearestHandler =
- LookupNearestOption(ArgName, OptionsMap, NearestHandlerString);
- }
-
- if (!Handler) {
- if (SinkOpts.empty()) {
- *Errs << ProgramName << ": Unknown command line argument '" << argv[i]
- << "'. Try: '" << argv[0] << " -help'\n";
-
- if (NearestHandler) {
- // If we know a near match, report it as well.
- *Errs << ProgramName << ": Did you mean '-" << NearestHandlerString
- << "'?\n";
- }
-
- ErrorParsing = true;
- } else {
- for (SmallVectorImpl<Option *>::iterator I = SinkOpts.begin(),
- E = SinkOpts.end();
- I != E; ++I)
- (*I)->addOccurrence(i, "", StringRef(argv[i]));
- }
- continue;
- }
-
- // If this is a named positional argument, just remember that it is the
- // active one...
- if (Handler->getFormattingFlag() == cl::Positional) {
- if ((Handler->getMiscFlags() & PositionalEatsArgs) && !Value.empty()) {
- Handler->error("This argument does not take a value.\n"
- "\tInstead, it consumes any positional arguments until "
- "the next recognized option.", *Errs);
- ErrorParsing = true;
- }
- ActivePositionalArg = Handler;
- }
- else
- ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i);
- }
-
- // Check and handle positional arguments now...
- if (NumPositionalRequired > PositionalVals.size()) {
- *Errs << ProgramName
- << ": Not enough positional command line arguments specified!\n"
- << "Must specify at least " << NumPositionalRequired
- << " positional argument" << (NumPositionalRequired > 1 ? "s" : "")
- << ": See: " << argv[0] << " -help\n";
-
- ErrorParsing = true;
- } else if (!HasUnlimitedPositionals &&
- PositionalVals.size() > PositionalOpts.size()) {
- *Errs << ProgramName << ": Too many positional arguments specified!\n"
- << "Can specify at most " << PositionalOpts.size()
- << " positional arguments: See: " << argv[0] << " -help\n";
- ErrorParsing = true;
-
- } else if (!ConsumeAfterOpt) {
- // Positional args have already been handled if ConsumeAfter is specified.
- unsigned ValNo = 0, NumVals = static_cast<unsigned>(PositionalVals.size());
- for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) {
- if (RequiresValue(PositionalOpts[i])) {
- ProvidePositionalOption(PositionalOpts[i], PositionalVals[ValNo].first,
- PositionalVals[ValNo].second);
- ValNo++;
- --NumPositionalRequired; // We fulfilled our duty...
- }
-
- // If we _can_ give this option more arguments, do so now, as long as we
- // do not give it values that others need. 'Done' controls whether the
- // option even _WANTS_ any more.
- //
- bool Done = PositionalOpts[i]->getNumOccurrencesFlag() == cl::Required;
- while (NumVals - ValNo > NumPositionalRequired && !Done) {
- switch (PositionalOpts[i]->getNumOccurrencesFlag()) {
- case cl::Optional:
- Done = true; // Optional arguments want _at most_ one value
- LLVM_FALLTHROUGH;
- case cl::ZeroOrMore: // Zero or more will take all they can get...
- case cl::OneOrMore: // One or more will take all they can get...
- ProvidePositionalOption(PositionalOpts[i],
- PositionalVals[ValNo].first,
- PositionalVals[ValNo].second);
- ValNo++;
- break;
- default:
- llvm_unreachable("Internal error, unexpected NumOccurrences flag in "
- "positional argument processing!");
- }
- }
- }
- } else {
- assert(ConsumeAfterOpt && NumPositionalRequired <= PositionalVals.size());
- unsigned ValNo = 0;
- for (size_t j = 1, e = PositionalOpts.size(); j != e; ++j)
- if (RequiresValue(PositionalOpts[j])) {
- ErrorParsing |= ProvidePositionalOption(PositionalOpts[j],
- PositionalVals[ValNo].first,
- PositionalVals[ValNo].second);
- ValNo++;
- }
-
- // Handle the case where there is just one positional option, and it's
- // optional. In this case, we want to give JUST THE FIRST option to the
- // positional option and keep the rest for the consume after. The above
- // loop would have assigned no values to positional options in this case.
- //
- if (PositionalOpts.size() == 1 && ValNo == 0 && !PositionalVals.empty()) {
- ErrorParsing |= ProvidePositionalOption(PositionalOpts[0],
- PositionalVals[ValNo].first,
- PositionalVals[ValNo].second);
- ValNo++;
- }
-
- // Handle over all of the rest of the arguments to the
- // cl::ConsumeAfter command line option...
- for (; ValNo != PositionalVals.size(); ++ValNo)
- ErrorParsing |=
- ProvidePositionalOption(ConsumeAfterOpt, PositionalVals[ValNo].first,
- PositionalVals[ValNo].second);
- }
-
- // Loop over args and make sure all required args are specified!
- for (const auto &Opt : OptionsMap) {
- switch (Opt.second->getNumOccurrencesFlag()) {
- case Required:
- case OneOrMore:
- if (Opt.second->getNumOccurrences() == 0) {
- Opt.second->error("must be specified at least once!");
- ErrorParsing = true;
- }
- LLVM_FALLTHROUGH;
- default:
- break;
- }
- }
-
- // Now that we know if -debug is specified, we can use it.
- // Note that if ReadResponseFiles == true, this must be done before the
- // memory allocated for the expanded command line is free()d below.
- LLVM_DEBUG(dbgs() << "Args: ";
- for (int i = 0; i < argc; ++i) dbgs() << argv[i] << ' ';
- dbgs() << '\n';);
-
- // Free all of the memory allocated to the map. Command line options may only
- // be processed once!
- MoreHelp.clear();
-
- // If we had an error processing our arguments, don't let the program execute
- if (ErrorParsing) {
- if (!IgnoreErrors)
- exit(1);
- return false;
- }
- return true;
-}
-
-//===----------------------------------------------------------------------===//
-// Option Base class implementation
-//
-
-bool Option::error(const Twine &Message, StringRef ArgName, raw_ostream &Errs) {
- if (!ArgName.data())
- ArgName = ArgStr;
- if (ArgName.empty())
- Errs << HelpStr; // Be nice for positional arguments
- else
- Errs << GlobalParser->ProgramName << ": for the -" << ArgName;
-
- Errs << " option: " << Message << "\n";
- return true;
-}
-
-bool Option::addOccurrence(unsigned pos, StringRef ArgName, StringRef Value,
- bool MultiArg) {
- if (!MultiArg)
- NumOccurrences++; // Increment the number of times we have been seen
-
- switch (getNumOccurrencesFlag()) {
- case Optional:
- if (NumOccurrences > 1)
- return error("may only occur zero or one times!", ArgName);
- break;
- case Required:
- if (NumOccurrences > 1)
- return error("must occur exactly one time!", ArgName);
- LLVM_FALLTHROUGH;
- case OneOrMore:
- case ZeroOrMore:
- case ConsumeAfter:
- break;
- }
-
- return handleOccurrence(pos, ArgName, Value);
-}
-
-// getValueStr - Get the value description string, using "DefaultMsg" if nothing
-// has been specified yet.
-//
-static StringRef getValueStr(const Option &O, StringRef DefaultMsg) {
- if (O.ValueStr.empty())
- return DefaultMsg;
- return O.ValueStr;
-}
-
-//===----------------------------------------------------------------------===//
-// cl::alias class implementation
-//
-
-// Return the width of the option tag for printing...
-size_t alias::getOptionWidth() const { return ArgStr.size() + 6; }
-
-void Option::printHelpStr(StringRef HelpStr, size_t Indent,
- size_t FirstLineIndentedBy) {
- std::pair<StringRef, StringRef> Split = HelpStr.split('\n');
- outs().indent(Indent - FirstLineIndentedBy) << " - " << Split.first << "\n";
- while (!Split.second.empty()) {
- Split = Split.second.split('\n');
- outs().indent(Indent) << Split.first << "\n";
- }
-}
-
-// Print out the option for the alias.
-void alias::printOptionInfo(size_t GlobalWidth) const {
- outs() << " -" << ArgStr;
- printHelpStr(HelpStr, GlobalWidth, ArgStr.size() + 6);
-}
-
-//===----------------------------------------------------------------------===//
-// Parser Implementation code...
-//
-
-// basic_parser implementation
-//
-
-// Return the width of the option tag for printing...
-size_t basic_parser_impl::getOptionWidth(const Option &O) const {
- size_t Len = O.ArgStr.size();
- auto ValName = getValueName();
- if (!ValName.empty()) {
- size_t FormattingLen = 3;
- if (O.getMiscFlags() & PositionalEatsArgs)
- FormattingLen = 6;
- Len += getValueStr(O, ValName).size() + FormattingLen;
- }
-
- return Len + 6;
-}
-
-// printOptionInfo - Print out information about this option. The
-// to-be-maintained width is specified.
-//
-void basic_parser_impl::printOptionInfo(const Option &O,
- size_t GlobalWidth) const {
- outs() << " -" << O.ArgStr;
-
- auto ValName = getValueName();
- if (!ValName.empty()) {
- if (O.getMiscFlags() & PositionalEatsArgs) {
- outs() << " <" << getValueStr(O, ValName) << ">...";
- } else {
- outs() << "=<" << getValueStr(O, ValName) << '>';
- }
- }
-
- Option::printHelpStr(O.HelpStr, GlobalWidth, getOptionWidth(O));
-}
-
-void basic_parser_impl::printOptionName(const Option &O,
- size_t GlobalWidth) const {
- outs() << " -" << O.ArgStr;
- outs().indent(GlobalWidth - O.ArgStr.size());
-}
-
-// parser<bool> implementation
-//
-bool parser<bool>::parse(Option &O, StringRef ArgName, StringRef Arg,
- bool &Value) {
- if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||
- Arg == "1") {
- Value = true;
- return false;
- }
-
- if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {
- Value = false;
- return false;
- }
- return O.error("'" + Arg +
- "' is invalid value for boolean argument! Try 0 or 1");
-}
-
-// parser<boolOrDefault> implementation
-//
-bool parser<boolOrDefault>::parse(Option &O, StringRef ArgName, StringRef Arg,
- boolOrDefault &Value) {
- if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||
- Arg == "1") {
- Value = BOU_TRUE;
- return false;
- }
- if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {
- Value = BOU_FALSE;
- return false;
- }
-
- return O.error("'" + Arg +
- "' is invalid value for boolean argument! Try 0 or 1");
-}
-
-// parser<int> implementation
-//
-bool parser<int>::parse(Option &O, StringRef ArgName, StringRef Arg,
- int &Value) {
- if (Arg.getAsInteger(0, Value))
- return O.error("'" + Arg + "' value invalid for integer argument!");
- return false;
-}
-
-// parser<unsigned> implementation
-//
-bool parser<unsigned>::parse(Option &O, StringRef ArgName, StringRef Arg,
- unsigned &Value) {
-
- if (Arg.getAsInteger(0, Value))
- return O.error("'" + Arg + "' value invalid for uint argument!");
- return false;
-}
-
-// parser<unsigned long long> implementation
-//
-bool parser<unsigned long long>::parse(Option &O, StringRef ArgName,
- StringRef Arg,
- unsigned long long &Value) {
-
- if (Arg.getAsInteger(0, Value))
- return O.error("'" + Arg + "' value invalid for uint argument!");
- return false;
-}
-
-// parser<double>/parser<float> implementation
-//
-static bool parseDouble(Option &O, StringRef Arg, double &Value) {
- if (to_float(Arg, Value))
- return false;
- return O.error("'" + Arg + "' value invalid for floating point argument!");
-}
-
-bool parser<double>::parse(Option &O, StringRef ArgName, StringRef Arg,
- double &Val) {
- return parseDouble(O, Arg, Val);
-}
-
-bool parser<float>::parse(Option &O, StringRef ArgName, StringRef Arg,
- float &Val) {
- double dVal;
- if (parseDouble(O, Arg, dVal))
- return true;
- Val = (float)dVal;
- return false;
-}
-
-// generic_parser_base implementation
-//
-
-// findOption - Return the option number corresponding to the specified
-// argument string. If the option is not found, getNumOptions() is returned.
-//
-unsigned generic_parser_base::findOption(StringRef Name) {
- unsigned e = getNumOptions();
-
- for (unsigned i = 0; i != e; ++i) {
- if (getOption(i) == Name)
- return i;
- }
- return e;
-}
-
-// Return the width of the option tag for printing...
-size_t generic_parser_base::getOptionWidth(const Option &O) const {
- if (O.hasArgStr()) {
- size_t Size = O.ArgStr.size() + 6;
- for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
- Size = std::max(Size, getOption(i).size() + 8);
- return Size;
- } else {
- size_t BaseSize = 0;
- for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
- BaseSize = std::max(BaseSize, getOption(i).size() + 8);
- return BaseSize;
- }
-}
-
-// printOptionInfo - Print out information about this option. The
-// to-be-maintained width is specified.
-//
-void generic_parser_base::printOptionInfo(const Option &O,
- size_t GlobalWidth) const {
- if (O.hasArgStr()) {
- outs() << " -" << O.ArgStr;
- Option::printHelpStr(O.HelpStr, GlobalWidth, O.ArgStr.size() + 6);
-
- for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
- size_t NumSpaces = GlobalWidth - getOption(i).size() - 8;
- outs() << " =" << getOption(i);
- outs().indent(NumSpaces) << " - " << getDescription(i) << '\n';
- }
- } else {
- if (!O.HelpStr.empty())
- outs() << " " << O.HelpStr << '\n';
- for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
- auto Option = getOption(i);
- outs() << " -" << Option;
- Option::printHelpStr(getDescription(i), GlobalWidth, Option.size() + 8);
- }
- }
-}
-
-static const size_t MaxOptWidth = 8; // arbitrary spacing for printOptionDiff
-
-// printGenericOptionDiff - Print the value of this option and it's default.
-//
-// "Generic" options have each value mapped to a name.
-void generic_parser_base::printGenericOptionDiff(
- const Option &O, const GenericOptionValue &Value,
- const GenericOptionValue &Default, size_t GlobalWidth) const {
- outs() << " -" << O.ArgStr;
- outs().indent(GlobalWidth - O.ArgStr.size());
-
- unsigned NumOpts = getNumOptions();
- for (unsigned i = 0; i != NumOpts; ++i) {
- if (Value.compare(getOptionValue(i)))
- continue;
-
- outs() << "= " << getOption(i);
- size_t L = getOption(i).size();
- size_t NumSpaces = MaxOptWidth > L ? MaxOptWidth - L : 0;
- outs().indent(NumSpaces) << " (default: ";
- for (unsigned j = 0; j != NumOpts; ++j) {
- if (Default.compare(getOptionValue(j)))
- continue;
- outs() << getOption(j);
- break;
- }
- outs() << ")\n";
- return;
- }
- outs() << "= *unknown option value*\n";
-}
-
-// printOptionDiff - Specializations for printing basic value types.
-//
-#define PRINT_OPT_DIFF(T) \
- void parser<T>::printOptionDiff(const Option &O, T V, OptionValue<T> D, \
- size_t GlobalWidth) const { \
- printOptionName(O, GlobalWidth); \
- std::string Str; \
- { \
- raw_string_ostream SS(Str); \
- SS << V; \
- } \
- outs() << "= " << Str; \
- size_t NumSpaces = \
- MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0; \
- outs().indent(NumSpaces) << " (default: "; \
- if (D.hasValue()) \
- outs() << D.getValue(); \
- else \
- outs() << "*no default*"; \
- outs() << ")\n"; \
- }
-
-PRINT_OPT_DIFF(bool)
-PRINT_OPT_DIFF(boolOrDefault)
-PRINT_OPT_DIFF(int)
-PRINT_OPT_DIFF(unsigned)
-PRINT_OPT_DIFF(unsigned long long)
-PRINT_OPT_DIFF(double)
-PRINT_OPT_DIFF(float)
-PRINT_OPT_DIFF(char)
-
-void parser<std::string>::printOptionDiff(const Option &O, StringRef V,
- const OptionValue<std::string> &D,
- size_t GlobalWidth) const {
- printOptionName(O, GlobalWidth);
- outs() << "= " << V;
- size_t NumSpaces = MaxOptWidth > V.size() ? MaxOptWidth - V.size() : 0;
- outs().indent(NumSpaces) << " (default: ";
- if (D.hasValue())
- outs() << D.getValue();
- else
- outs() << "*no default*";
- outs() << ")\n";
-}
-
-// Print a placeholder for options that don't yet support printOptionDiff().
-void basic_parser_impl::printOptionNoValue(const Option &O,
- size_t GlobalWidth) const {
- printOptionName(O, GlobalWidth);
- outs() << "= *cannot print option value*\n";
-}
-
-//===----------------------------------------------------------------------===//
-// -help and -help-hidden option implementation
-//
-
-static int OptNameCompare(const std::pair<const char *, Option *> *LHS,
- const std::pair<const char *, Option *> *RHS) {
- return strcmp(LHS->first, RHS->first);
-}
-
-static int SubNameCompare(const std::pair<const char *, SubCommand *> *LHS,
- const std::pair<const char *, SubCommand *> *RHS) {
- return strcmp(LHS->first, RHS->first);
-}
-
-// Copy Options into a vector so we can sort them as we like.
-static void sortOpts(StringMap<Option *> &OptMap,
- SmallVectorImpl<std::pair<const char *, Option *>> &Opts,
- bool ShowHidden) {
- SmallPtrSet<Option *, 32> OptionSet; // Duplicate option detection.
-
- for (StringMap<Option *>::iterator I = OptMap.begin(), E = OptMap.end();
- I != E; ++I) {
- // Ignore really-hidden options.
- if (I->second->getOptionHiddenFlag() == ReallyHidden)
- continue;
-
- // Unless showhidden is set, ignore hidden flags.
- if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden)
- continue;
-
- // If we've already seen this option, don't add it to the list again.
- if (!OptionSet.insert(I->second).second)
- continue;
-
- Opts.push_back(
- std::pair<const char *, Option *>(I->getKey().data(), I->second));
- }
-
- // Sort the options list alphabetically.
- array_pod_sort(Opts.begin(), Opts.end(), OptNameCompare);
-}
-
-static void
-sortSubCommands(const SmallPtrSetImpl<SubCommand *> &SubMap,
- SmallVectorImpl<std::pair<const char *, SubCommand *>> &Subs) {
- for (const auto &S : SubMap) {
- if (S->getName().empty())
- continue;
- Subs.push_back(std::make_pair(S->getName().data(), S));
- }
- array_pod_sort(Subs.begin(), Subs.end(), SubNameCompare);
-}
-
-namespace {
-
-class HelpPrinter {
-protected:
- const bool ShowHidden;
- typedef SmallVector<std::pair<const char *, Option *>, 128>
- StrOptionPairVector;
- typedef SmallVector<std::pair<const char *, SubCommand *>, 128>
- StrSubCommandPairVector;
- // Print the options. Opts is assumed to be alphabetically sorted.
- virtual void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) {
- for (size_t i = 0, e = Opts.size(); i != e; ++i)
- Opts[i].second->printOptionInfo(MaxArgLen);
- }
-
- void printSubCommands(StrSubCommandPairVector &Subs, size_t MaxSubLen) {
- for (const auto &S : Subs) {
- outs() << " " << S.first;
- if (!S.second->getDescription().empty()) {
- outs().indent(MaxSubLen - strlen(S.first));
- outs() << " - " << S.second->getDescription();
- }
- outs() << "\n";
- }
- }
-
-public:
- explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) {}
- virtual ~HelpPrinter() {}
-
- // Invoke the printer.
- void operator=(bool Value) {
- if (!Value)
- return;
- printHelp();
-
- // Halt the program since help information was printed
- exit(0);
- }
-
- void printHelp() {
- SubCommand *Sub = GlobalParser->getActiveSubCommand();
- auto &OptionsMap = Sub->OptionsMap;
- auto &PositionalOpts = Sub->PositionalOpts;
- auto &ConsumeAfterOpt = Sub->ConsumeAfterOpt;
-
- StrOptionPairVector Opts;
- sortOpts(OptionsMap, Opts, ShowHidden);
-
- StrSubCommandPairVector Subs;
- sortSubCommands(GlobalParser->RegisteredSubCommands, Subs);
-
- if (!GlobalParser->ProgramOverview.empty())
- outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n";
-
- if (Sub == &*TopLevelSubCommand) {
- outs() << "USAGE: " << GlobalParser->ProgramName;
- if (Subs.size() > 2)
- outs() << " [subcommand]";
- outs() << " [options]";
- } else {
- if (!Sub->getDescription().empty()) {
- outs() << "SUBCOMMAND '" << Sub->getName()
- << "': " << Sub->getDescription() << "\n\n";
- }
- outs() << "USAGE: " << GlobalParser->ProgramName << " " << Sub->getName()
- << " [options]";
- }
-
- for (auto Opt : PositionalOpts) {
- if (Opt->hasArgStr())
- outs() << " --" << Opt->ArgStr;
- outs() << " " << Opt->HelpStr;
- }
-
- // Print the consume after option info if it exists...
- if (ConsumeAfterOpt)
- outs() << " " << ConsumeAfterOpt->HelpStr;
-
- if (Sub == &*TopLevelSubCommand && !Subs.empty()) {
- // Compute the maximum subcommand length...
- size_t MaxSubLen = 0;
- for (size_t i = 0, e = Subs.size(); i != e; ++i)
- MaxSubLen = std::max(MaxSubLen, strlen(Subs[i].first));
-
- outs() << "\n\n";
- outs() << "SUBCOMMANDS:\n\n";
- printSubCommands(Subs, MaxSubLen);
- outs() << "\n";
- outs() << " Type \"" << GlobalParser->ProgramName
- << " <subcommand> -help\" to get more help on a specific "
- "subcommand";
- }
-
- outs() << "\n\n";
-
- // Compute the maximum argument length...
- size_t MaxArgLen = 0;
- for (size_t i = 0, e = Opts.size(); i != e; ++i)
- MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth());
-
- outs() << "OPTIONS:\n";
- printOptions(Opts, MaxArgLen);
-
- // Print any extra help the user has declared.
- for (auto I : GlobalParser->MoreHelp)
- outs() << I;
- GlobalParser->MoreHelp.clear();
- }
-};
-
-class CategorizedHelpPrinter : public HelpPrinter {
-public:
- explicit CategorizedHelpPrinter(bool showHidden) : HelpPrinter(showHidden) {}
-
- // Helper function for printOptions().
- // It shall return a negative value if A's name should be lexicographically
- // ordered before B's name. It returns a value greater than zero if B's name
- // should be ordered before A's name, and it returns 0 otherwise.
- static int OptionCategoryCompare(OptionCategory *const *A,
- OptionCategory *const *B) {
- return (*A)->getName().compare((*B)->getName());
- }
-
- // Make sure we inherit our base class's operator=()
- using HelpPrinter::operator=;
-
-protected:
- void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) override {
- std::vector<OptionCategory *> SortedCategories;
- std::map<OptionCategory *, std::vector<Option *>> CategorizedOptions;
-
- // Collect registered option categories into vector in preparation for
- // sorting.
- for (auto I = GlobalParser->RegisteredOptionCategories.begin(),
- E = GlobalParser->RegisteredOptionCategories.end();
- I != E; ++I) {
- SortedCategories.push_back(*I);
- }
-
- // Sort the different option categories alphabetically.
- assert(SortedCategories.size() > 0 && "No option categories registered!");
- array_pod_sort(SortedCategories.begin(), SortedCategories.end(),
- OptionCategoryCompare);
-
- // Create map to empty vectors.
- for (std::vector<OptionCategory *>::const_iterator
- I = SortedCategories.begin(),
- E = SortedCategories.end();
- I != E; ++I)
- CategorizedOptions[*I] = std::vector<Option *>();
-
- // Walk through pre-sorted options and assign into categories.
- // Because the options are already alphabetically sorted the
- // options within categories will also be alphabetically sorted.
- for (size_t I = 0, E = Opts.size(); I != E; ++I) {
- Option *Opt = Opts[I].second;
- assert(CategorizedOptions.count(Opt->Category) > 0 &&
- "Option has an unregistered category");
- CategorizedOptions[Opt->Category].push_back(Opt);
- }
-
- // Now do printing.
- for (std::vector<OptionCategory *>::const_iterator
- Category = SortedCategories.begin(),
- E = SortedCategories.end();
- Category != E; ++Category) {
- // Hide empty categories for -help, but show for -help-hidden.
- const auto &CategoryOptions = CategorizedOptions[*Category];
- bool IsEmptyCategory = CategoryOptions.empty();
- if (!ShowHidden && IsEmptyCategory)
- continue;
-
- // Print category information.
- outs() << "\n";
- outs() << (*Category)->getName() << ":\n";
-
- // Check if description is set.
- if (!(*Category)->getDescription().empty())
- outs() << (*Category)->getDescription() << "\n\n";
- else
- outs() << "\n";
-
- // When using -help-hidden explicitly state if the category has no
- // options associated with it.
- if (IsEmptyCategory) {
- outs() << " This option category has no options.\n";
- continue;
- }
- // Loop over the options in the category and print.
- for (const Option *Opt : CategoryOptions)
- Opt->printOptionInfo(MaxArgLen);
- }
- }
-};
-
-// This wraps the Uncategorizing and Categorizing printers and decides
-// at run time which should be invoked.
-class HelpPrinterWrapper {
-private:
- HelpPrinter &UncategorizedPrinter;
- CategorizedHelpPrinter &CategorizedPrinter;
-
-public:
- explicit HelpPrinterWrapper(HelpPrinter &UncategorizedPrinter,
- CategorizedHelpPrinter &CategorizedPrinter)
- : UncategorizedPrinter(UncategorizedPrinter),
- CategorizedPrinter(CategorizedPrinter) {}
-
- // Invoke the printer.
- void operator=(bool Value);
-};
-
-} // End anonymous namespace
-
-// Declare the four HelpPrinter instances that are used to print out help, or
-// help-hidden as an uncategorized list or in categories.
-static HelpPrinter UncategorizedNormalPrinter(false);
-static HelpPrinter UncategorizedHiddenPrinter(true);
-static CategorizedHelpPrinter CategorizedNormalPrinter(false);
-static CategorizedHelpPrinter CategorizedHiddenPrinter(true);
-
-// Declare HelpPrinter wrappers that will decide whether or not to invoke
-// a categorizing help printer
-static HelpPrinterWrapper WrappedNormalPrinter(UncategorizedNormalPrinter,
- CategorizedNormalPrinter);
-static HelpPrinterWrapper WrappedHiddenPrinter(UncategorizedHiddenPrinter,
- CategorizedHiddenPrinter);
-
-// Define a category for generic options that all tools should have.
-static cl::OptionCategory GenericCategory("Generic Options");
-
-// Define uncategorized help printers.
-// -help-list is hidden by default because if Option categories are being used
-// then -help behaves the same as -help-list.
-static cl::opt<HelpPrinter, true, parser<bool>> HLOp(
- "help-list",
- cl::desc("Display list of available options (-help-list-hidden for more)"),
- cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed,
- cl::cat(GenericCategory), cl::sub(*AllSubCommands));
-
-static cl::opt<HelpPrinter, true, parser<bool>>
- HLHOp("help-list-hidden", cl::desc("Display list of all available options"),
- cl::location(UncategorizedHiddenPrinter), cl::Hidden,
- cl::ValueDisallowed, cl::cat(GenericCategory),
- cl::sub(*AllSubCommands));
-
-// Define uncategorized/categorized help printers. These printers change their
-// behaviour at runtime depending on whether one or more Option categories have
-// been declared.
-static cl::opt<HelpPrinterWrapper, true, parser<bool>>
- HOp("help", cl::desc("Display available options (-help-hidden for more)"),
- cl::location(WrappedNormalPrinter), cl::ValueDisallowed,
- cl::cat(GenericCategory), cl::sub(*AllSubCommands));
-
-static cl::opt<HelpPrinterWrapper, true, parser<bool>>
- HHOp("help-hidden", cl::desc("Display all available options"),
- cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed,
- cl::cat(GenericCategory), cl::sub(*AllSubCommands));
-
-static cl::opt<bool> PrintOptions(
- "print-options",
- cl::desc("Print non-default options after command line parsing"),
- cl::Hidden, cl::init(false), cl::cat(GenericCategory),
- cl::sub(*AllSubCommands));
-
-static cl::opt<bool> PrintAllOptions(
- "print-all-options",
- cl::desc("Print all option values after command line parsing"), cl::Hidden,
- cl::init(false), cl::cat(GenericCategory), cl::sub(*AllSubCommands));
-
-void HelpPrinterWrapper::operator=(bool Value) {
- if (!Value)
- return;
-
- // Decide which printer to invoke. If more than one option category is
- // registered then it is useful to show the categorized help instead of
- // uncategorized help.
- if (GlobalParser->RegisteredOptionCategories.size() > 1) {
- // unhide -help-list option so user can have uncategorized output if they
- // want it.
- HLOp.setHiddenFlag(NotHidden);
-
- CategorizedPrinter = true; // Invoke categorized printer
- } else
- UncategorizedPrinter = true; // Invoke uncategorized printer
-}
-
-// Print the value of each option.
-void cl::PrintOptionValues() { GlobalParser->printOptionValues(); }
-
-void CommandLineParser::printOptionValues() {
- if (!PrintOptions && !PrintAllOptions)
- return;
-
- SmallVector<std::pair<const char *, Option *>, 128> Opts;
- sortOpts(ActiveSubCommand->OptionsMap, Opts, /*ShowHidden*/ true);
-
- // Compute the maximum argument length...
- size_t MaxArgLen = 0;
- for (size_t i = 0, e = Opts.size(); i != e; ++i)
- MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth());
-
- for (size_t i = 0, e = Opts.size(); i != e; ++i)
- Opts[i].second->printOptionValue(MaxArgLen, PrintAllOptions);
-}
-
-static VersionPrinterTy OverrideVersionPrinter = nullptr;
-
-static std::vector<VersionPrinterTy> *ExtraVersionPrinters = nullptr;
-
-namespace {
-class VersionPrinter {
-public:
- void print() {
- raw_ostream &OS = outs();
-#ifdef PACKAGE_VENDOR
- OS << PACKAGE_VENDOR << " ";
-#else
- OS << "LLVM (http://llvm.org/):\n ";
-#endif
- OS << PACKAGE_NAME << " version " << PACKAGE_VERSION;
-#ifdef LLVM_VERSION_INFO
- OS << " " << LLVM_VERSION_INFO;
-#endif
- OS << "\n ";
-#ifndef __OPTIMIZE__
- OS << "DEBUG build";
-#else
- OS << "Optimized build";
-#endif
-#ifndef NDEBUG
- OS << " with assertions";
-#endif
-#if LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO
- std::string CPU = sys::getHostCPUName();
- if (CPU == "generic")
- CPU = "(unknown)";
- OS << ".\n"
- << " Default target: " << sys::getDefaultTargetTriple() << '\n'
- << " Host CPU: " << CPU;
-#endif
- OS << '\n';
- }
- void operator=(bool OptionWasSpecified) {
- if (!OptionWasSpecified)
- return;
-
- if (OverrideVersionPrinter != nullptr) {
- OverrideVersionPrinter(outs());
- exit(0);
- }
- print();
-
- // Iterate over any registered extra printers and call them to add further
- // information.
- if (ExtraVersionPrinters != nullptr) {
- outs() << '\n';
- for (auto I : *ExtraVersionPrinters)
- I(outs());
- }
-
- exit(0);
- }
-};
-} // End anonymous namespace
-
-// Define the --version option that prints out the LLVM version for the tool
-static VersionPrinter VersionPrinterInstance;
-
-static cl::opt<VersionPrinter, true, parser<bool>>
- VersOp("version", cl::desc("Display the version of this program"),
- cl::location(VersionPrinterInstance), cl::ValueDisallowed,
- cl::cat(GenericCategory));
-
-// Utility function for printing the help message.
-void cl::PrintHelpMessage(bool Hidden, bool Categorized) {
- if (!Hidden && !Categorized)
- UncategorizedNormalPrinter.printHelp();
- else if (!Hidden && Categorized)
- CategorizedNormalPrinter.printHelp();
- else if (Hidden && !Categorized)
- UncategorizedHiddenPrinter.printHelp();
- else
- CategorizedHiddenPrinter.printHelp();
-}
-
-/// Utility function for printing version number.
-void cl::PrintVersionMessage() { VersionPrinterInstance.print(); }
-
-void cl::SetVersionPrinter(VersionPrinterTy func) { OverrideVersionPrinter = func; }
-
-void cl::AddExtraVersionPrinter(VersionPrinterTy func) {
- if (!ExtraVersionPrinters)
- ExtraVersionPrinters = new std::vector<VersionPrinterTy>;
-
- ExtraVersionPrinters->push_back(func);
-}
-
-StringMap<Option *> &cl::getRegisteredOptions(SubCommand &Sub) {
- auto &Subs = GlobalParser->RegisteredSubCommands;
- (void)Subs;
- assert(is_contained(Subs, &Sub));
- return Sub.OptionsMap;
-}
-
-iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator>
-cl::getRegisteredSubcommands() {
- return GlobalParser->getRegisteredSubcommands();
-}
-
-void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {
- for (auto &I : Sub.OptionsMap) {
- if (I.second->Category != &Category &&
- I.second->Category != &GenericCategory)
- I.second->setHiddenFlag(cl::ReallyHidden);
- }
-}
-
-void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
- SubCommand &Sub) {
- auto CategoriesBegin = Categories.begin();
- auto CategoriesEnd = Categories.end();
- for (auto &I : Sub.OptionsMap) {
- if (std::find(CategoriesBegin, CategoriesEnd, I.second->Category) ==
- CategoriesEnd &&
- I.second->Category != &GenericCategory)
- I.second->setHiddenFlag(cl::ReallyHidden);
- }
-}
-
-void cl::ResetCommandLineParser() { GlobalParser->reset(); }
-void cl::ResetAllOptionOccurrences() {
- GlobalParser->ResetAllOptionOccurrences();
-}
-
-void LLVMParseCommandLineOptions(int argc, const char *const *argv,
- const char *Overview) {
- llvm::cl::ParseCommandLineOptions(argc, argv, StringRef(Overview),
- &llvm::nulls());
-}
diff --git a/gnu/llvm/lib/Support/Compression.cpp b/gnu/llvm/lib/Support/Compression.cpp
deleted file mode 100644
index 95261d4aad2..00000000000
--- a/gnu/llvm/lib/Support/Compression.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-//===--- Compression.cpp - Compression implementation ---------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements compression functions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Compression.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorHandling.h"
-#if LLVM_ENABLE_ZLIB == 1 && HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-using namespace llvm;
-
-#if LLVM_ENABLE_ZLIB == 1 && HAVE_LIBZ
-static Error createError(StringRef Err) {
- return make_error<StringError>(Err, inconvertibleErrorCode());
-}
-
-static StringRef convertZlibCodeToString(int Code) {
- switch (Code) {
- case Z_MEM_ERROR:
- return "zlib error: Z_MEM_ERROR";
- case Z_BUF_ERROR:
- return "zlib error: Z_BUF_ERROR";
- case Z_STREAM_ERROR:
- return "zlib error: Z_STREAM_ERROR";
- case Z_DATA_ERROR:
- return "zlib error: Z_DATA_ERROR";
- case Z_OK:
- default:
- llvm_unreachable("unknown or unexpected zlib status code");
- }
-}
-
-bool zlib::isAvailable() { return true; }
-
-Error zlib::compress(StringRef InputBuffer,
- SmallVectorImpl<char> &CompressedBuffer, int Level) {
- unsigned long CompressedSize = ::compressBound(InputBuffer.size());
- CompressedBuffer.reserve(CompressedSize);
- int Res =
- ::compress2((Bytef *)CompressedBuffer.data(), &CompressedSize,
- (const Bytef *)InputBuffer.data(), InputBuffer.size(), Level);
- // Tell MemorySanitizer that zlib output buffer is fully initialized.
- // This avoids a false report when running LLVM with uninstrumented ZLib.
- __msan_unpoison(CompressedBuffer.data(), CompressedSize);
- CompressedBuffer.set_size(CompressedSize);
- return Res ? createError(convertZlibCodeToString(Res)) : Error::success();
-}
-
-Error zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer,
- size_t &UncompressedSize) {
- int Res =
- ::uncompress((Bytef *)UncompressedBuffer, (uLongf *)&UncompressedSize,
- (const Bytef *)InputBuffer.data(), InputBuffer.size());
- // Tell MemorySanitizer that zlib output buffer is fully initialized.
- // This avoids a false report when running LLVM with uninstrumented ZLib.
- __msan_unpoison(UncompressedBuffer, UncompressedSize);
- return Res ? createError(convertZlibCodeToString(Res)) : Error::success();
-}
-
-Error zlib::uncompress(StringRef InputBuffer,
- SmallVectorImpl<char> &UncompressedBuffer,
- size_t UncompressedSize) {
- UncompressedBuffer.resize(UncompressedSize);
- Error E =
- uncompress(InputBuffer, UncompressedBuffer.data(), UncompressedSize);
- UncompressedBuffer.resize(UncompressedSize);
- return E;
-}
-
-uint32_t zlib::crc32(StringRef Buffer) {
- return ::crc32(0, (const Bytef *)Buffer.data(), Buffer.size());
-}
-
-#else
-bool zlib::isAvailable() { return false; }
-Error zlib::compress(StringRef InputBuffer,
- SmallVectorImpl<char> &CompressedBuffer, int Level) {
- llvm_unreachable("zlib::compress is unavailable");
-}
-Error zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer,
- size_t &UncompressedSize) {
- llvm_unreachable("zlib::uncompress is unavailable");
-}
-Error zlib::uncompress(StringRef InputBuffer,
- SmallVectorImpl<char> &UncompressedBuffer,
- size_t UncompressedSize) {
- llvm_unreachable("zlib::uncompress is unavailable");
-}
-uint32_t zlib::crc32(StringRef Buffer) {
- llvm_unreachable("zlib::crc32 is unavailable");
-}
-#endif
diff --git a/gnu/llvm/lib/Support/ConvertUTF.cpp b/gnu/llvm/lib/Support/ConvertUTF.cpp
deleted file mode 100644
index 8f02fae4f55..00000000000
--- a/gnu/llvm/lib/Support/ConvertUTF.cpp
+++ /dev/null
@@ -1,739 +0,0 @@
-/*===--- ConvertUTF.c - Universal Character Names conversions ---------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
- *
- *===------------------------------------------------------------------------=*/
-/*
- * Copyright 2001-2004 Unicode, Inc.
- *
- * Disclaimer
- *
- * This source code is provided as is by Unicode, Inc. No claims are
- * made as to fitness for any particular purpose. No warranties of any
- * kind are expressed or implied. The recipient agrees to determine
- * applicability of information provided. If this file has been
- * purchased on magnetic or optical media from Unicode, Inc., the
- * sole remedy for any claim will be exchange of defective media
- * within 90 days of receipt.
- *
- * Limitations on Rights to Redistribute This Code
- *
- * Unicode, Inc. hereby grants the right to freely use the information
- * supplied in this file in the creation of products supporting the
- * Unicode Standard, and to make copies of this file in any form
- * for internal or external distribution as long as this notice
- * remains attached.
- */
-
-/* ---------------------------------------------------------------------
-
- Conversions between UTF32, UTF-16, and UTF-8. Source code file.
- Author: Mark E. Davis, 1994.
- Rev History: Rick McGowan, fixes & updates May 2001.
- Sept 2001: fixed const & error conditions per
- mods suggested by S. Parent & A. Lillich.
- June 2002: Tim Dodd added detection and handling of incomplete
- source sequences, enhanced error detection, added casts
- to eliminate compiler warnings.
- July 2003: slight mods to back out aggressive FFFE detection.
- Jan 2004: updated switches in from-UTF8 conversions.
- Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
-
- See the header file "ConvertUTF.h" for complete documentation.
-
------------------------------------------------------------------------- */
-
-#include "llvm/Support/ConvertUTF.h"
-#ifdef CVTUTF_DEBUG
-#include <stdio.h>
-#endif
-#include <assert.h>
-
-/*
- * This code extensively uses fall-through switches.
- * Keep the compiler from warning about that.
- */
-#if defined(__clang__) && defined(__has_warning)
-# if __has_warning("-Wimplicit-fallthrough")
-# define ConvertUTF_DISABLE_WARNINGS \
- _Pragma("clang diagnostic push") \
- _Pragma("clang diagnostic ignored \"-Wimplicit-fallthrough\"")
-# define ConvertUTF_RESTORE_WARNINGS \
- _Pragma("clang diagnostic pop")
-# endif
-#elif defined(__GNUC__) && __GNUC__ > 6
-# define ConvertUTF_DISABLE_WARNINGS \
- _Pragma("GCC diagnostic push") \
- _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
-# define ConvertUTF_RESTORE_WARNINGS \
- _Pragma("GCC diagnostic pop")
-#endif
-#ifndef ConvertUTF_DISABLE_WARNINGS
-# define ConvertUTF_DISABLE_WARNINGS
-#endif
-#ifndef ConvertUTF_RESTORE_WARNINGS
-# define ConvertUTF_RESTORE_WARNINGS
-#endif
-
-ConvertUTF_DISABLE_WARNINGS
-
-namespace llvm {
-
-static const int halfShift = 10; /* used for shifting by 10 bits */
-
-static const UTF32 halfBase = 0x0010000UL;
-static const UTF32 halfMask = 0x3FFUL;
-
-#define UNI_SUR_HIGH_START (UTF32)0xD800
-#define UNI_SUR_HIGH_END (UTF32)0xDBFF
-#define UNI_SUR_LOW_START (UTF32)0xDC00
-#define UNI_SUR_LOW_END (UTF32)0xDFFF
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Index into the table below with the first byte of a UTF-8 sequence to
- * get the number of trailing bytes that are supposed to follow it.
- * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
- * left as-is for anyone who may want to do such conversion, which was
- * allowed in earlier algorithms.
- */
-static const char trailingBytesForUTF8[256] = {
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
-};
-
-/*
- * Magic values subtracted from a buffer value during UTF8 conversion.
- * This table contains as many values as there might be trailing bytes
- * in a UTF-8 sequence.
- */
-static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
- 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
-
-/*
- * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
- * into the first byte, depending on how many bytes follow. There are
- * as many entries in this table as there are UTF-8 sequence types.
- * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
- * for *legal* UTF-8 will be 4 or fewer bytes total.
- */
-static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-
-/* --------------------------------------------------------------------- */
-
-/* The interface converts a whole buffer to avoid function-call overhead.
- * Constants have been gathered. Loops & conditionals have been removed as
- * much as possible for efficiency, in favor of drop-through switches.
- * (See "Note A" at the bottom of the file for equivalent code.)
- * If your compiler supports it, the "isLegalUTF8" call can be turned
- * into an inline function.
- */
-
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF32toUTF16 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF32* source = *sourceStart;
- UTF16* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch;
- if (target >= targetEnd) {
- result = targetExhausted; break;
- }
- ch = *source++;
- if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
- /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = (UTF16)ch; /* normal case */
- }
- } else if (ch > UNI_MAX_LEGAL_UTF32) {
- if (flags == strictConversion) {
- result = sourceIllegal;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- /* target is a character in range 0xFFFF - 0x10FFFF. */
- if (target + 1 >= targetEnd) {
- --source; /* Back up source pointer! */
- result = targetExhausted; break;
- }
- ch -= halfBase;
- *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
- *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
- }
- }
- *sourceStart = source;
- *targetStart = target;
- return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF16toUTF32 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF16* source = *sourceStart;
- UTF32* target = *targetStart;
- UTF32 ch, ch2;
- while (source < sourceEnd) {
- const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
- ch = *source++;
- /* If we have a surrogate pair, convert to UTF32 first. */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
- /* If the 16 bits following the high surrogate are in the source buffer... */
- if (source < sourceEnd) {
- ch2 = *source;
- /* If it's a low surrogate, convert to UTF32. */
- if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
- ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
- + (ch2 - UNI_SUR_LOW_START) + halfBase;
- ++source;
- } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- } else { /* We don't have the 16 bits following the high surrogate. */
- --source; /* return to the high surrogate */
- result = sourceExhausted;
- break;
- }
- } else if (flags == strictConversion) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- if (target >= targetEnd) {
- source = oldSource; /* Back up source pointer! */
- result = targetExhausted; break;
- }
- *target++ = ch;
- }
- *sourceStart = source;
- *targetStart = target;
-#ifdef CVTUTF_DEBUG
-if (result == sourceIllegal) {
- fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
- fflush(stderr);
-}
-#endif
- return result;
-}
-ConversionResult ConvertUTF16toUTF8 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF16* source = *sourceStart;
- UTF8* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch;
- unsigned short bytesToWrite = 0;
- const UTF32 byteMask = 0xBF;
- const UTF32 byteMark = 0x80;
- const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
- ch = *source++;
- /* If we have a surrogate pair, convert to UTF32 first. */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
- /* If the 16 bits following the high surrogate are in the source buffer... */
- if (source < sourceEnd) {
- UTF32 ch2 = *source;
- /* If it's a low surrogate, convert to UTF32. */
- if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
- ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
- + (ch2 - UNI_SUR_LOW_START) + halfBase;
- ++source;
- } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- } else { /* We don't have the 16 bits following the high surrogate. */
- --source; /* return to the high surrogate */
- result = sourceExhausted;
- break;
- }
- } else if (flags == strictConversion) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- /* Figure out how many bytes the result will require */
- if (ch < (UTF32)0x80) { bytesToWrite = 1;
- } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
- } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
- } else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
- } else { bytesToWrite = 3;
- ch = UNI_REPLACEMENT_CHAR;
- }
-
- target += bytesToWrite;
- if (target > targetEnd) {
- source = oldSource; /* Back up source pointer! */
- target -= bytesToWrite; result = targetExhausted; break;
- }
- switch (bytesToWrite) { /* note: everything falls through. */
- case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
- }
- target += bytesToWrite;
- }
- *sourceStart = source;
- *targetStart = target;
- return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF32toUTF8 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF32* source = *sourceStart;
- UTF8* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch;
- unsigned short bytesToWrite = 0;
- const UTF32 byteMask = 0xBF;
- const UTF32 byteMark = 0x80;
- ch = *source++;
- if (flags == strictConversion ) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- /*
- * Figure out how many bytes the result will require. Turn any
- * illegally large UTF32 things (> Plane 17) into replacement chars.
- */
- if (ch < (UTF32)0x80) { bytesToWrite = 1;
- } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
- } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
- } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
- } else { bytesToWrite = 3;
- ch = UNI_REPLACEMENT_CHAR;
- result = sourceIllegal;
- }
-
- target += bytesToWrite;
- if (target > targetEnd) {
- --source; /* Back up source pointer! */
- target -= bytesToWrite; result = targetExhausted; break;
- }
- switch (bytesToWrite) { /* note: everything falls through. */
- case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
- }
- target += bytesToWrite;
- }
- *sourceStart = source;
- *targetStart = target;
- return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Utility routine to tell whether a sequence of bytes is legal UTF-8.
- * This must be called with the length pre-determined by the first byte.
- * If not calling this from ConvertUTF8to*, then the length can be set by:
- * length = trailingBytesForUTF8[*source]+1;
- * and the sequence is illegal right away if there aren't that many bytes
- * available.
- * If presented with a length > 4, this returns false. The Unicode
- * definition of UTF-8 goes up to 4-byte sequences.
- */
-
-static Boolean isLegalUTF8(const UTF8 *source, int length) {
- UTF8 a;
- const UTF8 *srcptr = source+length;
- switch (length) {
- default: return false;
- /* Everything else falls through when "true"... */
- case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
- case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
- case 2: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
-
- switch (*source) {
- /* no fall-through in this inner switch */
- case 0xE0: if (a < 0xA0) return false; break;
- case 0xED: if (a > 0x9F) return false; break;
- case 0xF0: if (a < 0x90) return false; break;
- case 0xF4: if (a > 0x8F) return false; break;
- default: if (a < 0x80) return false;
- }
-
- case 1: if (*source >= 0x80 && *source < 0xC2) return false;
- }
- if (*source > 0xF4) return false;
- return true;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Exported function to return whether a UTF-8 sequence is legal or not.
- * This is not used here; it's just exported.
- */
-Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
- int length = trailingBytesForUTF8[*source]+1;
- if (length > sourceEnd - source) {
- return false;
- }
- return isLegalUTF8(source, length);
-}
-
-/* --------------------------------------------------------------------- */
-
-static unsigned
-findMaximalSubpartOfIllFormedUTF8Sequence(const UTF8 *source,
- const UTF8 *sourceEnd) {
- UTF8 b1, b2, b3;
-
- assert(!isLegalUTF8Sequence(source, sourceEnd));
-
- /*
- * Unicode 6.3.0, D93b:
- *
- * Maximal subpart of an ill-formed subsequence: The longest code unit
- * subsequence starting at an unconvertible offset that is either:
- * a. the initial subsequence of a well-formed code unit sequence, or
- * b. a subsequence of length one.
- */
-
- if (source == sourceEnd)
- return 0;
-
- /*
- * Perform case analysis. See Unicode 6.3.0, Table 3-7. Well-Formed UTF-8
- * Byte Sequences.
- */
-
- b1 = *source;
- ++source;
- if (b1 >= 0xC2 && b1 <= 0xDF) {
- /*
- * First byte is valid, but we know that this code unit sequence is
- * invalid, so the maximal subpart has to end after the first byte.
- */
- return 1;
- }
-
- if (source == sourceEnd)
- return 1;
-
- b2 = *source;
- ++source;
-
- if (b1 == 0xE0) {
- return (b2 >= 0xA0 && b2 <= 0xBF) ? 2 : 1;
- }
- if (b1 >= 0xE1 && b1 <= 0xEC) {
- return (b2 >= 0x80 && b2 <= 0xBF) ? 2 : 1;
- }
- if (b1 == 0xED) {
- return (b2 >= 0x80 && b2 <= 0x9F) ? 2 : 1;
- }
- if (b1 >= 0xEE && b1 <= 0xEF) {
- return (b2 >= 0x80 && b2 <= 0xBF) ? 2 : 1;
- }
- if (b1 == 0xF0) {
- if (b2 >= 0x90 && b2 <= 0xBF) {
- if (source == sourceEnd)
- return 2;
-
- b3 = *source;
- return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2;
- }
- return 1;
- }
- if (b1 >= 0xF1 && b1 <= 0xF3) {
- if (b2 >= 0x80 && b2 <= 0xBF) {
- if (source == sourceEnd)
- return 2;
-
- b3 = *source;
- return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2;
- }
- return 1;
- }
- if (b1 == 0xF4) {
- if (b2 >= 0x80 && b2 <= 0x8F) {
- if (source == sourceEnd)
- return 2;
-
- b3 = *source;
- return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2;
- }
- return 1;
- }
-
- assert((b1 >= 0x80 && b1 <= 0xC1) || b1 >= 0xF5);
- /*
- * There are no valid sequences that start with these bytes. Maximal subpart
- * is defined to have length 1 in these cases.
- */
- return 1;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Exported function to return the total number of bytes in a codepoint
- * represented in UTF-8, given the value of the first byte.
- */
-unsigned getNumBytesForUTF8(UTF8 first) {
- return trailingBytesForUTF8[first] + 1;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Exported function to return whether a UTF-8 string is legal or not.
- * This is not used here; it's just exported.
- */
-Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd) {
- while (*source != sourceEnd) {
- int length = trailingBytesForUTF8[**source] + 1;
- if (length > sourceEnd - *source || !isLegalUTF8(*source, length))
- return false;
- *source += length;
- }
- return true;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF8toUTF16 (
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF8* source = *sourceStart;
- UTF16* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch = 0;
- unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
- if (extraBytesToRead >= sourceEnd - source) {
- result = sourceExhausted; break;
- }
- /* Do this check whether lenient or strict */
- if (!isLegalUTF8(source, extraBytesToRead+1)) {
- result = sourceIllegal;
- break;
- }
- /*
- * The cases all fall through. See "Note A" below.
- */
- switch (extraBytesToRead) {
- case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 3: ch += *source++; ch <<= 6;
- case 2: ch += *source++; ch <<= 6;
- case 1: ch += *source++; ch <<= 6;
- case 0: ch += *source++;
- }
- ch -= offsetsFromUTF8[extraBytesToRead];
-
- if (target >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up source pointer! */
- result = targetExhausted; break;
- }
- if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- source -= (extraBytesToRead+1); /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = (UTF16)ch; /* normal case */
- }
- } else if (ch > UNI_MAX_UTF16) {
- if (flags == strictConversion) {
- result = sourceIllegal;
- source -= (extraBytesToRead+1); /* return to the start */
- break; /* Bail out; shouldn't continue */
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- /* target is a character in range 0xFFFF - 0x10FFFF. */
- if (target + 1 >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up source pointer! */
- result = targetExhausted; break;
- }
- ch -= halfBase;
- *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
- *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
- }
- }
- *sourceStart = source;
- *targetStart = target;
- return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-static ConversionResult ConvertUTF8toUTF32Impl(
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags,
- Boolean InputIsPartial) {
- ConversionResult result = conversionOK;
- const UTF8* source = *sourceStart;
- UTF32* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch = 0;
- unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
- if (extraBytesToRead >= sourceEnd - source) {
- if (flags == strictConversion || InputIsPartial) {
- result = sourceExhausted;
- break;
- } else {
- result = sourceIllegal;
-
- /*
- * Replace the maximal subpart of ill-formed sequence with
- * replacement character.
- */
- source += findMaximalSubpartOfIllFormedUTF8Sequence(source,
- sourceEnd);
- *target++ = UNI_REPLACEMENT_CHAR;
- continue;
- }
- }
- if (target >= targetEnd) {
- result = targetExhausted; break;
- }
-
- /* Do this check whether lenient or strict */
- if (!isLegalUTF8(source, extraBytesToRead+1)) {
- result = sourceIllegal;
- if (flags == strictConversion) {
- /* Abort conversion. */
- break;
- } else {
- /*
- * Replace the maximal subpart of ill-formed sequence with
- * replacement character.
- */
- source += findMaximalSubpartOfIllFormedUTF8Sequence(source,
- sourceEnd);
- *target++ = UNI_REPLACEMENT_CHAR;
- continue;
- }
- }
- /*
- * The cases all fall through. See "Note A" below.
- */
- switch (extraBytesToRead) {
- case 5: ch += *source++; ch <<= 6;
- case 4: ch += *source++; ch <<= 6;
- case 3: ch += *source++; ch <<= 6;
- case 2: ch += *source++; ch <<= 6;
- case 1: ch += *source++; ch <<= 6;
- case 0: ch += *source++;
- }
- ch -= offsetsFromUTF8[extraBytesToRead];
-
- if (ch <= UNI_MAX_LEGAL_UTF32) {
- /*
- * UTF-16 surrogate values are illegal in UTF-32, and anything
- * over Plane 17 (> 0x10FFFF) is illegal.
- */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- source -= (extraBytesToRead+1); /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = ch;
- }
- } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
- result = sourceIllegal;
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- }
- *sourceStart = source;
- *targetStart = target;
- return result;
-}
-
-ConversionResult ConvertUTF8toUTF32Partial(const UTF8 **sourceStart,
- const UTF8 *sourceEnd,
- UTF32 **targetStart,
- UTF32 *targetEnd,
- ConversionFlags flags) {
- return ConvertUTF8toUTF32Impl(sourceStart, sourceEnd, targetStart, targetEnd,
- flags, /*InputIsPartial=*/true);
-}
-
-ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart,
- const UTF8 *sourceEnd, UTF32 **targetStart,
- UTF32 *targetEnd, ConversionFlags flags) {
- return ConvertUTF8toUTF32Impl(sourceStart, sourceEnd, targetStart, targetEnd,
- flags, /*InputIsPartial=*/false);
-}
-
-/* ---------------------------------------------------------------------
-
- Note A.
- The fall-through switches in UTF-8 reading code save a
- temp variable, some decrements & conditionals. The switches
- are equivalent to the following loop:
- {
- int tmpBytesToRead = extraBytesToRead+1;
- do {
- ch += *source++;
- --tmpBytesToRead;
- if (tmpBytesToRead) ch <<= 6;
- } while (tmpBytesToRead > 0);
- }
- In UTF-8 writing code, the switches on "bytesToWrite" are
- similarly unrolled loops.
-
- --------------------------------------------------------------------- */
-
-} // namespace llvm
-
-ConvertUTF_RESTORE_WARNINGS
diff --git a/gnu/llvm/lib/Support/ConvertUTFWrapper.cpp b/gnu/llvm/lib/Support/ConvertUTFWrapper.cpp
deleted file mode 100644
index 6cb4f637625..00000000000
--- a/gnu/llvm/lib/Support/ConvertUTFWrapper.cpp
+++ /dev/null
@@ -1,251 +0,0 @@
-//===-- ConvertUTFWrapper.cpp - Wrap ConvertUTF.h with clang data types -----===
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/SwapByteOrder.h"
-#include <string>
-#include <vector>
-
-namespace llvm {
-
-bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source,
- char *&ResultPtr, const UTF8 *&ErrorPtr) {
- assert(WideCharWidth == 1 || WideCharWidth == 2 || WideCharWidth == 4);
- ConversionResult result = conversionOK;
- // Copy the character span over.
- if (WideCharWidth == 1) {
- const UTF8 *Pos = reinterpret_cast<const UTF8*>(Source.begin());
- if (!isLegalUTF8String(&Pos, reinterpret_cast<const UTF8*>(Source.end()))) {
- result = sourceIllegal;
- ErrorPtr = Pos;
- } else {
- memcpy(ResultPtr, Source.data(), Source.size());
- ResultPtr += Source.size();
- }
- } else if (WideCharWidth == 2) {
- const UTF8 *sourceStart = (const UTF8*)Source.data();
- // FIXME: Make the type of the result buffer correct instead of
- // using reinterpret_cast.
- UTF16 *targetStart = reinterpret_cast<UTF16*>(ResultPtr);
- ConversionFlags flags = strictConversion;
- result = ConvertUTF8toUTF16(
- &sourceStart, sourceStart + Source.size(),
- &targetStart, targetStart + Source.size(), flags);
- if (result == conversionOK)
- ResultPtr = reinterpret_cast<char*>(targetStart);
- else
- ErrorPtr = sourceStart;
- } else if (WideCharWidth == 4) {
- const UTF8 *sourceStart = (const UTF8*)Source.data();
- // FIXME: Make the type of the result buffer correct instead of
- // using reinterpret_cast.
- UTF32 *targetStart = reinterpret_cast<UTF32*>(ResultPtr);
- ConversionFlags flags = strictConversion;
- result = ConvertUTF8toUTF32(
- &sourceStart, sourceStart + Source.size(),
- &targetStart, targetStart + Source.size(), flags);
- if (result == conversionOK)
- ResultPtr = reinterpret_cast<char*>(targetStart);
- else
- ErrorPtr = sourceStart;
- }
- assert((result != targetExhausted)
- && "ConvertUTF8toUTFXX exhausted target buffer");
- return result == conversionOK;
-}
-
-bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) {
- const UTF32 *SourceStart = &Source;
- const UTF32 *SourceEnd = SourceStart + 1;
- UTF8 *TargetStart = reinterpret_cast<UTF8 *>(ResultPtr);
- UTF8 *TargetEnd = TargetStart + 4;
- ConversionResult CR = ConvertUTF32toUTF8(&SourceStart, SourceEnd,
- &TargetStart, TargetEnd,
- strictConversion);
- if (CR != conversionOK)
- return false;
-
- ResultPtr = reinterpret_cast<char*>(TargetStart);
- return true;
-}
-
-bool hasUTF16ByteOrderMark(ArrayRef<char> S) {
- return (S.size() >= 2 &&
- ((S[0] == '\xff' && S[1] == '\xfe') ||
- (S[0] == '\xfe' && S[1] == '\xff')));
-}
-
-bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) {
- assert(Out.empty());
-
- // Error out on an uneven byte count.
- if (SrcBytes.size() % 2)
- return false;
-
- // Avoid OOB by returning early on empty input.
- if (SrcBytes.empty())
- return true;
-
- const UTF16 *Src = reinterpret_cast<const UTF16 *>(SrcBytes.begin());
- const UTF16 *SrcEnd = reinterpret_cast<const UTF16 *>(SrcBytes.end());
-
- // Byteswap if necessary.
- std::vector<UTF16> ByteSwapped;
- if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) {
- ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
- for (unsigned I = 0, E = ByteSwapped.size(); I != E; ++I)
- ByteSwapped[I] = llvm::sys::SwapByteOrder_16(ByteSwapped[I]);
- Src = &ByteSwapped[0];
- SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
- }
-
- // Skip the BOM for conversion.
- if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE)
- Src++;
-
- // Just allocate enough space up front. We'll shrink it later. Allocate
- // enough that we can fit a null terminator without reallocating.
- Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1);
- UTF8 *Dst = reinterpret_cast<UTF8 *>(&Out[0]);
- UTF8 *DstEnd = Dst + Out.size();
-
- ConversionResult CR =
- ConvertUTF16toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
- assert(CR != targetExhausted);
-
- if (CR != conversionOK) {
- Out.clear();
- return false;
- }
-
- Out.resize(reinterpret_cast<char *>(Dst) - &Out[0]);
- Out.push_back(0);
- Out.pop_back();
- return true;
-}
-
-bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out)
-{
- return convertUTF16ToUTF8String(
- llvm::ArrayRef<char>(reinterpret_cast<const char *>(Src.data()),
- Src.size() * sizeof(UTF16)), Out);
-}
-
-bool convertUTF8ToUTF16String(StringRef SrcUTF8,
- SmallVectorImpl<UTF16> &DstUTF16) {
- assert(DstUTF16.empty());
-
- // Avoid OOB by returning early on empty input.
- if (SrcUTF8.empty()) {
- DstUTF16.push_back(0);
- DstUTF16.pop_back();
- return true;
- }
-
- const UTF8 *Src = reinterpret_cast<const UTF8 *>(SrcUTF8.begin());
- const UTF8 *SrcEnd = reinterpret_cast<const UTF8 *>(SrcUTF8.end());
-
- // Allocate the same number of UTF-16 code units as UTF-8 code units. Encoding
- // as UTF-16 should always require the same amount or less code units than the
- // UTF-8 encoding. Allocate one extra byte for the null terminator though,
- // so that someone calling DstUTF16.data() gets a null terminated string.
- // We resize down later so we don't have to worry that this over allocates.
- DstUTF16.resize(SrcUTF8.size()+1);
- UTF16 *Dst = &DstUTF16[0];
- UTF16 *DstEnd = Dst + DstUTF16.size();
-
- ConversionResult CR =
- ConvertUTF8toUTF16(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
- assert(CR != targetExhausted);
-
- if (CR != conversionOK) {
- DstUTF16.clear();
- return false;
- }
-
- DstUTF16.resize(Dst - &DstUTF16[0]);
- DstUTF16.push_back(0);
- DstUTF16.pop_back();
- return true;
-}
-
-static_assert(sizeof(wchar_t) == 1 || sizeof(wchar_t) == 2 ||
- sizeof(wchar_t) == 4,
- "Expected wchar_t to be 1, 2, or 4 bytes");
-
-template <typename TResult>
-static inline bool ConvertUTF8toWideInternal(llvm::StringRef Source,
- TResult &Result) {
- // Even in the case of UTF-16, the number of bytes in a UTF-8 string is
- // at least as large as the number of elements in the resulting wide
- // string, because surrogate pairs take at least 4 bytes in UTF-8.
- Result.resize(Source.size() + 1);
- char *ResultPtr = reinterpret_cast<char *>(&Result[0]);
- const UTF8 *ErrorPtr;
- if (!ConvertUTF8toWide(sizeof(wchar_t), Source, ResultPtr, ErrorPtr)) {
- Result.clear();
- return false;
- }
- Result.resize(reinterpret_cast<wchar_t *>(ResultPtr) - &Result[0]);
- return true;
-}
-
-bool ConvertUTF8toWide(llvm::StringRef Source, std::wstring &Result) {
- return ConvertUTF8toWideInternal(Source, Result);
-}
-
-bool ConvertUTF8toWide(const char *Source, std::wstring &Result) {
- if (!Source) {
- Result.clear();
- return true;
- }
- return ConvertUTF8toWide(llvm::StringRef(Source), Result);
-}
-
-bool convertWideToUTF8(const std::wstring &Source, std::string &Result) {
- if (sizeof(wchar_t) == 1) {
- const UTF8 *Start = reinterpret_cast<const UTF8 *>(Source.data());
- const UTF8 *End =
- reinterpret_cast<const UTF8 *>(Source.data() + Source.size());
- if (!isLegalUTF8String(&Start, End))
- return false;
- Result.resize(Source.size());
- memcpy(&Result[0], Source.data(), Source.size());
- return true;
- } else if (sizeof(wchar_t) == 2) {
- return convertUTF16ToUTF8String(
- llvm::ArrayRef<UTF16>(reinterpret_cast<const UTF16 *>(Source.data()),
- Source.size()),
- Result);
- } else if (sizeof(wchar_t) == 4) {
- const UTF32 *Start = reinterpret_cast<const UTF32 *>(Source.data());
- const UTF32 *End =
- reinterpret_cast<const UTF32 *>(Source.data() + Source.size());
- Result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * Source.size());
- UTF8 *ResultPtr = reinterpret_cast<UTF8 *>(&Result[0]);
- UTF8 *ResultEnd = reinterpret_cast<UTF8 *>(&Result[0] + Result.size());
- if (ConvertUTF32toUTF8(&Start, End, &ResultPtr, ResultEnd,
- strictConversion) == conversionOK) {
- Result.resize(reinterpret_cast<char *>(ResultPtr) - &Result[0]);
- return true;
- } else {
- Result.clear();
- return false;
- }
- } else {
- llvm_unreachable(
- "Control should never reach this point; see static_assert further up");
- }
-}
-
-} // end namespace llvm
-
diff --git a/gnu/llvm/lib/Support/CrashRecoveryContext.cpp b/gnu/llvm/lib/Support/CrashRecoveryContext.cpp
deleted file mode 100644
index be4b5c3e01c..00000000000
--- a/gnu/llvm/lib/Support/CrashRecoveryContext.cpp
+++ /dev/null
@@ -1,412 +0,0 @@
-//===--- CrashRecoveryContext.cpp - Crash Recovery ------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/CrashRecoveryContext.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/ThreadLocal.h"
-#include <setjmp.h>
-using namespace llvm;
-
-namespace {
-
-struct CrashRecoveryContextImpl;
-
-static ManagedStatic<
- sys::ThreadLocal<const CrashRecoveryContextImpl> > CurrentContext;
-
-struct CrashRecoveryContextImpl {
- // When threads are disabled, this links up all active
- // CrashRecoveryContextImpls. When threads are enabled there's one thread
- // per CrashRecoveryContext and CurrentContext is a thread-local, so only one
- // CrashRecoveryContextImpl is active per thread and this is always null.
- const CrashRecoveryContextImpl *Next;
-
- CrashRecoveryContext *CRC;
- ::jmp_buf JumpBuffer;
- volatile unsigned Failed : 1;
- unsigned SwitchedThread : 1;
-
-public:
- CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC),
- Failed(false),
- SwitchedThread(false) {
- Next = CurrentContext->get();
- CurrentContext->set(this);
- }
- ~CrashRecoveryContextImpl() {
- if (!SwitchedThread)
- CurrentContext->set(Next);
- }
-
- /// Called when the separate crash-recovery thread was finished, to
- /// indicate that we don't need to clear the thread-local CurrentContext.
- void setSwitchedThread() {
-#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
- SwitchedThread = true;
-#endif
- }
-
- void HandleCrash() {
- // Eliminate the current context entry, to avoid re-entering in case the
- // cleanup code crashes.
- CurrentContext->set(Next);
-
- assert(!Failed && "Crash recovery context already failed!");
- Failed = true;
-
- // FIXME: Stash the backtrace.
-
- // Jump back to the RunSafely we were called under.
- longjmp(JumpBuffer, 1);
- }
-};
-
-}
-
-static ManagedStatic<sys::Mutex> gCrashRecoveryContextMutex;
-static bool gCrashRecoveryEnabled = false;
-
-static ManagedStatic<sys::ThreadLocal<const CrashRecoveryContext>>
- tlIsRecoveringFromCrash;
-
-static void installExceptionOrSignalHandlers();
-static void uninstallExceptionOrSignalHandlers();
-
-CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {}
-
-CrashRecoveryContext::~CrashRecoveryContext() {
- // Reclaim registered resources.
- CrashRecoveryContextCleanup *i = head;
- const CrashRecoveryContext *PC = tlIsRecoveringFromCrash->get();
- tlIsRecoveringFromCrash->set(this);
- while (i) {
- CrashRecoveryContextCleanup *tmp = i;
- i = tmp->next;
- tmp->cleanupFired = true;
- tmp->recoverResources();
- delete tmp;
- }
- tlIsRecoveringFromCrash->set(PC);
-
- CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
- delete CRCI;
-}
-
-bool CrashRecoveryContext::isRecoveringFromCrash() {
- return tlIsRecoveringFromCrash->get() != nullptr;
-}
-
-CrashRecoveryContext *CrashRecoveryContext::GetCurrent() {
- if (!gCrashRecoveryEnabled)
- return nullptr;
-
- const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
- if (!CRCI)
- return nullptr;
-
- return CRCI->CRC;
-}
-
-void CrashRecoveryContext::Enable() {
- sys::ScopedLock L(*gCrashRecoveryContextMutex);
- // FIXME: Shouldn't this be a refcount or something?
- if (gCrashRecoveryEnabled)
- return;
- gCrashRecoveryEnabled = true;
- installExceptionOrSignalHandlers();
-}
-
-void CrashRecoveryContext::Disable() {
- sys::ScopedLock L(*gCrashRecoveryContextMutex);
- if (!gCrashRecoveryEnabled)
- return;
- gCrashRecoveryEnabled = false;
- uninstallExceptionOrSignalHandlers();
-}
-
-void CrashRecoveryContext::registerCleanup(CrashRecoveryContextCleanup *cleanup)
-{
- if (!cleanup)
- return;
- if (head)
- head->prev = cleanup;
- cleanup->next = head;
- head = cleanup;
-}
-
-void
-CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
- if (!cleanup)
- return;
- if (cleanup == head) {
- head = cleanup->next;
- if (head)
- head->prev = nullptr;
- }
- else {
- cleanup->prev->next = cleanup->next;
- if (cleanup->next)
- cleanup->next->prev = cleanup->prev;
- }
- delete cleanup;
-}
-
-#if defined(_MSC_VER)
-// If _MSC_VER is defined, we must have SEH. Use it if it's available. It's way
-// better than VEH. Vectored exception handling catches all exceptions happening
-// on the thread with installed exception handlers, so it can interfere with
-// internal exception handling of other libraries on that thread. SEH works
-// exactly as you would expect normal exception handling to work: it only
-// catches exceptions if they would bubble out from the stack frame with __try /
-// __except.
-
-static void installExceptionOrSignalHandlers() {}
-static void uninstallExceptionOrSignalHandlers() {}
-
-bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
- if (!gCrashRecoveryEnabled) {
- Fn();
- return true;
- }
-
- bool Result = true;
- __try {
- Fn();
- } __except (1) { // Catch any exception.
- Result = false;
- }
- return Result;
-}
-
-#else // !_MSC_VER
-
-#if defined(_WIN32)
-// This is a non-MSVC compiler, probably mingw gcc or clang without
-// -fms-extensions. Use vectored exception handling (VEH).
-//
-// On Windows, we can make use of vectored exception handling to catch most
-// crashing situations. Note that this does mean we will be alerted of
-// exceptions *before* structured exception handling has the opportunity to
-// catch it. Unfortunately, this causes problems in practice with other code
-// running on threads with LLVM crash recovery contexts, so we would like to
-// eventually move away from VEH.
-//
-// Vectored works on a per-thread basis, which is an advantage over
-// SetUnhandledExceptionFilter. SetUnhandledExceptionFilter also doesn't have
-// any native support for chaining exception handlers, but VEH allows more than
-// one.
-//
-// The vectored exception handler functionality was added in Windows
-// XP, so if support for older versions of Windows is required,
-// it will have to be added.
-
-#include "Windows/WindowsSupport.h"
-
-static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
-{
- // DBG_PRINTEXCEPTION_WIDE_C is not properly defined on all supported
- // compilers and platforms, so we define it manually.
- constexpr ULONG DbgPrintExceptionWideC = 0x4001000AL;
- switch (ExceptionInfo->ExceptionRecord->ExceptionCode)
- {
- case DBG_PRINTEXCEPTION_C:
- case DbgPrintExceptionWideC:
- case 0x406D1388: // set debugger thread name
- return EXCEPTION_CONTINUE_EXECUTION;
- }
-
- // Lookup the current thread local recovery object.
- const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
-
- if (!CRCI) {
- // Something has gone horribly wrong, so let's just tell everyone
- // to keep searching
- CrashRecoveryContext::Disable();
- return EXCEPTION_CONTINUE_SEARCH;
- }
-
- // TODO: We can capture the stack backtrace here and store it on the
- // implementation if we so choose.
-
- // Handle the crash
- const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash();
-
- // Note that we don't actually get here because HandleCrash calls
- // longjmp, which means the HandleCrash function never returns.
- llvm_unreachable("Handled the crash, should have longjmp'ed out of here");
-}
-
-// Because the Enable and Disable calls are static, it means that
-// there may not actually be an Impl available, or even a current
-// CrashRecoveryContext at all. So we make use of a thread-local
-// exception table. The handles contained in here will either be
-// non-NULL, valid VEH handles, or NULL.
-static sys::ThreadLocal<const void> sCurrentExceptionHandle;
-
-static void installExceptionOrSignalHandlers() {
- // We can set up vectored exception handling now. We will install our
- // handler as the front of the list, though there's no assurances that
- // it will remain at the front (another call could install itself before
- // our handler). This 1) isn't likely, and 2) shouldn't cause problems.
- PVOID handle = ::AddVectoredExceptionHandler(1, ExceptionHandler);
- sCurrentExceptionHandle.set(handle);
-}
-
-static void uninstallExceptionOrSignalHandlers() {
- PVOID currentHandle = const_cast<PVOID>(sCurrentExceptionHandle.get());
- if (currentHandle) {
- // Now we can remove the vectored exception handler from the chain
- ::RemoveVectoredExceptionHandler(currentHandle);
-
- // Reset the handle in our thread-local set.
- sCurrentExceptionHandle.set(NULL);
- }
-}
-
-#else // !_WIN32
-
-// Generic POSIX implementation.
-//
-// This implementation relies on synchronous signals being delivered to the
-// current thread. We use a thread local object to keep track of the active
-// crash recovery context, and install signal handlers to invoke HandleCrash on
-// the active object.
-//
-// This implementation does not to attempt to chain signal handlers in any
-// reliable fashion -- if we get a signal outside of a crash recovery context we
-// simply disable crash recovery and raise the signal again.
-
-#include <signal.h>
-
-static const int Signals[] =
- { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP };
-static const unsigned NumSignals = array_lengthof(Signals);
-static struct sigaction PrevActions[NumSignals];
-
-static void CrashRecoverySignalHandler(int Signal) {
- // Lookup the current thread local recovery object.
- const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
-
- if (!CRCI) {
- // We didn't find a crash recovery context -- this means either we got a
- // signal on a thread we didn't expect it on, the application got a signal
- // outside of a crash recovery context, or something else went horribly
- // wrong.
- //
- // Disable crash recovery and raise the signal again. The assumption here is
- // that the enclosing application will terminate soon, and we won't want to
- // attempt crash recovery again.
- //
- // This call of Disable isn't thread safe, but it doesn't actually matter.
- CrashRecoveryContext::Disable();
- raise(Signal);
-
- // The signal will be thrown once the signal mask is restored.
- return;
- }
-
- // Unblock the signal we received.
- sigset_t SigMask;
- sigemptyset(&SigMask);
- sigaddset(&SigMask, Signal);
- sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
-
- if (CRCI)
- const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash();
-}
-
-static void installExceptionOrSignalHandlers() {
- // Setup the signal handler.
- struct sigaction Handler;
- Handler.sa_handler = CrashRecoverySignalHandler;
- Handler.sa_flags = 0;
- sigemptyset(&Handler.sa_mask);
-
- for (unsigned i = 0; i != NumSignals; ++i) {
- sigaction(Signals[i], &Handler, &PrevActions[i]);
- }
-}
-
-static void uninstallExceptionOrSignalHandlers() {
- // Restore the previous signal handlers.
- for (unsigned i = 0; i != NumSignals; ++i)
- sigaction(Signals[i], &PrevActions[i], nullptr);
-}
-
-#endif // !_WIN32
-
-bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
- // If crash recovery is disabled, do nothing.
- if (gCrashRecoveryEnabled) {
- assert(!Impl && "Crash recovery context already initialized!");
- CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this);
- Impl = CRCI;
-
- if (setjmp(CRCI->JumpBuffer) != 0) {
- return false;
- }
- }
-
- Fn();
- return true;
-}
-
-#endif // !_MSC_VER
-
-void CrashRecoveryContext::HandleCrash() {
- CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
- assert(CRCI && "Crash recovery context never initialized!");
- CRCI->HandleCrash();
-}
-
-// FIXME: Portability.
-static void setThreadBackgroundPriority() {
-#ifdef __APPLE__
- setpriority(PRIO_DARWIN_THREAD, 0, PRIO_DARWIN_BG);
-#endif
-}
-
-static bool hasThreadBackgroundPriority() {
-#ifdef __APPLE__
- return getpriority(PRIO_DARWIN_THREAD, 0) == 1;
-#else
- return false;
-#endif
-}
-
-namespace {
-struct RunSafelyOnThreadInfo {
- function_ref<void()> Fn;
- CrashRecoveryContext *CRC;
- bool UseBackgroundPriority;
- bool Result;
-};
-}
-
-static void RunSafelyOnThread_Dispatch(void *UserData) {
- RunSafelyOnThreadInfo *Info =
- reinterpret_cast<RunSafelyOnThreadInfo*>(UserData);
-
- if (Info->UseBackgroundPriority)
- setThreadBackgroundPriority();
-
- Info->Result = Info->CRC->RunSafely(Info->Fn);
-}
-bool CrashRecoveryContext::RunSafelyOnThread(function_ref<void()> Fn,
- unsigned RequestedStackSize) {
- bool UseBackgroundPriority = hasThreadBackgroundPriority();
- RunSafelyOnThreadInfo Info = { Fn, this, UseBackgroundPriority, false };
- llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info, RequestedStackSize);
- if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl)
- CRC->setSwitchedThread();
- return Info.Result;
-}
diff --git a/gnu/llvm/lib/Support/DAGDeltaAlgorithm.cpp b/gnu/llvm/lib/Support/DAGDeltaAlgorithm.cpp
deleted file mode 100644
index bd9f98b0b82..00000000000
--- a/gnu/llvm/lib/Support/DAGDeltaAlgorithm.cpp
+++ /dev/null
@@ -1,362 +0,0 @@
-//===--- DAGDeltaAlgorithm.cpp - A DAG Minimization Algorithm --*- C++ -*--===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//===----------------------------------------------------------------------===//
-//
-// The algorithm we use attempts to exploit the dependency information by
-// minimizing top-down. We start by constructing an initial root set R, and
-// then iteratively:
-//
-// 1. Minimize the set R using the test predicate:
-// P'(S) = P(S union pred*(S))
-//
-// 2. Extend R to R' = R union pred(R).
-//
-// until a fixed point is reached.
-//
-// The idea is that we want to quickly prune entire portions of the graph, so we
-// try to find high-level nodes that can be eliminated with all of their
-// dependents.
-//
-// FIXME: The current algorithm doesn't actually provide a strong guarantee
-// about the minimality of the result. The problem is that after adding nodes to
-// the required set, we no longer consider them for elimination. For strictly
-// well formed predicates, this doesn't happen, but it commonly occurs in
-// practice when there are unmodelled dependencies. I believe we can resolve
-// this by allowing the required set to be minimized as well, but need more test
-// cases first.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/DAGDeltaAlgorithm.h"
-#include "llvm/ADT/DeltaAlgorithm.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <iterator>
-#include <map>
-using namespace llvm;
-
-#define DEBUG_TYPE "dag-delta"
-
-namespace {
-
-class DAGDeltaAlgorithmImpl {
- friend class DeltaActiveSetHelper;
-
-public:
- typedef DAGDeltaAlgorithm::change_ty change_ty;
- typedef DAGDeltaAlgorithm::changeset_ty changeset_ty;
- typedef DAGDeltaAlgorithm::changesetlist_ty changesetlist_ty;
- typedef DAGDeltaAlgorithm::edge_ty edge_ty;
-
-private:
- typedef std::vector<change_ty>::iterator pred_iterator_ty;
- typedef std::vector<change_ty>::iterator succ_iterator_ty;
- typedef std::set<change_ty>::iterator pred_closure_iterator_ty;
- typedef std::set<change_ty>::iterator succ_closure_iterator_ty;
-
- DAGDeltaAlgorithm &DDA;
-
- std::vector<change_ty> Roots;
-
- /// Cache of failed test results. Successful test results are never cached
- /// since we always reduce following a success. We maintain an independent
- /// cache from that used by the individual delta passes because we may get
- /// hits across multiple individual delta invocations.
- mutable std::set<changeset_ty> FailedTestsCache;
-
- // FIXME: Gross.
- std::map<change_ty, std::vector<change_ty> > Predecessors;
- std::map<change_ty, std::vector<change_ty> > Successors;
-
- std::map<change_ty, std::set<change_ty> > PredClosure;
- std::map<change_ty, std::set<change_ty> > SuccClosure;
-
-private:
- pred_iterator_ty pred_begin(change_ty Node) {
- assert(Predecessors.count(Node) && "Invalid node!");
- return Predecessors[Node].begin();
- }
- pred_iterator_ty pred_end(change_ty Node) {
- assert(Predecessors.count(Node) && "Invalid node!");
- return Predecessors[Node].end();
- }
-
- pred_closure_iterator_ty pred_closure_begin(change_ty Node) {
- assert(PredClosure.count(Node) && "Invalid node!");
- return PredClosure[Node].begin();
- }
- pred_closure_iterator_ty pred_closure_end(change_ty Node) {
- assert(PredClosure.count(Node) && "Invalid node!");
- return PredClosure[Node].end();
- }
-
- succ_iterator_ty succ_begin(change_ty Node) {
- assert(Successors.count(Node) && "Invalid node!");
- return Successors[Node].begin();
- }
- succ_iterator_ty succ_end(change_ty Node) {
- assert(Successors.count(Node) && "Invalid node!");
- return Successors[Node].end();
- }
-
- succ_closure_iterator_ty succ_closure_begin(change_ty Node) {
- assert(SuccClosure.count(Node) && "Invalid node!");
- return SuccClosure[Node].begin();
- }
- succ_closure_iterator_ty succ_closure_end(change_ty Node) {
- assert(SuccClosure.count(Node) && "Invalid node!");
- return SuccClosure[Node].end();
- }
-
- void UpdatedSearchState(const changeset_ty &Changes,
- const changesetlist_ty &Sets,
- const changeset_ty &Required) {
- DDA.UpdatedSearchState(Changes, Sets, Required);
- }
-
- /// ExecuteOneTest - Execute a single test predicate on the change set \p S.
- bool ExecuteOneTest(const changeset_ty &S) {
- // Check dependencies invariant.
- LLVM_DEBUG({
- for (changeset_ty::const_iterator it = S.begin(), ie = S.end(); it != ie;
- ++it)
- for (succ_iterator_ty it2 = succ_begin(*it), ie2 = succ_end(*it);
- it2 != ie2; ++it2)
- assert(S.count(*it2) && "Attempt to run invalid changeset!");
- });
-
- return DDA.ExecuteOneTest(S);
- }
-
-public:
- DAGDeltaAlgorithmImpl(DAGDeltaAlgorithm &DDA, const changeset_ty &Changes,
- const std::vector<edge_ty> &Dependencies);
-
- changeset_ty Run();
-
- /// GetTestResult - Get the test result for the active set \p Changes with
- /// \p Required changes from the cache, executing the test if necessary.
- ///
- /// \param Changes - The set of active changes being minimized, which should
- /// have their pred closure included in the test.
- /// \param Required - The set of changes which have previously been
- /// established to be required.
- /// \return - The test result.
- bool GetTestResult(const changeset_ty &Changes, const changeset_ty &Required);
-};
-
-/// Helper object for minimizing an active set of changes.
-class DeltaActiveSetHelper : public DeltaAlgorithm {
- DAGDeltaAlgorithmImpl &DDAI;
-
- const changeset_ty &Required;
-
-protected:
- /// UpdatedSearchState - Callback used when the search state changes.
- void UpdatedSearchState(const changeset_ty &Changes,
- const changesetlist_ty &Sets) override {
- DDAI.UpdatedSearchState(Changes, Sets, Required);
- }
-
- bool ExecuteOneTest(const changeset_ty &S) override {
- return DDAI.GetTestResult(S, Required);
- }
-
-public:
- DeltaActiveSetHelper(DAGDeltaAlgorithmImpl &DDAI,
- const changeset_ty &Required)
- : DDAI(DDAI), Required(Required) {}
-};
-
-}
-
-DAGDeltaAlgorithmImpl::DAGDeltaAlgorithmImpl(
- DAGDeltaAlgorithm &DDA, const changeset_ty &Changes,
- const std::vector<edge_ty> &Dependencies)
- : DDA(DDA) {
- for (changeset_ty::const_iterator it = Changes.begin(),
- ie = Changes.end(); it != ie; ++it) {
- Predecessors.insert(std::make_pair(*it, std::vector<change_ty>()));
- Successors.insert(std::make_pair(*it, std::vector<change_ty>()));
- }
- for (std::vector<edge_ty>::const_iterator it = Dependencies.begin(),
- ie = Dependencies.end(); it != ie; ++it) {
- Predecessors[it->second].push_back(it->first);
- Successors[it->first].push_back(it->second);
- }
-
- // Compute the roots.
- for (changeset_ty::const_iterator it = Changes.begin(),
- ie = Changes.end(); it != ie; ++it)
- if (succ_begin(*it) == succ_end(*it))
- Roots.push_back(*it);
-
- // Pre-compute the closure of the successor relation.
- std::vector<change_ty> Worklist(Roots.begin(), Roots.end());
- while (!Worklist.empty()) {
- change_ty Change = Worklist.back();
- Worklist.pop_back();
-
- std::set<change_ty> &ChangeSuccs = SuccClosure[Change];
- for (pred_iterator_ty it = pred_begin(Change),
- ie = pred_end(Change); it != ie; ++it) {
- SuccClosure[*it].insert(Change);
- SuccClosure[*it].insert(ChangeSuccs.begin(), ChangeSuccs.end());
- Worklist.push_back(*it);
- }
- }
-
- // Invert to form the predecessor closure map.
- for (changeset_ty::const_iterator it = Changes.begin(),
- ie = Changes.end(); it != ie; ++it)
- PredClosure.insert(std::make_pair(*it, std::set<change_ty>()));
- for (changeset_ty::const_iterator it = Changes.begin(),
- ie = Changes.end(); it != ie; ++it)
- for (succ_closure_iterator_ty it2 = succ_closure_begin(*it),
- ie2 = succ_closure_end(*it); it2 != ie2; ++it2)
- PredClosure[*it2].insert(*it);
-
- // Dump useful debug info.
- LLVM_DEBUG({
- llvm::errs() << "-- DAGDeltaAlgorithmImpl --\n";
- llvm::errs() << "Changes: [";
- for (changeset_ty::const_iterator it = Changes.begin(), ie = Changes.end();
- it != ie; ++it) {
- if (it != Changes.begin())
- llvm::errs() << ", ";
- llvm::errs() << *it;
-
- if (succ_begin(*it) != succ_end(*it)) {
- llvm::errs() << "(";
- for (succ_iterator_ty it2 = succ_begin(*it), ie2 = succ_end(*it);
- it2 != ie2; ++it2) {
- if (it2 != succ_begin(*it))
- llvm::errs() << ", ";
- llvm::errs() << "->" << *it2;
- }
- llvm::errs() << ")";
- }
- }
- llvm::errs() << "]\n";
-
- llvm::errs() << "Roots: [";
- for (std::vector<change_ty>::const_iterator it = Roots.begin(),
- ie = Roots.end();
- it != ie; ++it) {
- if (it != Roots.begin())
- llvm::errs() << ", ";
- llvm::errs() << *it;
- }
- llvm::errs() << "]\n";
-
- llvm::errs() << "Predecessor Closure:\n";
- for (changeset_ty::const_iterator it = Changes.begin(), ie = Changes.end();
- it != ie; ++it) {
- llvm::errs() << format(" %-4d: [", *it);
- for (pred_closure_iterator_ty it2 = pred_closure_begin(*it),
- ie2 = pred_closure_end(*it);
- it2 != ie2; ++it2) {
- if (it2 != pred_closure_begin(*it))
- llvm::errs() << ", ";
- llvm::errs() << *it2;
- }
- llvm::errs() << "]\n";
- }
-
- llvm::errs() << "Successor Closure:\n";
- for (changeset_ty::const_iterator it = Changes.begin(), ie = Changes.end();
- it != ie; ++it) {
- llvm::errs() << format(" %-4d: [", *it);
- for (succ_closure_iterator_ty it2 = succ_closure_begin(*it),
- ie2 = succ_closure_end(*it);
- it2 != ie2; ++it2) {
- if (it2 != succ_closure_begin(*it))
- llvm::errs() << ", ";
- llvm::errs() << *it2;
- }
- llvm::errs() << "]\n";
- }
-
- llvm::errs() << "\n\n";
- });
-}
-
-bool DAGDeltaAlgorithmImpl::GetTestResult(const changeset_ty &Changes,
- const changeset_ty &Required) {
- changeset_ty Extended(Required);
- Extended.insert(Changes.begin(), Changes.end());
- for (changeset_ty::const_iterator it = Changes.begin(),
- ie = Changes.end(); it != ie; ++it)
- Extended.insert(pred_closure_begin(*it), pred_closure_end(*it));
-
- if (FailedTestsCache.count(Extended))
- return false;
-
- bool Result = ExecuteOneTest(Extended);
- if (!Result)
- FailedTestsCache.insert(Extended);
-
- return Result;
-}
-
-DAGDeltaAlgorithm::changeset_ty
-DAGDeltaAlgorithmImpl::Run() {
- // The current set of changes we are minimizing, starting at the roots.
- changeset_ty CurrentSet(Roots.begin(), Roots.end());
-
- // The set of required changes.
- changeset_ty Required;
-
- // Iterate until the active set of changes is empty. Convergence is guaranteed
- // assuming input was a DAG.
- //
- // Invariant: CurrentSet intersect Required == {}
- // Invariant: Required == (Required union succ*(Required))
- while (!CurrentSet.empty()) {
- LLVM_DEBUG({
- llvm::errs() << "DAG_DD - " << CurrentSet.size() << " active changes, "
- << Required.size() << " required changes\n";
- });
-
- // Minimize the current set of changes.
- DeltaActiveSetHelper Helper(*this, Required);
- changeset_ty CurrentMinSet = Helper.Run(CurrentSet);
-
- // Update the set of required changes. Since
- // CurrentMinSet subset CurrentSet
- // and after the last iteration,
- // succ(CurrentSet) subset Required
- // then
- // succ(CurrentMinSet) subset Required
- // and our invariant on Required is maintained.
- Required.insert(CurrentMinSet.begin(), CurrentMinSet.end());
-
- // Replace the current set with the predecssors of the minimized set of
- // active changes.
- CurrentSet.clear();
- for (changeset_ty::const_iterator it = CurrentMinSet.begin(),
- ie = CurrentMinSet.end(); it != ie; ++it)
- CurrentSet.insert(pred_begin(*it), pred_end(*it));
-
- // FIXME: We could enforce CurrentSet intersect Required == {} here if we
- // wanted to protect against cyclic graphs.
- }
-
- return Required;
-}
-
-void DAGDeltaAlgorithm::anchor() {
-}
-
-DAGDeltaAlgorithm::changeset_ty
-DAGDeltaAlgorithm::Run(const changeset_ty &Changes,
- const std::vector<edge_ty> &Dependencies) {
- return DAGDeltaAlgorithmImpl(*this, Changes, Dependencies).Run();
-}
diff --git a/gnu/llvm/lib/Support/DJB.cpp b/gnu/llvm/lib/Support/DJB.cpp
deleted file mode 100644
index 905dcf1b7e8..00000000000
--- a/gnu/llvm/lib/Support/DJB.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//===-- Support/DJB.cpp ---DJB Hash -----------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains support for the DJ Bernstein hash function.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/DJB.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/Unicode.h"
-
-using namespace llvm;
-
-static UTF32 chopOneUTF32(StringRef &Buffer) {
- UTF32 C;
- const UTF8 *const Begin8Const =
- reinterpret_cast<const UTF8 *>(Buffer.begin());
- const UTF8 *Begin8 = Begin8Const;
- UTF32 *Begin32 = &C;
-
- // In lenient mode we will always end up with a "reasonable" value in C for
- // non-empty input.
- assert(!Buffer.empty());
- ConvertUTF8toUTF32(&Begin8, reinterpret_cast<const UTF8 *>(Buffer.end()),
- &Begin32, &C + 1, lenientConversion);
- Buffer = Buffer.drop_front(Begin8 - Begin8Const);
- return C;
-}
-
-static StringRef toUTF8(UTF32 C, MutableArrayRef<UTF8> Storage) {
- const UTF32 *Begin32 = &C;
- UTF8 *Begin8 = Storage.begin();
-
- // The case-folded output should always be a valid unicode character, so use
- // strict mode here.
- ConversionResult CR = ConvertUTF32toUTF8(&Begin32, &C + 1, &Begin8,
- Storage.end(), strictConversion);
- assert(CR == conversionOK && "Case folding produced invalid char?");
- (void)CR;
- return StringRef(reinterpret_cast<char *>(Storage.begin()),
- Begin8 - Storage.begin());
-}
-
-static UTF32 foldCharDwarf(UTF32 C) {
- // DWARF v5 addition to the unicode folding rules.
- // Fold "Latin Small Letter Dotless I" and "Latin Capital Letter I With Dot
- // Above" into "i".
- if (C == 0x130 || C == 0x131)
- return 'i';
- return sys::unicode::foldCharSimple(C);
-}
-
-static uint32_t caseFoldingDjbHashCharSlow(StringRef &Buffer, uint32_t H) {
- UTF32 C = chopOneUTF32(Buffer);
-
- C = foldCharDwarf(C);
-
- std::array<UTF8, UNI_MAX_UTF8_BYTES_PER_CODE_POINT> Storage;
- StringRef Folded = toUTF8(C, Storage);
- return djbHash(Folded, H);
-}
-
-uint32_t llvm::caseFoldingDjbHash(StringRef Buffer, uint32_t H) {
- while (!Buffer.empty()) {
- unsigned char C = Buffer.front();
- if (LLVM_LIKELY(C <= 0x7f)) {
- // US-ASCII, encoded as one character in utf-8.
- // This is by far the most common case, so handle this specially.
- if (C >= 'A' && C <= 'Z')
- C = 'a' + (C - 'A'); // fold uppercase into lowercase
- H = (H << 5) + H + C;
- Buffer = Buffer.drop_front();
- continue;
- }
- H = caseFoldingDjbHashCharSlow(Buffer, H);
- }
- return H;
-}
diff --git a/gnu/llvm/lib/Support/DataExtractor.cpp b/gnu/llvm/lib/Support/DataExtractor.cpp
deleted file mode 100644
index 0199b300ba7..00000000000
--- a/gnu/llvm/lib/Support/DataExtractor.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-//===-- DataExtractor.cpp -------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/DataExtractor.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/SwapByteOrder.h"
-using namespace llvm;
-
-template <typename T>
-static T getU(uint32_t *offset_ptr, const DataExtractor *de,
- bool isLittleEndian, const char *Data) {
- T val = 0;
- uint32_t offset = *offset_ptr;
- if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) {
- std::memcpy(&val, &Data[offset], sizeof(val));
- if (sys::IsLittleEndianHost != isLittleEndian)
- sys::swapByteOrder(val);
-
- // Advance the offset
- *offset_ptr += sizeof(val);
- }
- return val;
-}
-
-template <typename T>
-static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count,
- const DataExtractor *de, bool isLittleEndian, const char *Data){
- uint32_t offset = *offset_ptr;
-
- if (count > 0 && de->isValidOffsetForDataOfSize(offset, sizeof(*dst)*count)) {
- for (T *value_ptr = dst, *end = dst + count; value_ptr != end;
- ++value_ptr, offset += sizeof(*dst))
- *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data);
- // Advance the offset
- *offset_ptr = offset;
- // Return a non-NULL pointer to the converted data as an indicator of
- // success
- return dst;
- }
- return nullptr;
-}
-
-uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const {
- return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data());
-}
-
-uint8_t *
-DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const {
- return getUs<uint8_t>(offset_ptr, dst, count, this, IsLittleEndian,
- Data.data());
-}
-
-
-uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
- return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data());
-}
-
-uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst,
- uint32_t count) const {
- return getUs<uint16_t>(offset_ptr, dst, count, this, IsLittleEndian,
- Data.data());
-}
-
-uint32_t DataExtractor::getU24(uint32_t *offset_ptr) const {
- uint24_t ExtractedVal =
- getU<uint24_t>(offset_ptr, this, IsLittleEndian, Data.data());
- // The 3 bytes are in the correct byte order for the host.
- return ExtractedVal.getAsUint32(sys::IsLittleEndianHost);
-}
-
-uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
- return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data());
-}
-
-uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst,
- uint32_t count) const {
- return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
- Data.data());
-}
-
-uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
- return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data());
-}
-
-uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
- uint32_t count) const {
- return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian,
- Data.data());
-}
-
-uint64_t
-DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
- switch (byte_size) {
- case 1:
- return getU8(offset_ptr);
- case 2:
- return getU16(offset_ptr);
- case 4:
- return getU32(offset_ptr);
- case 8:
- return getU64(offset_ptr);
- }
- llvm_unreachable("getUnsigned unhandled case!");
-}
-
-int64_t
-DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
- switch (byte_size) {
- case 1:
- return (int8_t)getU8(offset_ptr);
- case 2:
- return (int16_t)getU16(offset_ptr);
- case 4:
- return (int32_t)getU32(offset_ptr);
- case 8:
- return (int64_t)getU64(offset_ptr);
- }
- llvm_unreachable("getSigned unhandled case!");
-}
-
-const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
- uint32_t offset = *offset_ptr;
- StringRef::size_type pos = Data.find('\0', offset);
- if (pos != StringRef::npos) {
- *offset_ptr = pos + 1;
- return Data.data() + offset;
- }
- return nullptr;
-}
-
-StringRef DataExtractor::getCStrRef(uint32_t *OffsetPtr) const {
- uint32_t Start = *OffsetPtr;
- StringRef::size_type Pos = Data.find('\0', Start);
- if (Pos != StringRef::npos) {
- *OffsetPtr = Pos + 1;
- return StringRef(Data.data() + Start, Pos - Start);
- }
- return StringRef();
-}
-
-uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
- uint64_t result = 0;
- if (Data.empty())
- return 0;
-
- unsigned shift = 0;
- uint32_t offset = *offset_ptr;
- uint8_t byte = 0;
-
- while (isValidOffset(offset)) {
- byte = Data[offset++];
- result |= uint64_t(byte & 0x7f) << shift;
- shift += 7;
- if ((byte & 0x80) == 0)
- break;
- }
-
- *offset_ptr = offset;
- return result;
-}
-
-int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
- int64_t result = 0;
- if (Data.empty())
- return 0;
-
- unsigned shift = 0;
- uint32_t offset = *offset_ptr;
- uint8_t byte = 0;
-
- while (isValidOffset(offset)) {
- byte = Data[offset++];
- result |= uint64_t(byte & 0x7f) << shift;
- shift += 7;
- if ((byte & 0x80) == 0)
- break;
- }
-
- // Sign bit of byte is 2nd high order bit (0x40)
- if (shift < 64 && (byte & 0x40))
- result |= -(1ULL << shift);
-
- *offset_ptr = offset;
- return result;
-}
diff --git a/gnu/llvm/lib/Support/Debug.cpp b/gnu/llvm/lib/Support/Debug.cpp
deleted file mode 100644
index 1a70017fee3..00000000000
--- a/gnu/llvm/lib/Support/Debug.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-//===-- Debug.cpp - An easy way to add debug output to your code ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a handy way of adding debugging information to your
-// code, without it being enabled all of the time, and without having to add
-// command line options to enable it.
-//
-// In particular, just wrap your code with the LLVM_DEBUG() macro, and it will
-// be enabled automatically if you specify '-debug' on the command-line.
-// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify
-// that your debug code belongs to class "foo". Then, on the command line, you
-// can specify '-debug-only=foo' to enable JUST the debug information for the
-// foo class.
-//
-// When compiling without assertions, the -debug-* options and all code in
-// LLVM_DEBUG() statements disappears, so it does not affect the runtime of the
-// code.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/circular_raw_ostream.h"
-#include "llvm/Support/raw_ostream.h"
-
-#undef isCurrentDebugType
-#undef setCurrentDebugType
-#undef setCurrentDebugTypes
-
-using namespace llvm;
-
-// Even though LLVM might be built with NDEBUG, define symbols that the code
-// built without NDEBUG can depend on via the llvm/Support/Debug.h header.
-namespace llvm {
-/// Exported boolean set by the -debug option.
-bool DebugFlag = false;
-
-static ManagedStatic<std::vector<std::string>> CurrentDebugType;
-
-/// Return true if the specified string is the debug type
-/// specified on the command line, or if none was specified on the command line
-/// with the -debug-only=X option.
-bool isCurrentDebugType(const char *DebugType) {
- if (CurrentDebugType->empty())
- return true;
- // See if DebugType is in list. Note: do not use find() as that forces us to
- // unnecessarily create an std::string instance.
- for (auto &d : *CurrentDebugType) {
- if (d == DebugType)
- return true;
- }
- return false;
-}
-
-/// Set the current debug type, as if the -debug-only=X
-/// option were specified. Note that DebugFlag also needs to be set to true for
-/// debug output to be produced.
-///
-void setCurrentDebugTypes(const char **Types, unsigned Count);
-
-void setCurrentDebugType(const char *Type) {
- setCurrentDebugTypes(&Type, 1);
-}
-
-void setCurrentDebugTypes(const char **Types, unsigned Count) {
- CurrentDebugType->clear();
- for (size_t T = 0; T < Count; ++T)
- CurrentDebugType->push_back(Types[T]);
-}
-} // namespace llvm
-
-// All Debug.h functionality is a no-op in NDEBUG mode.
-#ifndef NDEBUG
-
-// -debug - Command line option to enable the DEBUG statements in the passes.
-// This flag may only be enabled in debug builds.
-static cl::opt<bool, true>
-Debug("debug", cl::desc("Enable debug output"), cl::Hidden,
- cl::location(DebugFlag));
-
-// -debug-buffer-size - Buffer the last N characters of debug output
-//until program termination.
-static cl::opt<unsigned>
-DebugBufferSize("debug-buffer-size",
- cl::desc("Buffer the last N characters of debug output "
- "until program termination. "
- "[default 0 -- immediate print-out]"),
- cl::Hidden,
- cl::init(0));
-
-namespace {
-
-struct DebugOnlyOpt {
- void operator=(const std::string &Val) const {
- if (Val.empty())
- return;
- DebugFlag = true;
- SmallVector<StringRef,8> dbgTypes;
- StringRef(Val).split(dbgTypes, ',', -1, false);
- for (auto dbgType : dbgTypes)
- CurrentDebugType->push_back(dbgType);
- }
-};
-
-}
-
-static DebugOnlyOpt DebugOnlyOptLoc;
-
-static cl::opt<DebugOnlyOpt, true, cl::parser<std::string> >
-DebugOnly("debug-only", cl::desc("Enable a specific type of debug output (comma separated list of types)"),
- cl::Hidden, cl::ZeroOrMore, cl::value_desc("debug string"),
- cl::location(DebugOnlyOptLoc), cl::ValueRequired);
-// Signal handlers - dump debug output on termination.
-static void debug_user_sig_handler(void *Cookie) {
- // This is a bit sneaky. Since this is under #ifndef NDEBUG, we
- // know that debug mode is enabled and dbgs() really is a
- // circular_raw_ostream. If NDEBUG is defined, then dbgs() ==
- // errs() but this will never be invoked.
- llvm::circular_raw_ostream &dbgout =
- static_cast<circular_raw_ostream &>(llvm::dbgs());
- dbgout.flushBufferWithBanner();
-}
-
-/// dbgs - Return a circular-buffered debug stream.
-raw_ostream &llvm::dbgs() {
- // Do one-time initialization in a thread-safe way.
- static struct dbgstream {
- circular_raw_ostream strm;
-
- dbgstream() :
- strm(errs(), "*** Debug Log Output ***\n",
- (!EnableDebugBuffering || !DebugFlag) ? 0 : DebugBufferSize) {
- if (EnableDebugBuffering && DebugFlag && DebugBufferSize != 0)
- // TODO: Add a handler for SIGUSER1-type signals so the user can
- // force a debug dump.
- sys::AddSignalHandler(&debug_user_sig_handler, nullptr);
- // Otherwise we've already set the debug stream buffer size to
- // zero, disabling buffering so it will output directly to errs().
- }
- } thestrm;
-
- return thestrm.strm;
-}
-
-#else
-// Avoid "has no symbols" warning.
-namespace llvm {
- /// dbgs - Return errs().
- raw_ostream &dbgs() {
- return errs();
- }
-}
-
-#endif
-
-/// EnableDebugBuffering - Turn on signal handler installation.
-///
-bool llvm::EnableDebugBuffering = false;
diff --git a/gnu/llvm/lib/Support/DebugCounter.cpp b/gnu/llvm/lib/Support/DebugCounter.cpp
deleted file mode 100644
index 6598103658d..00000000000
--- a/gnu/llvm/lib/Support/DebugCounter.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "llvm/Support/DebugCounter.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Options.h"
-
-using namespace llvm;
-
-namespace {
-// This class overrides the default list implementation of printing so we
-// can pretty print the list of debug counter options. This type of
-// dynamic option is pretty rare (basically this and pass lists).
-class DebugCounterList : public cl::list<std::string, DebugCounter> {
-private:
- using Base = cl::list<std::string, DebugCounter>;
-
-public:
- template <class... Mods>
- explicit DebugCounterList(Mods &&... Ms) : Base(std::forward<Mods>(Ms)...) {}
-
-private:
- void printOptionInfo(size_t GlobalWidth) const override {
- // This is a variant of from generic_parser_base::printOptionInfo. Sadly,
- // it's not easy to make it more usable. We could get it to print these as
- // options if we were a cl::opt and registered them, but lists don't have
- // options, nor does the parser for std::string. The other mechanisms for
- // options are global and would pollute the global namespace with our
- // counters. Rather than go that route, we have just overridden the
- // printing, which only a few things call anyway.
- outs() << " -" << ArgStr;
- // All of the other options in CommandLine.cpp use ArgStr.size() + 6 for
- // width, so we do the same.
- Option::printHelpStr(HelpStr, GlobalWidth, ArgStr.size() + 6);
- const auto &CounterInstance = DebugCounter::instance();
- for (auto Name : CounterInstance) {
- const auto Info =
- CounterInstance.getCounterInfo(CounterInstance.getCounterId(Name));
- size_t NumSpaces = GlobalWidth - Info.first.size() - 8;
- outs() << " =" << Info.first;
- outs().indent(NumSpaces) << " - " << Info.second << '\n';
- }
- }
-};
-} // namespace
-
-// Create our command line option.
-static DebugCounterList DebugCounterOption(
- "debug-counter", cl::Hidden,
- cl::desc("Comma separated list of debug counter skip and count"),
- cl::CommaSeparated, cl::ZeroOrMore, cl::location(DebugCounter::instance()));
-
-static cl::opt<bool> PrintDebugCounter(
- "print-debug-counter", cl::Hidden, cl::init(false), cl::Optional,
- cl::desc("Print out debug counter info after all counters accumulated"));
-
-static ManagedStatic<DebugCounter> DC;
-
-// Print information when destroyed, iff command line option is specified.
-DebugCounter::~DebugCounter() {
- if (isCountingEnabled() && PrintDebugCounter)
- print(dbgs());
-}
-
-DebugCounter &DebugCounter::instance() { return *DC; }
-
-// This is called by the command line parser when it sees a value for the
-// debug-counter option defined above.
-void DebugCounter::push_back(const std::string &Val) {
- if (Val.empty())
- return;
- // The strings should come in as counter=value
- auto CounterPair = StringRef(Val).split('=');
- if (CounterPair.second.empty()) {
- errs() << "DebugCounter Error: " << Val << " does not have an = in it\n";
- return;
- }
- // Now we have counter=value.
- // First, process value.
- int64_t CounterVal;
- if (CounterPair.second.getAsInteger(0, CounterVal)) {
- errs() << "DebugCounter Error: " << CounterPair.second
- << " is not a number\n";
- return;
- }
- // Now we need to see if this is the skip or the count, remove the suffix, and
- // add it to the counter values.
- if (CounterPair.first.endswith("-skip")) {
- auto CounterName = CounterPair.first.drop_back(5);
- unsigned CounterID = getCounterId(CounterName);
- if (!CounterID) {
- errs() << "DebugCounter Error: " << CounterName
- << " is not a registered counter\n";
- return;
- }
- enableAllCounters();
-
- CounterInfo &Counter = Counters[CounterID];
- Counter.Skip = CounterVal;
- Counter.IsSet = true;
- } else if (CounterPair.first.endswith("-count")) {
- auto CounterName = CounterPair.first.drop_back(6);
- unsigned CounterID = getCounterId(CounterName);
- if (!CounterID) {
- errs() << "DebugCounter Error: " << CounterName
- << " is not a registered counter\n";
- return;
- }
- enableAllCounters();
-
- CounterInfo &Counter = Counters[CounterID];
- Counter.StopAfter = CounterVal;
- Counter.IsSet = true;
- } else {
- errs() << "DebugCounter Error: " << CounterPair.first
- << " does not end with -skip or -count\n";
- }
-}
-
-void DebugCounter::print(raw_ostream &OS) const {
- SmallVector<StringRef, 16> CounterNames(RegisteredCounters.begin(),
- RegisteredCounters.end());
- sort(CounterNames.begin(), CounterNames.end());
-
- auto &Us = instance();
- OS << "Counters and values:\n";
- for (auto &CounterName : CounterNames) {
- unsigned CounterID = getCounterId(CounterName);
- OS << left_justify(RegisteredCounters[CounterID], 32) << ": {"
- << Us.Counters[CounterID].Count << "," << Us.Counters[CounterID].Skip
- << "," << Us.Counters[CounterID].StopAfter << "}\n";
- }
-}
-
-LLVM_DUMP_METHOD void DebugCounter::dump() const {
- print(dbgs());
-}
diff --git a/gnu/llvm/lib/Support/DeltaAlgorithm.cpp b/gnu/llvm/lib/Support/DeltaAlgorithm.cpp
deleted file mode 100644
index 50ea4e9ce0c..00000000000
--- a/gnu/llvm/lib/Support/DeltaAlgorithm.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-//===--- DeltaAlgorithm.cpp - A Set Minimization Algorithm -----*- C++ -*--===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/DeltaAlgorithm.h"
-#include <algorithm>
-#include <iterator>
-#include <set>
-using namespace llvm;
-
-DeltaAlgorithm::~DeltaAlgorithm() {
-}
-
-bool DeltaAlgorithm::GetTestResult(const changeset_ty &Changes) {
- if (FailedTestsCache.count(Changes))
- return false;
-
- bool Result = ExecuteOneTest(Changes);
- if (!Result)
- FailedTestsCache.insert(Changes);
-
- return Result;
-}
-
-void DeltaAlgorithm::Split(const changeset_ty &S, changesetlist_ty &Res) {
- // FIXME: Allow clients to provide heuristics for improved splitting.
-
- // FIXME: This is really slow.
- changeset_ty LHS, RHS;
- unsigned idx = 0, N = S.size() / 2;
- for (changeset_ty::const_iterator it = S.begin(),
- ie = S.end(); it != ie; ++it, ++idx)
- ((idx < N) ? LHS : RHS).insert(*it);
- if (!LHS.empty())
- Res.push_back(LHS);
- if (!RHS.empty())
- Res.push_back(RHS);
-}
-
-DeltaAlgorithm::changeset_ty
-DeltaAlgorithm::Delta(const changeset_ty &Changes,
- const changesetlist_ty &Sets) {
- // Invariant: union(Res) == Changes
- UpdatedSearchState(Changes, Sets);
-
- // If there is nothing left we can remove, we are done.
- if (Sets.size() <= 1)
- return Changes;
-
- // Look for a passing subset.
- changeset_ty Res;
- if (Search(Changes, Sets, Res))
- return Res;
-
- // Otherwise, partition the sets if possible; if not we are done.
- changesetlist_ty SplitSets;
- for (changesetlist_ty::const_iterator it = Sets.begin(),
- ie = Sets.end(); it != ie; ++it)
- Split(*it, SplitSets);
- if (SplitSets.size() == Sets.size())
- return Changes;
-
- return Delta(Changes, SplitSets);
-}
-
-bool DeltaAlgorithm::Search(const changeset_ty &Changes,
- const changesetlist_ty &Sets,
- changeset_ty &Res) {
- // FIXME: Parallelize.
- for (changesetlist_ty::const_iterator it = Sets.begin(),
- ie = Sets.end(); it != ie; ++it) {
- // If the test passes on this subset alone, recurse.
- if (GetTestResult(*it)) {
- changesetlist_ty Sets;
- Split(*it, Sets);
- Res = Delta(*it, Sets);
- return true;
- }
-
- // Otherwise, if we have more than two sets, see if test passes on the
- // complement.
- if (Sets.size() > 2) {
- // FIXME: This is really slow.
- changeset_ty Complement;
- std::set_difference(
- Changes.begin(), Changes.end(), it->begin(), it->end(),
- std::insert_iterator<changeset_ty>(Complement, Complement.begin()));
- if (GetTestResult(Complement)) {
- changesetlist_ty ComplementSets;
- ComplementSets.insert(ComplementSets.end(), Sets.begin(), it);
- ComplementSets.insert(ComplementSets.end(), it + 1, Sets.end());
- Res = Delta(Complement, ComplementSets);
- return true;
- }
- }
- }
-
- return false;
-}
-
-DeltaAlgorithm::changeset_ty DeltaAlgorithm::Run(const changeset_ty &Changes) {
- // Check empty set first to quickly find poor test functions.
- if (GetTestResult(changeset_ty()))
- return changeset_ty();
-
- // Otherwise run the real delta algorithm.
- changesetlist_ty Sets;
- Split(Changes, Sets);
-
- return Delta(Changes, Sets);
-}
diff --git a/gnu/llvm/lib/Support/DynamicLibrary.cpp b/gnu/llvm/lib/Support/DynamicLibrary.cpp
deleted file mode 100644
index 530e92d99a9..00000000000
--- a/gnu/llvm/lib/Support/DynamicLibrary.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the operating system DynamicLibrary concept.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/DynamicLibrary.h"
-#include "llvm-c/Support.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Mutex.h"
-#include <cstdio>
-#include <cstring>
-#include <vector>
-
-using namespace llvm;
-using namespace llvm::sys;
-
-// All methods for HandleSet should be used holding SymbolsMutex.
-class DynamicLibrary::HandleSet {
- typedef std::vector<void *> HandleList;
- HandleList Handles;
- void *Process;
-
-public:
- static void *DLOpen(const char *Filename, std::string *Err);
- static void DLClose(void *Handle);
- static void *DLSym(void *Handle, const char *Symbol);
-
- HandleSet() : Process(nullptr) {}
- ~HandleSet();
-
- HandleList::iterator Find(void *Handle) {
- return std::find(Handles.begin(), Handles.end(), Handle);
- }
-
- bool Contains(void *Handle) {
- return Handle == Process || Find(Handle) != Handles.end();
- }
-
- bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
-#ifdef _WIN32
- assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
-#endif
-
- if (LLVM_LIKELY(!IsProcess)) {
- if (Find(Handle) != Handles.end()) {
- if (CanClose)
- DLClose(Handle);
- return false;
- }
- Handles.push_back(Handle);
- } else {
-#ifndef _WIN32
- if (Process) {
- if (CanClose)
- DLClose(Process);
- if (Process == Handle)
- return false;
- }
-#endif
- Process = Handle;
- }
- return true;
- }
-
- void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
- if (Order & SO_LoadOrder) {
- for (void *Handle : Handles) {
- if (void *Ptr = DLSym(Handle, Symbol))
- return Ptr;
- }
- } else {
- for (void *Handle : llvm::reverse(Handles)) {
- if (void *Ptr = DLSym(Handle, Symbol))
- return Ptr;
- }
- }
- return nullptr;
- }
-
- void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
- assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&
- "Invalid Ordering");
-
- if (!Process || (Order & SO_LoadedFirst)) {
- if (void *Ptr = LibLookup(Symbol, Order))
- return Ptr;
- }
- if (Process) {
- // Use OS facilities to search the current binary and all loaded libs.
- if (void *Ptr = DLSym(Process, Symbol))
- return Ptr;
-
- // Search any libs that might have been skipped because of RTLD_LOCAL.
- if (Order & SO_LoadedLast) {
- if (void *Ptr = LibLookup(Symbol, Order))
- return Ptr;
- }
- }
- return nullptr;
- }
-};
-
-namespace {
-// Collection of symbol name/value pairs to be searched prior to any libraries.
-static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols;
-// Collection of known library handles.
-static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles;
-// Lock for ExplicitSymbols and OpenedHandles.
-static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex;
-}
-
-#ifdef _WIN32
-
-#include "Windows/DynamicLibrary.inc"
-
-#else
-
-#include "Unix/DynamicLibrary.inc"
-
-#endif
-
-char DynamicLibrary::Invalid;
-DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder =
- DynamicLibrary::SO_Linker;
-
-namespace llvm {
-void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
- return DoSearch(SymbolName); // DynamicLibrary.inc
-}
-}
-
-void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
- SmartScopedLock<true> Lock(*SymbolsMutex);
- (*ExplicitSymbols)[SymbolName] = SymbolValue;
-}
-
-DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
- std::string *Err) {
- // Force OpenedHandles to be added into the ManagedStatic list before any
- // ManagedStatic can be added from static constructors in HandleSet::DLOpen.
- HandleSet& HS = *OpenedHandles;
-
- void *Handle = HandleSet::DLOpen(FileName, Err);
- if (Handle != &Invalid) {
- SmartScopedLock<true> Lock(*SymbolsMutex);
- HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
- }
-
- return DynamicLibrary(Handle);
-}
-
-DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
- std::string *Err) {
- SmartScopedLock<true> Lock(*SymbolsMutex);
- // If we've already loaded this library, tell the caller.
- if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false))
- *Err = "Library already loaded";
-
- return DynamicLibrary(Handle);
-}
-
-void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
- if (!isValid())
- return nullptr;
- return HandleSet::DLSym(Data, SymbolName);
-}
-
-void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
- {
- SmartScopedLock<true> Lock(*SymbolsMutex);
-
- // First check symbols added via AddSymbol().
- if (ExplicitSymbols.isConstructed()) {
- StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
-
- if (i != ExplicitSymbols->end())
- return i->second;
- }
-
- // Now search the libraries.
- if (OpenedHandles.isConstructed()) {
- if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder))
- return Ptr;
- }
- }
-
- return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
-}
-
-//===----------------------------------------------------------------------===//
-// C API.
-//===----------------------------------------------------------------------===//
-
-LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
- return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
-}
-
-void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
- return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
-}
-
-void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
- return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
-}
diff --git a/gnu/llvm/lib/Support/Errno.cpp b/gnu/llvm/lib/Support/Errno.cpp
deleted file mode 100644
index 2149f21281d..00000000000
--- a/gnu/llvm/lib/Support/Errno.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-//===- Errno.cpp - errno support --------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the errno wrappers.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Errno.h"
-#include "llvm/Config/config.h" // Get autoconf configuration settings
-#include "llvm/Support/raw_ostream.h"
-#include <string.h>
-
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
-namespace sys {
-
-#if HAVE_ERRNO_H
-std::string StrError() {
- return StrError(errno);
-}
-#endif // HAVE_ERRNO_H
-
-std::string StrError(int errnum) {
- std::string str;
- if (errnum == 0)
- return str;
-#if defined(HAVE_STRERROR_R) || HAVE_DECL_STRERROR_S
- const int MaxErrStrLen = 2000;
- char buffer[MaxErrStrLen];
- buffer[0] = '\0';
-#endif
-
-#ifdef HAVE_STRERROR_R
- // strerror_r is thread-safe.
-#if defined(__GLIBC__) && defined(_GNU_SOURCE)
- // glibc defines its own incompatible version of strerror_r
- // which may not use the buffer supplied.
- str = strerror_r(errnum, buffer, MaxErrStrLen - 1);
-#else
- strerror_r(errnum, buffer, MaxErrStrLen - 1);
- str = buffer;
-#endif
-#elif HAVE_DECL_STRERROR_S // "Windows Secure API"
- strerror_s(buffer, MaxErrStrLen - 1, errnum);
- str = buffer;
-#elif defined(HAVE_STRERROR)
- // Copy the thread un-safe result of strerror into
- // the buffer as fast as possible to minimize impact
- // of collision of strerror in multiple threads.
- str = strerror(errnum);
-#else
- // Strange that this system doesn't even have strerror
- // but, oh well, just use a generic message
- raw_string_ostream stream(str);
- stream << "Error #" << errnum;
- stream.flush();
-#endif
- return str;
-}
-
-} // namespace sys
-} // namespace llvm
diff --git a/gnu/llvm/lib/Support/Error.cpp b/gnu/llvm/lib/Support/Error.cpp
deleted file mode 100644
index 30bfc3e6d2f..00000000000
--- a/gnu/llvm/lib/Support/Error.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-//===----- lib/Support/Error.cpp - Error and associated utilities ---------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Error.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ManagedStatic.h"
-#include <system_error>
-
-using namespace llvm;
-
-namespace {
-
- enum class ErrorErrorCode : int {
- MultipleErrors = 1,
- FileError,
- InconvertibleError
- };
-
- // FIXME: This class is only here to support the transition to llvm::Error. It
- // will be removed once this transition is complete. Clients should prefer to
- // deal with the Error value directly, rather than converting to error_code.
- class ErrorErrorCategory : public std::error_category {
- public:
- const char *name() const noexcept override { return "Error"; }
-
- std::string message(int condition) const override {
- switch (static_cast<ErrorErrorCode>(condition)) {
- case ErrorErrorCode::MultipleErrors:
- return "Multiple errors";
- case ErrorErrorCode::InconvertibleError:
- return "Inconvertible error value. An error has occurred that could "
- "not be converted to a known std::error_code. Please file a "
- "bug.";
- case ErrorErrorCode::FileError:
- return "A file error occurred.";
- }
- llvm_unreachable("Unhandled error code");
- }
- };
-
-}
-
-static ManagedStatic<ErrorErrorCategory> ErrorErrorCat;
-
-namespace llvm {
-
-void ErrorInfoBase::anchor() {}
-char ErrorInfoBase::ID = 0;
-char ErrorList::ID = 0;
-void ECError::anchor() {}
-char ECError::ID = 0;
-char StringError::ID = 0;
-char FileError::ID = 0;
-
-void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) {
- if (!E)
- return;
- OS << ErrorBanner;
- handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
- EI.log(OS);
- OS << "\n";
- });
-}
-
-
-std::error_code ErrorList::convertToErrorCode() const {
- return std::error_code(static_cast<int>(ErrorErrorCode::MultipleErrors),
- *ErrorErrorCat);
-}
-
-std::error_code inconvertibleErrorCode() {
- return std::error_code(static_cast<int>(ErrorErrorCode::InconvertibleError),
- *ErrorErrorCat);
-}
-
-std::error_code FileError::convertToErrorCode() const {
- return std::error_code(static_cast<int>(ErrorErrorCode::FileError),
- *ErrorErrorCat);
-}
-
-Error errorCodeToError(std::error_code EC) {
- if (!EC)
- return Error::success();
- return Error(llvm::make_unique<ECError>(ECError(EC)));
-}
-
-std::error_code errorToErrorCode(Error Err) {
- std::error_code EC;
- handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
- EC = EI.convertToErrorCode();
- });
- if (EC == inconvertibleErrorCode())
- report_fatal_error(EC.message());
- return EC;
-}
-
-#if LLVM_ENABLE_ABI_BREAKING_CHECKS
-void Error::fatalUncheckedError() const {
- dbgs() << "Program aborted due to an unhandled Error:\n";
- if (getPtr())
- getPtr()->log(dbgs());
- else
- dbgs() << "Error value was Success. (Note: Success values must still be "
- "checked prior to being destroyed).\n";
- abort();
-}
-#endif
-
-StringError::StringError(std::error_code EC, const Twine &S)
- : Msg(S.str()), EC(EC) {}
-
-StringError::StringError(const Twine &S, std::error_code EC)
- : Msg(S.str()), EC(EC), PrintMsgOnly(true) {}
-
-void StringError::log(raw_ostream &OS) const {
- if (PrintMsgOnly) {
- OS << Msg;
- } else {
- OS << EC.message();
- if (!Msg.empty())
- OS << (" " + Msg);
- }
-}
-
-std::error_code StringError::convertToErrorCode() const {
- return EC;
-}
-
-Error createStringError(std::error_code EC, char const *Msg) {
- return make_error<StringError>(Msg, EC);
-}
-
-void report_fatal_error(Error Err, bool GenCrashDiag) {
- assert(Err && "report_fatal_error called with success value");
- std::string ErrMsg;
- {
- raw_string_ostream ErrStream(ErrMsg);
- logAllUnhandledErrors(std::move(Err), ErrStream);
- }
- report_fatal_error(ErrMsg);
-}
-
-} // end namespace llvm
-
-LLVMErrorTypeId LLVMGetErrorTypeId(LLVMErrorRef Err) {
- return reinterpret_cast<ErrorInfoBase *>(Err)->dynamicClassID();
-}
-
-void LLVMConsumeError(LLVMErrorRef Err) { consumeError(unwrap(Err)); }
-
-char *LLVMGetErrorMessage(LLVMErrorRef Err) {
- std::string Tmp = toString(unwrap(Err));
- char *ErrMsg = new char[Tmp.size() + 1];
- memcpy(ErrMsg, Tmp.data(), Tmp.size());
- ErrMsg[Tmp.size()] = '\0';
- return ErrMsg;
-}
-
-void LLVMDisposeErrorMessage(char *ErrMsg) { delete[] ErrMsg; }
-
-LLVMErrorTypeId LLVMGetStringErrorTypeId() {
- return reinterpret_cast<void *>(&StringError::ID);
-}
-
-#ifndef _MSC_VER
-namespace llvm {
-
-// One of these two variables will be referenced by a symbol defined in
-// llvm-config.h. We provide a link-time (or load time for DSO) failure when
-// there is a mismatch in the build configuration of the API client and LLVM.
-#if LLVM_ENABLE_ABI_BREAKING_CHECKS
-int EnableABIBreakingChecks;
-#else
-int DisableABIBreakingChecks;
-#endif
-
-} // end namespace llvm
-#endif
diff --git a/gnu/llvm/lib/Support/ErrorHandling.cpp b/gnu/llvm/lib/Support/ErrorHandling.cpp
deleted file mode 100644
index 21712c5c039..00000000000
--- a/gnu/llvm/lib/Support/ErrorHandling.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-//===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines an API used to indicate fatal error conditions. Non-fatal
-// errors (most of them) should be handled through LLVMContext.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm-c/ErrorHandling.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/Threading.h"
-#include "llvm/Support/WindowsError.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstdlib>
-#include <mutex>
-#include <new>
-
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-#if defined(_MSC_VER)
-# include <io.h>
-# include <fcntl.h>
-#endif
-
-using namespace llvm;
-
-static fatal_error_handler_t ErrorHandler = nullptr;
-static void *ErrorHandlerUserData = nullptr;
-
-static fatal_error_handler_t BadAllocErrorHandler = nullptr;
-static void *BadAllocErrorHandlerUserData = nullptr;
-
-#if LLVM_ENABLE_THREADS == 1
-// Mutexes to synchronize installing error handlers and calling error handlers.
-// Do not use ManagedStatic, or that may allocate memory while attempting to
-// report an OOM.
-//
-// This usage of std::mutex has to be conditionalized behind ifdefs because
-// of this script:
-// compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh
-// That script attempts to statically link the LLVM symbolizer library with the
-// STL and hide all of its symbols with 'opt -internalize'. To reduce size, it
-// cuts out the threading portions of the hermetic copy of libc++ that it
-// builds. We can remove these ifdefs if that script goes away.
-static std::mutex ErrorHandlerMutex;
-static std::mutex BadAllocErrorHandlerMutex;
-#endif
-
-void llvm::install_fatal_error_handler(fatal_error_handler_t handler,
- void *user_data) {
-#if LLVM_ENABLE_THREADS == 1
- std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
-#endif
- assert(!ErrorHandler && "Error handler already registered!\n");
- ErrorHandler = handler;
- ErrorHandlerUserData = user_data;
-}
-
-void llvm::remove_fatal_error_handler() {
-#if LLVM_ENABLE_THREADS == 1
- std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
-#endif
- ErrorHandler = nullptr;
- ErrorHandlerUserData = nullptr;
-}
-
-void llvm::report_fatal_error(const char *Reason, bool GenCrashDiag) {
- report_fatal_error(Twine(Reason), GenCrashDiag);
-}
-
-void llvm::report_fatal_error(const std::string &Reason, bool GenCrashDiag) {
- report_fatal_error(Twine(Reason), GenCrashDiag);
-}
-
-void llvm::report_fatal_error(StringRef Reason, bool GenCrashDiag) {
- report_fatal_error(Twine(Reason), GenCrashDiag);
-}
-
-void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
- llvm::fatal_error_handler_t handler = nullptr;
- void* handlerData = nullptr;
- {
- // Only acquire the mutex while reading the handler, so as not to invoke a
- // user-supplied callback under a lock.
-#if LLVM_ENABLE_THREADS == 1
- std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
-#endif
- handler = ErrorHandler;
- handlerData = ErrorHandlerUserData;
- }
-
- if (handler) {
- handler(handlerData, Reason.str(), GenCrashDiag);
- } else {
- // Blast the result out to stderr. We don't try hard to make sure this
- // succeeds (e.g. handling EINTR) and we can't use errs() here because
- // raw ostreams can call report_fatal_error.
- SmallVector<char, 64> Buffer;
- raw_svector_ostream OS(Buffer);
- OS << "LLVM ERROR: " << Reason << "\n";
- StringRef MessageStr = OS.str();
- ssize_t written = ::write(2, MessageStr.data(), MessageStr.size());
- (void)written; // If something went wrong, we deliberately just give up.
- }
-
- // If we reached here, we are failing ungracefully. Run the interrupt handlers
- // to make sure any special cleanups get done, in particular that we remove
- // files registered with RemoveFileOnSignal.
- sys::RunInterruptHandlers();
-
- exit(1);
-}
-
-void llvm::install_bad_alloc_error_handler(fatal_error_handler_t handler,
- void *user_data) {
-#if LLVM_ENABLE_THREADS == 1
- std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
-#endif
- assert(!ErrorHandler && "Bad alloc error handler already registered!\n");
- BadAllocErrorHandler = handler;
- BadAllocErrorHandlerUserData = user_data;
-}
-
-void llvm::remove_bad_alloc_error_handler() {
-#if LLVM_ENABLE_THREADS == 1
- std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
-#endif
- BadAllocErrorHandler = nullptr;
- BadAllocErrorHandlerUserData = nullptr;
-}
-
-void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
- fatal_error_handler_t Handler = nullptr;
- void *HandlerData = nullptr;
- {
- // Only acquire the mutex while reading the handler, so as not to invoke a
- // user-supplied callback under a lock.
-#if LLVM_ENABLE_THREADS == 1
- std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
-#endif
- Handler = BadAllocErrorHandler;
- HandlerData = BadAllocErrorHandlerUserData;
- }
-
- if (Handler) {
- Handler(HandlerData, Reason, GenCrashDiag);
- llvm_unreachable("bad alloc handler should not return");
- }
-
-#ifdef LLVM_ENABLE_EXCEPTIONS
- // If exceptions are enabled, make OOM in malloc look like OOM in new.
- throw std::bad_alloc();
-#else
- // Don't call the normal error handler. It may allocate memory. Directly write
- // an OOM to stderr and abort.
- char OOMMessage[] = "LLVM ERROR: out of memory\n";
- ssize_t written = ::write(2, OOMMessage, strlen(OOMMessage));
- (void)written;
- abort();
-#endif
-}
-
-#ifdef LLVM_ENABLE_EXCEPTIONS
-// Do not set custom new handler if exceptions are enabled. In this case OOM
-// errors are handled by throwing 'std::bad_alloc'.
-void llvm::install_out_of_memory_new_handler() {
-}
-#else
-// Causes crash on allocation failure. It is called prior to the handler set by
-// 'install_bad_alloc_error_handler'.
-static void out_of_memory_new_handler() {
- llvm::report_bad_alloc_error("Allocation failed");
-}
-
-// Installs new handler that causes crash on allocation failure. It does not
-// need to be called explicitly, if this file is linked to application, because
-// in this case it is called during construction of 'new_handler_installer'.
-void llvm::install_out_of_memory_new_handler() {
- static bool out_of_memory_new_handler_installed = false;
- if (!out_of_memory_new_handler_installed) {
- std::set_new_handler(out_of_memory_new_handler);
- out_of_memory_new_handler_installed = true;
- }
-}
-
-// Static object that causes installation of 'out_of_memory_new_handler' before
-// execution of 'main'.
-static class NewHandlerInstaller {
-public:
- NewHandlerInstaller() {
- install_out_of_memory_new_handler();
- }
-} new_handler_installer;
-#endif
-
-void llvm::llvm_unreachable_internal(const char *msg, const char *file,
- unsigned line) {
- // This code intentionally doesn't call the ErrorHandler callback, because
- // llvm_unreachable is intended to be used to indicate "impossible"
- // situations, and not legitimate runtime errors.
- if (msg)
- dbgs() << msg << "\n";
- dbgs() << "UNREACHABLE executed";
- if (file)
- dbgs() << " at " << file << ":" << line;
- dbgs() << "!\n";
- abort();
-#ifdef LLVM_BUILTIN_UNREACHABLE
- // Windows systems and possibly others don't declare abort() to be noreturn,
- // so use the unreachable builtin to avoid a Clang self-host warning.
- LLVM_BUILTIN_UNREACHABLE;
-#endif
-}
-
-static void bindingsErrorHandler(void *user_data, const std::string& reason,
- bool gen_crash_diag) {
- LLVMFatalErrorHandler handler =
- LLVM_EXTENSION reinterpret_cast<LLVMFatalErrorHandler>(user_data);
- handler(reason.c_str());
-}
-
-void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler) {
- install_fatal_error_handler(bindingsErrorHandler,
- LLVM_EXTENSION reinterpret_cast<void *>(Handler));
-}
-
-void LLVMResetFatalErrorHandler() {
- remove_fatal_error_handler();
-}
-
-#ifdef _WIN32
-
-#include <winerror.h>
-
-// I'd rather not double the line count of the following.
-#define MAP_ERR_TO_COND(x, y) \
- case x: \
- return make_error_code(errc::y)
-
-std::error_code llvm::mapWindowsError(unsigned EV) {
- switch (EV) {
- MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied);
- MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists);
- MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device);
- MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long);
- MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy);
- MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy);
- MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied);
- MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error);
- MAP_ERR_TO_COND(ERROR_CANTREAD, io_error);
- MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error);
- MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied);
- MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device);
- MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy);
- MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty);
- MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument);
- MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device);
- MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists);
- MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory);
- MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device);
- MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied);
- MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device);
- MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);
- MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument);
- MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument);
- MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available);
- MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available);
- MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument);
- MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied);
- MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory);
- MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again);
- MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error);
- MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy);
- MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory);
- MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory);
- MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory);
- MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error);
- MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again);
- MAP_ERR_TO_COND(ERROR_SEEK, io_error);
- MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied);
- MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open);
- MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error);
- MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied);
- MAP_ERR_TO_COND(WSAEACCES, permission_denied);
- MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor);
- MAP_ERR_TO_COND(WSAEFAULT, bad_address);
- MAP_ERR_TO_COND(WSAEINTR, interrupted);
- MAP_ERR_TO_COND(WSAEINVAL, invalid_argument);
- MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open);
- MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long);
- default:
- return std::error_code(EV, std::system_category());
- }
-}
-
-#endif
diff --git a/gnu/llvm/lib/Support/FileCheck.cpp b/gnu/llvm/lib/Support/FileCheck.cpp
deleted file mode 100644
index 37986c96c08..00000000000
--- a/gnu/llvm/lib/Support/FileCheck.cpp
+++ /dev/null
@@ -1,1446 +0,0 @@
-//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// FileCheck does a line-by line check of a file that validates whether it
-// contains the expected content. This is useful for regression tests etc.
-//
-// This file implements most of the API that will be used by the FileCheck utility
-// as well as various unittests.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/FileCheck.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/FormatVariadic.h"
-#include <cstdint>
-#include <list>
-#include <map>
-#include <tuple>
-#include <utility>
-
-using namespace llvm;
-
-/// Parses the given string into the Pattern.
-///
-/// \p Prefix provides which prefix is being matched, \p SM provides the
-/// SourceMgr used for error reports, and \p LineNumber is the line number in
-/// the input file from which the pattern string was read. Returns true in
-/// case of an error, false otherwise.
-bool FileCheckPattern::ParsePattern(StringRef PatternStr, StringRef Prefix,
- SourceMgr &SM, unsigned LineNumber,
- const FileCheckRequest &Req) {
- bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot;
-
- this->LineNumber = LineNumber;
- PatternLoc = SMLoc::getFromPointer(PatternStr.data());
-
- if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
- // Ignore trailing whitespace.
- while (!PatternStr.empty() &&
- (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
- PatternStr = PatternStr.substr(0, PatternStr.size() - 1);
-
- // Check that there is something on the line.
- if (PatternStr.empty() && CheckTy != Check::CheckEmpty) {
- SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
- "found empty check string with prefix '" + Prefix + ":'");
- return true;
- }
-
- if (!PatternStr.empty() && CheckTy == Check::CheckEmpty) {
- SM.PrintMessage(
- PatternLoc, SourceMgr::DK_Error,
- "found non-empty check string for empty check with prefix '" + Prefix +
- ":'");
- return true;
- }
-
- if (CheckTy == Check::CheckEmpty) {
- RegExStr = "(\n$)";
- return false;
- }
-
- // Check to see if this is a fixed string, or if it has regex pieces.
- if (!MatchFullLinesHere &&
- (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
- PatternStr.find("[[") == StringRef::npos))) {
- FixedStr = PatternStr;
- return false;
- }
-
- if (MatchFullLinesHere) {
- RegExStr += '^';
- if (!Req.NoCanonicalizeWhiteSpace)
- RegExStr += " *";
- }
-
- // Paren value #0 is for the fully matched string. Any new parenthesized
- // values add from there.
- unsigned CurParen = 1;
-
- // Otherwise, there is at least one regex piece. Build up the regex pattern
- // by escaping scary characters in fixed strings, building up one big regex.
- while (!PatternStr.empty()) {
- // RegEx matches.
- if (PatternStr.startswith("{{")) {
- // This is the start of a regex match. Scan for the }}.
- size_t End = PatternStr.find("}}");
- if (End == StringRef::npos) {
- SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
- SourceMgr::DK_Error,
- "found start of regex string with no end '}}'");
- return true;
- }
-
- // Enclose {{}} patterns in parens just like [[]] even though we're not
- // capturing the result for any purpose. This is required in case the
- // expression contains an alternation like: CHECK: abc{{x|z}}def. We
- // want this to turn into: "abc(x|z)def" not "abcx|zdef".
- RegExStr += '(';
- ++CurParen;
-
- if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM))
- return true;
- RegExStr += ')';
-
- PatternStr = PatternStr.substr(End + 2);
- continue;
- }
-
- // Named RegEx matches. These are of two forms: [[foo:.*]] which matches .*
- // (or some other regex) and assigns it to the FileCheck variable 'foo'. The
- // second form is [[foo]] which is a reference to foo. The variable name
- // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
- // it. This is to catch some common errors.
- if (PatternStr.startswith("[[")) {
- // Find the closing bracket pair ending the match. End is going to be an
- // offset relative to the beginning of the match string.
- size_t End = FindRegexVarEnd(PatternStr.substr(2), SM);
-
- if (End == StringRef::npos) {
- SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
- SourceMgr::DK_Error,
- "invalid named regex reference, no ]] found");
- return true;
- }
-
- StringRef MatchStr = PatternStr.substr(2, End);
- PatternStr = PatternStr.substr(End + 4);
-
- // Get the regex name (e.g. "foo").
- size_t NameEnd = MatchStr.find(':');
- StringRef Name = MatchStr.substr(0, NameEnd);
-
- if (Name.empty()) {
- SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
- "invalid name in named regex: empty name");
- return true;
- }
-
- // Verify that the name/expression is well formed. FileCheck currently
- // supports @LINE, @LINE+number, @LINE-number expressions. The check here
- // is relaxed, more strict check is performed in \c EvaluateExpression.
- bool IsExpression = false;
- for (unsigned i = 0, e = Name.size(); i != e; ++i) {
- if (i == 0) {
- if (Name[i] == '$') // Global vars start with '$'
- continue;
- if (Name[i] == '@') {
- if (NameEnd != StringRef::npos) {
- SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
- SourceMgr::DK_Error,
- "invalid name in named regex definition");
- return true;
- }
- IsExpression = true;
- continue;
- }
- }
- if (Name[i] != '_' && !isalnum(Name[i]) &&
- (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) {
- SM.PrintMessage(SMLoc::getFromPointer(Name.data() + i),
- SourceMgr::DK_Error, "invalid name in named regex");
- return true;
- }
- }
-
- // Name can't start with a digit.
- if (isdigit(static_cast<unsigned char>(Name[0]))) {
- SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
- "invalid name in named regex");
- return true;
- }
-
- // Handle [[foo]].
- if (NameEnd == StringRef::npos) {
- // Handle variables that were defined earlier on the same line by
- // emitting a backreference.
- if (VariableDefs.find(Name) != VariableDefs.end()) {
- unsigned VarParenNum = VariableDefs[Name];
- if (VarParenNum < 1 || VarParenNum > 9) {
- SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
- SourceMgr::DK_Error,
- "Can't back-reference more than 9 variables");
- return true;
- }
- AddBackrefToRegEx(VarParenNum);
- } else {
- VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
- }
- continue;
- }
-
- // Handle [[foo:.*]].
- VariableDefs[Name] = CurParen;
- RegExStr += '(';
- ++CurParen;
-
- if (AddRegExToRegEx(MatchStr.substr(NameEnd + 1), CurParen, SM))
- return true;
-
- RegExStr += ')';
- }
-
- // Handle fixed string matches.
- // Find the end, which is the start of the next regex.
- size_t FixedMatchEnd = PatternStr.find("{{");
- FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[["));
- RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd));
- PatternStr = PatternStr.substr(FixedMatchEnd);
- }
-
- if (MatchFullLinesHere) {
- if (!Req.NoCanonicalizeWhiteSpace)
- RegExStr += " *";
- RegExStr += '$';
- }
-
- return false;
-}
-
-bool FileCheckPattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) {
- Regex R(RS);
- std::string Error;
- if (!R.isValid(Error)) {
- SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error,
- "invalid regex: " + Error);
- return true;
- }
-
- RegExStr += RS.str();
- CurParen += R.getNumMatches();
- return false;
-}
-
-void FileCheckPattern::AddBackrefToRegEx(unsigned BackrefNum) {
- assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number");
- std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum);
- RegExStr += Backref;
-}
-
-/// Evaluates expression and stores the result to \p Value.
-///
-/// Returns true on success and false when the expression has invalid syntax.
-bool FileCheckPattern::EvaluateExpression(StringRef Expr, std::string &Value) const {
- // The only supported expression is @LINE([\+-]\d+)?
- if (!Expr.startswith("@LINE"))
- return false;
- Expr = Expr.substr(StringRef("@LINE").size());
- int Offset = 0;
- if (!Expr.empty()) {
- if (Expr[0] == '+')
- Expr = Expr.substr(1);
- else if (Expr[0] != '-')
- return false;
- if (Expr.getAsInteger(10, Offset))
- return false;
- }
- Value = llvm::itostr(LineNumber + Offset);
- return true;
-}
-
-/// Matches the pattern string against the input buffer \p Buffer
-///
-/// This returns the position that is matched or npos if there is no match. If
-/// there is a match, the size of the matched string is returned in \p
-/// MatchLen.
-///
-/// The \p VariableTable StringMap provides the current values of filecheck
-/// variables and is updated if this match defines new values.
-size_t FileCheckPattern::Match(StringRef Buffer, size_t &MatchLen,
- StringMap<StringRef> &VariableTable) const {
- // If this is the EOF pattern, match it immediately.
- if (CheckTy == Check::CheckEOF) {
- MatchLen = 0;
- return Buffer.size();
- }
-
- // If this is a fixed string pattern, just match it now.
- if (!FixedStr.empty()) {
- MatchLen = FixedStr.size();
- return Buffer.find(FixedStr);
- }
-
- // Regex match.
-
- // If there are variable uses, we need to create a temporary string with the
- // actual value.
- StringRef RegExToMatch = RegExStr;
- std::string TmpStr;
- if (!VariableUses.empty()) {
- TmpStr = RegExStr;
-
- unsigned InsertOffset = 0;
- for (const auto &VariableUse : VariableUses) {
- std::string Value;
-
- if (VariableUse.first[0] == '@') {
- if (!EvaluateExpression(VariableUse.first, Value))
- return StringRef::npos;
- } else {
- StringMap<StringRef>::iterator it =
- VariableTable.find(VariableUse.first);
- // If the variable is undefined, return an error.
- if (it == VariableTable.end())
- return StringRef::npos;
-
- // Look up the value and escape it so that we can put it into the regex.
- Value += Regex::escape(it->second);
- }
-
- // Plop it into the regex at the adjusted offset.
- TmpStr.insert(TmpStr.begin() + VariableUse.second + InsertOffset,
- Value.begin(), Value.end());
- InsertOffset += Value.size();
- }
-
- // Match the newly constructed regex.
- RegExToMatch = TmpStr;
- }
-
- SmallVector<StringRef, 4> MatchInfo;
- if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
- return StringRef::npos;
-
- // Successful regex match.
- assert(!MatchInfo.empty() && "Didn't get any match");
- StringRef FullMatch = MatchInfo[0];
-
- // If this defines any variables, remember their values.
- for (const auto &VariableDef : VariableDefs) {
- assert(VariableDef.second < MatchInfo.size() && "Internal paren error");
- VariableTable[VariableDef.first] = MatchInfo[VariableDef.second];
- }
-
- // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
- // the required preceding newline, which is consumed by the pattern in the
- // case of CHECK-EMPTY but not CHECK-NEXT.
- size_t MatchStartSkip = CheckTy == Check::CheckEmpty;
- MatchLen = FullMatch.size() - MatchStartSkip;
- return FullMatch.data() - Buffer.data() + MatchStartSkip;
-}
-
-
-/// Computes an arbitrary estimate for the quality of matching this pattern at
-/// the start of \p Buffer; a distance of zero should correspond to a perfect
-/// match.
-unsigned
-FileCheckPattern::ComputeMatchDistance(StringRef Buffer,
- const StringMap<StringRef> &VariableTable) const {
- // Just compute the number of matching characters. For regular expressions, we
- // just compare against the regex itself and hope for the best.
- //
- // FIXME: One easy improvement here is have the regex lib generate a single
- // example regular expression which matches, and use that as the example
- // string.
- StringRef ExampleString(FixedStr);
- if (ExampleString.empty())
- ExampleString = RegExStr;
-
- // Only compare up to the first line in the buffer, or the string size.
- StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
- BufferPrefix = BufferPrefix.split('\n').first;
- return BufferPrefix.edit_distance(ExampleString);
-}
-
-void FileCheckPattern::PrintVariableUses(const SourceMgr &SM, StringRef Buffer,
- const StringMap<StringRef> &VariableTable,
- SMRange MatchRange) const {
- // If this was a regular expression using variables, print the current
- // variable values.
- if (!VariableUses.empty()) {
- for (const auto &VariableUse : VariableUses) {
- SmallString<256> Msg;
- raw_svector_ostream OS(Msg);
- StringRef Var = VariableUse.first;
- if (Var[0] == '@') {
- std::string Value;
- if (EvaluateExpression(Var, Value)) {
- OS << "with expression \"";
- OS.write_escaped(Var) << "\" equal to \"";
- OS.write_escaped(Value) << "\"";
- } else {
- OS << "uses incorrect expression \"";
- OS.write_escaped(Var) << "\"";
- }
- } else {
- StringMap<StringRef>::const_iterator it = VariableTable.find(Var);
-
- // Check for undefined variable references.
- if (it == VariableTable.end()) {
- OS << "uses undefined variable \"";
- OS.write_escaped(Var) << "\"";
- } else {
- OS << "with variable \"";
- OS.write_escaped(Var) << "\" equal to \"";
- OS.write_escaped(it->second) << "\"";
- }
- }
-
- if (MatchRange.isValid())
- SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, OS.str(),
- {MatchRange});
- else
- SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
- SourceMgr::DK_Note, OS.str());
- }
- }
-}
-
-static SMRange ProcessMatchResult(FileCheckDiag::MatchType MatchTy,
- const SourceMgr &SM, SMLoc Loc,
- Check::FileCheckType CheckTy,
- StringRef Buffer, size_t Pos, size_t Len,
- std::vector<FileCheckDiag> *Diags,
- bool AdjustPrevDiag = false) {
- SMLoc Start = SMLoc::getFromPointer(Buffer.data() + Pos);
- SMLoc End = SMLoc::getFromPointer(Buffer.data() + Pos + Len);
- SMRange Range(Start, End);
- if (Diags) {
- if (AdjustPrevDiag)
- Diags->rbegin()->MatchTy = MatchTy;
- else
- Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range);
- }
- return Range;
-}
-
-void FileCheckPattern::PrintFuzzyMatch(
- const SourceMgr &SM, StringRef Buffer,
- const StringMap<StringRef> &VariableTable,
- std::vector<FileCheckDiag> *Diags) const {
- // Attempt to find the closest/best fuzzy match. Usually an error happens
- // because some string in the output didn't exactly match. In these cases, we
- // would like to show the user a best guess at what "should have" matched, to
- // save them having to actually check the input manually.
- size_t NumLinesForward = 0;
- size_t Best = StringRef::npos;
- double BestQuality = 0;
-
- // Use an arbitrary 4k limit on how far we will search.
- for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
- if (Buffer[i] == '\n')
- ++NumLinesForward;
-
- // Patterns have leading whitespace stripped, so skip whitespace when
- // looking for something which looks like a pattern.
- if (Buffer[i] == ' ' || Buffer[i] == '\t')
- continue;
-
- // Compute the "quality" of this match as an arbitrary combination of the
- // match distance and the number of lines skipped to get to this match.
- unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable);
- double Quality = Distance + (NumLinesForward / 100.);
-
- if (Quality < BestQuality || Best == StringRef::npos) {
- Best = i;
- BestQuality = Quality;
- }
- }
-
- // Print the "possible intended match here" line if we found something
- // reasonable and not equal to what we showed in the "scanning from here"
- // line.
- if (Best && Best != StringRef::npos && BestQuality < 50) {
- SMRange MatchRange =
- ProcessMatchResult(FileCheckDiag::MatchFuzzy, SM, getLoc(),
- getCheckTy(), Buffer, Best, 0, Diags);
- SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note,
- "possible intended match here");
-
- // FIXME: If we wanted to be really friendly we would show why the match
- // failed, as it can be hard to spot simple one character differences.
- }
-}
-
-/// Finds the closing sequence of a regex variable usage or definition.
-///
-/// \p Str has to point in the beginning of the definition (right after the
-/// opening sequence). Returns the offset of the closing sequence within Str,
-/// or npos if it was not found.
-size_t FileCheckPattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) {
- // Offset keeps track of the current offset within the input Str
- size_t Offset = 0;
- // [...] Nesting depth
- size_t BracketDepth = 0;
-
- while (!Str.empty()) {
- if (Str.startswith("]]") && BracketDepth == 0)
- return Offset;
- if (Str[0] == '\\') {
- // Backslash escapes the next char within regexes, so skip them both.
- Str = Str.substr(2);
- Offset += 2;
- } else {
- switch (Str[0]) {
- default:
- break;
- case '[':
- BracketDepth++;
- break;
- case ']':
- if (BracketDepth == 0) {
- SM.PrintMessage(SMLoc::getFromPointer(Str.data()),
- SourceMgr::DK_Error,
- "missing closing \"]\" for regex variable");
- exit(1);
- }
- BracketDepth--;
- break;
- }
- Str = Str.substr(1);
- Offset++;
- }
- }
-
- return StringRef::npos;
-}
-
-/// Canonicalize whitespaces in the file. Line endings are replaced with
-/// UNIX-style '\n'.
-StringRef
-llvm::FileCheck::CanonicalizeFile(MemoryBuffer &MB,
- SmallVectorImpl<char> &OutputBuffer) {
- OutputBuffer.reserve(MB.getBufferSize());
-
- for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd();
- Ptr != End; ++Ptr) {
- // Eliminate trailing dosish \r.
- if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
- continue;
- }
-
- // If current char is not a horizontal whitespace or if horizontal
- // whitespace canonicalization is disabled, dump it to output as is.
- if (Req.NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) {
- OutputBuffer.push_back(*Ptr);
- continue;
- }
-
- // Otherwise, add one space and advance over neighboring space.
- OutputBuffer.push_back(' ');
- while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t'))
- ++Ptr;
- }
-
- // Add a null byte and then return all but that byte.
- OutputBuffer.push_back('\0');
- return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1);
-}
-
-FileCheckDiag::FileCheckDiag(const SourceMgr &SM,
- const Check::FileCheckType &CheckTy,
- SMLoc CheckLoc, MatchType MatchTy,
- SMRange InputRange)
- : CheckTy(CheckTy), MatchTy(MatchTy) {
- auto Start = SM.getLineAndColumn(InputRange.Start);
- auto End = SM.getLineAndColumn(InputRange.End);
- InputStartLine = Start.first;
- InputStartCol = Start.second;
- InputEndLine = End.first;
- InputEndCol = End.second;
- Start = SM.getLineAndColumn(CheckLoc);
- CheckLine = Start.first;
- CheckCol = Start.second;
-}
-
-static bool IsPartOfWord(char c) {
- return (isalnum(c) || c == '-' || c == '_');
-}
-
-Check::FileCheckType &Check::FileCheckType::setCount(int C) {
- assert(Count > 0 && "zero and negative counts are not supported");
- assert((C == 1 || Kind == CheckPlain) &&
- "count supported only for plain CHECK directives");
- Count = C;
- return *this;
-}
-
-// Get a description of the type.
-std::string Check::FileCheckType::getDescription(StringRef Prefix) const {
- switch (Kind) {
- case Check::CheckNone:
- return "invalid";
- case Check::CheckPlain:
- if (Count > 1)
- return Prefix.str() + "-COUNT";
- return Prefix;
- case Check::CheckNext:
- return Prefix.str() + "-NEXT";
- case Check::CheckSame:
- return Prefix.str() + "-SAME";
- case Check::CheckNot:
- return Prefix.str() + "-NOT";
- case Check::CheckDAG:
- return Prefix.str() + "-DAG";
- case Check::CheckLabel:
- return Prefix.str() + "-LABEL";
- case Check::CheckEmpty:
- return Prefix.str() + "-EMPTY";
- case Check::CheckEOF:
- return "implicit EOF";
- case Check::CheckBadNot:
- return "bad NOT";
- case Check::CheckBadCount:
- return "bad COUNT";
- }
- llvm_unreachable("unknown FileCheckType");
-}
-
-static std::pair<Check::FileCheckType, StringRef>
-FindCheckType(StringRef Buffer, StringRef Prefix) {
- if (Buffer.size() <= Prefix.size())
- return {Check::CheckNone, StringRef()};
-
- char NextChar = Buffer[Prefix.size()];
-
- StringRef Rest = Buffer.drop_front(Prefix.size() + 1);
- // Verify that the : is present after the prefix.
- if (NextChar == ':')
- return {Check::CheckPlain, Rest};
-
- if (NextChar != '-')
- return {Check::CheckNone, StringRef()};
-
- if (Rest.consume_front("COUNT-")) {
- int64_t Count;
- if (Rest.consumeInteger(10, Count))
- // Error happened in parsing integer.
- return {Check::CheckBadCount, Rest};
- if (Count <= 0 || Count > INT32_MAX)
- return {Check::CheckBadCount, Rest};
- if (!Rest.consume_front(":"))
- return {Check::CheckBadCount, Rest};
- return {Check::FileCheckType(Check::CheckPlain).setCount(Count), Rest};
- }
-
- if (Rest.consume_front("NEXT:"))
- return {Check::CheckNext, Rest};
-
- if (Rest.consume_front("SAME:"))
- return {Check::CheckSame, Rest};
-
- if (Rest.consume_front("NOT:"))
- return {Check::CheckNot, Rest};
-
- if (Rest.consume_front("DAG:"))
- return {Check::CheckDAG, Rest};
-
- if (Rest.consume_front("LABEL:"))
- return {Check::CheckLabel, Rest};
-
- if (Rest.consume_front("EMPTY:"))
- return {Check::CheckEmpty, Rest};
-
- // You can't combine -NOT with another suffix.
- if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||
- Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||
- Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:") ||
- Rest.startswith("EMPTY-NOT:") || Rest.startswith("NOT-EMPTY:"))
- return {Check::CheckBadNot, Rest};
-
- return {Check::CheckNone, Rest};
-}
-
-// From the given position, find the next character after the word.
-static size_t SkipWord(StringRef Str, size_t Loc) {
- while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
- ++Loc;
- return Loc;
-}
-
-/// Search the buffer for the first prefix in the prefix regular expression.
-///
-/// This searches the buffer using the provided regular expression, however it
-/// enforces constraints beyond that:
-/// 1) The found prefix must not be a suffix of something that looks like
-/// a valid prefix.
-/// 2) The found prefix must be followed by a valid check type suffix using \c
-/// FindCheckType above.
-///
-/// Returns a pair of StringRefs into the Buffer, which combines:
-/// - the first match of the regular expression to satisfy these two is
-/// returned,
-/// otherwise an empty StringRef is returned to indicate failure.
-/// - buffer rewound to the location right after parsed suffix, for parsing
-/// to continue from
-///
-/// If this routine returns a valid prefix, it will also shrink \p Buffer to
-/// start at the beginning of the returned prefix, increment \p LineNumber for
-/// each new line consumed from \p Buffer, and set \p CheckTy to the type of
-/// check found by examining the suffix.
-///
-/// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
-/// is unspecified.
-static std::pair<StringRef, StringRef>
-FindFirstMatchingPrefix(Regex &PrefixRE, StringRef &Buffer,
- unsigned &LineNumber, Check::FileCheckType &CheckTy) {
- SmallVector<StringRef, 2> Matches;
-
- while (!Buffer.empty()) {
- // Find the first (longest) match using the RE.
- if (!PrefixRE.match(Buffer, &Matches))
- // No match at all, bail.
- return {StringRef(), StringRef()};
-
- StringRef Prefix = Matches[0];
- Matches.clear();
-
- assert(Prefix.data() >= Buffer.data() &&
- Prefix.data() < Buffer.data() + Buffer.size() &&
- "Prefix doesn't start inside of buffer!");
- size_t Loc = Prefix.data() - Buffer.data();
- StringRef Skipped = Buffer.substr(0, Loc);
- Buffer = Buffer.drop_front(Loc);
- LineNumber += Skipped.count('\n');
-
- // Check that the matched prefix isn't a suffix of some other check-like
- // word.
- // FIXME: This is a very ad-hoc check. it would be better handled in some
- // other way. Among other things it seems hard to distinguish between
- // intentional and unintentional uses of this feature.
- if (Skipped.empty() || !IsPartOfWord(Skipped.back())) {
- // Now extract the type.
- StringRef AfterSuffix;
- std::tie(CheckTy, AfterSuffix) = FindCheckType(Buffer, Prefix);
-
- // If we've found a valid check type for this prefix, we're done.
- if (CheckTy != Check::CheckNone)
- return {Prefix, AfterSuffix};
- }
-
- // If we didn't successfully find a prefix, we need to skip this invalid
- // prefix and continue scanning. We directly skip the prefix that was
- // matched and any additional parts of that check-like word.
- Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size()));
- }
-
- // We ran out of buffer while skipping partial matches so give up.
- return {StringRef(), StringRef()};
-}
-
-/// Read the check file, which specifies the sequence of expected strings.
-///
-/// The strings are added to the CheckStrings vector. Returns true in case of
-/// an error, false otherwise.
-bool llvm::FileCheck::ReadCheckFile(SourceMgr &SM, StringRef Buffer,
- Regex &PrefixRE,
- std::vector<FileCheckString> &CheckStrings) {
- std::vector<FileCheckPattern> ImplicitNegativeChecks;
- for (const auto &PatternString : Req.ImplicitCheckNot) {
- // Create a buffer with fake command line content in order to display the
- // command line option responsible for the specific implicit CHECK-NOT.
- std::string Prefix = "-implicit-check-not='";
- std::string Suffix = "'";
- std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy(
- Prefix + PatternString + Suffix, "command line");
-
- StringRef PatternInBuffer =
- CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
- SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
-
- ImplicitNegativeChecks.push_back(FileCheckPattern(Check::CheckNot));
- ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer,
- "IMPLICIT-CHECK", SM, 0, Req);
- }
-
- std::vector<FileCheckPattern> DagNotMatches = ImplicitNegativeChecks;
-
- // LineNumber keeps track of the line on which CheckPrefix instances are
- // found.
- unsigned LineNumber = 1;
-
- while (1) {
- Check::FileCheckType CheckTy;
-
- // See if a prefix occurs in the memory buffer.
- StringRef UsedPrefix;
- StringRef AfterSuffix;
- std::tie(UsedPrefix, AfterSuffix) =
- FindFirstMatchingPrefix(PrefixRE, Buffer, LineNumber, CheckTy);
- if (UsedPrefix.empty())
- break;
- assert(UsedPrefix.data() == Buffer.data() &&
- "Failed to move Buffer's start forward, or pointed prefix outside "
- "of the buffer!");
- assert(AfterSuffix.data() >= Buffer.data() &&
- AfterSuffix.data() < Buffer.data() + Buffer.size() &&
- "Parsing after suffix doesn't start inside of buffer!");
-
- // Location to use for error messages.
- const char *UsedPrefixStart = UsedPrefix.data();
-
- // Skip the buffer to the end of parsed suffix (or just prefix, if no good
- // suffix was processed).
- Buffer = AfterSuffix.empty() ? Buffer.drop_front(UsedPrefix.size())
- : AfterSuffix;
-
- // Complain about useful-looking but unsupported suffixes.
- if (CheckTy == Check::CheckBadNot) {
- SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
- "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
- return true;
- }
-
- // Complain about invalid count specification.
- if (CheckTy == Check::CheckBadCount) {
- SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error,
- "invalid count in -COUNT specification on prefix '" +
- UsedPrefix + "'");
- return true;
- }
-
- // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
- // leading whitespace.
- if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines))
- Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
-
- // Scan ahead to the end of line.
- size_t EOL = Buffer.find_first_of("\n\r");
-
- // Remember the location of the start of the pattern, for diagnostics.
- SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
-
- // Parse the pattern.
- FileCheckPattern P(CheckTy);
- if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber, Req))
- return true;
-
- // Verify that CHECK-LABEL lines do not define or use variables
- if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
- SM.PrintMessage(
- SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error,
- "found '" + UsedPrefix + "-LABEL:'"
- " with variable definition or use");
- return true;
- }
-
- Buffer = Buffer.substr(EOL);
-
- // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
- if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||
- CheckTy == Check::CheckEmpty) &&
- CheckStrings.empty()) {
- StringRef Type = CheckTy == Check::CheckNext
- ? "NEXT"
- : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";
- SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
- SourceMgr::DK_Error,
- "found '" + UsedPrefix + "-" + Type +
- "' without previous '" + UsedPrefix + ": line");
- return true;
- }
-
- // Handle CHECK-DAG/-NOT.
- if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
- DagNotMatches.push_back(P);
- continue;
- }
-
- // Okay, add the string we captured to the output vector and move on.
- CheckStrings.emplace_back(P, UsedPrefix, PatternLoc);
- std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
- DagNotMatches = ImplicitNegativeChecks;
- }
-
- // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
- // prefix as a filler for the error message.
- if (!DagNotMatches.empty()) {
- CheckStrings.emplace_back(FileCheckPattern(Check::CheckEOF), *Req.CheckPrefixes.begin(),
- SMLoc::getFromPointer(Buffer.data()));
- std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
- }
-
- if (CheckStrings.empty()) {
- errs() << "error: no check strings found with prefix"
- << (Req.CheckPrefixes.size() > 1 ? "es " : " ");
- auto I = Req.CheckPrefixes.begin();
- auto E = Req.CheckPrefixes.end();
- if (I != E) {
- errs() << "\'" << *I << ":'";
- ++I;
- }
- for (; I != E; ++I)
- errs() << ", \'" << *I << ":'";
-
- errs() << '\n';
- return true;
- }
-
- return false;
-}
-
-static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
- StringRef Prefix, SMLoc Loc, const FileCheckPattern &Pat,
- int MatchedCount, StringRef Buffer,
- StringMap<StringRef> &VariableTable, size_t MatchPos,
- size_t MatchLen, const FileCheckRequest &Req,
- std::vector<FileCheckDiag> *Diags) {
- if (ExpectedMatch) {
- if (!Req.Verbose)
- return;
- if (!Req.VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF)
- return;
- }
- SMRange MatchRange = ProcessMatchResult(
- ExpectedMatch ? FileCheckDiag::MatchFoundAndExpected
- : FileCheckDiag::MatchFoundButExcluded,
- SM, Loc, Pat.getCheckTy(), Buffer, MatchPos, MatchLen, Diags);
- std::string Message = formatv("{0}: {1} string found in input",
- Pat.getCheckTy().getDescription(Prefix),
- (ExpectedMatch ? "expected" : "excluded"))
- .str();
- if (Pat.getCount() > 1)
- Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
-
- SM.PrintMessage(
- Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error, Message);
- SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, "found here",
- {MatchRange});
- Pat.PrintVariableUses(SM, Buffer, VariableTable, MatchRange);
-}
-
-static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
- const FileCheckString &CheckStr, int MatchedCount,
- StringRef Buffer, StringMap<StringRef> &VariableTable,
- size_t MatchPos, size_t MatchLen, FileCheckRequest &Req,
- std::vector<FileCheckDiag> *Diags) {
- PrintMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
- MatchedCount, Buffer, VariableTable, MatchPos, MatchLen, Req,
- Diags);
-}
-
-static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
- StringRef Prefix, SMLoc Loc,
- const FileCheckPattern &Pat, int MatchedCount,
- StringRef Buffer, StringMap<StringRef> &VariableTable,
- bool VerboseVerbose,
- std::vector<FileCheckDiag> *Diags) {
- if (!ExpectedMatch && !VerboseVerbose)
- return;
-
- // Otherwise, we have an error, emit an error message.
- std::string Message = formatv("{0}: {1} string not found in input",
- Pat.getCheckTy().getDescription(Prefix),
- (ExpectedMatch ? "expected" : "excluded"))
- .str();
- if (Pat.getCount() > 1)
- Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str();
-
- SM.PrintMessage(
- Loc, ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark, Message);
-
- // Print the "scanning from here" line. If the current position is at the
- // end of a line, advance to the start of the next line.
- Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
- SMRange SearchRange = ProcessMatchResult(
- ExpectedMatch ? FileCheckDiag::MatchNoneButExpected
- : FileCheckDiag::MatchNoneAndExcluded,
- SM, Loc, Pat.getCheckTy(), Buffer, 0, Buffer.size(), Diags);
- SM.PrintMessage(SearchRange.Start, SourceMgr::DK_Note, "scanning from here");
-
- // Allow the pattern to print additional information if desired.
- Pat.PrintVariableUses(SM, Buffer, VariableTable);
-
- if (ExpectedMatch)
- Pat.PrintFuzzyMatch(SM, Buffer, VariableTable, Diags);
-}
-
-static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
- const FileCheckString &CheckStr, int MatchedCount,
- StringRef Buffer, StringMap<StringRef> &VariableTable,
- bool VerboseVerbose,
- std::vector<FileCheckDiag> *Diags) {
- PrintNoMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
- MatchedCount, Buffer, VariableTable, VerboseVerbose, Diags);
-}
-
-/// Count the number of newlines in the specified range.
-static unsigned CountNumNewlinesBetween(StringRef Range,
- const char *&FirstNewLine) {
- unsigned NumNewLines = 0;
- while (1) {
- // Scan for newline.
- Range = Range.substr(Range.find_first_of("\n\r"));
- if (Range.empty())
- return NumNewLines;
-
- ++NumNewLines;
-
- // Handle \n\r and \r\n as a single newline.
- if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') &&
- (Range[0] != Range[1]))
- Range = Range.substr(1);
- Range = Range.substr(1);
-
- if (NumNewLines == 1)
- FirstNewLine = Range.begin();
- }
-}
-
-/// Match check string and its "not strings" and/or "dag strings".
-size_t FileCheckString::Check(const SourceMgr &SM, StringRef Buffer,
- bool IsLabelScanMode, size_t &MatchLen,
- StringMap<StringRef> &VariableTable,
- FileCheckRequest &Req,
- std::vector<FileCheckDiag> *Diags) const {
- size_t LastPos = 0;
- std::vector<const FileCheckPattern *> NotStrings;
-
- // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
- // bounds; we have not processed variable definitions within the bounded block
- // yet so cannot handle any final CHECK-DAG yet; this is handled when going
- // over the block again (including the last CHECK-LABEL) in normal mode.
- if (!IsLabelScanMode) {
- // Match "dag strings" (with mixed "not strings" if any).
- LastPos = CheckDag(SM, Buffer, NotStrings, VariableTable, Req, Diags);
- if (LastPos == StringRef::npos)
- return StringRef::npos;
- }
-
- // Match itself from the last position after matching CHECK-DAG.
- size_t LastMatchEnd = LastPos;
- size_t FirstMatchPos = 0;
- // Go match the pattern Count times. Majority of patterns only match with
- // count 1 though.
- assert(Pat.getCount() != 0 && "pattern count can not be zero");
- for (int i = 1; i <= Pat.getCount(); i++) {
- StringRef MatchBuffer = Buffer.substr(LastMatchEnd);
- size_t CurrentMatchLen;
- // get a match at current start point
- size_t MatchPos = Pat.Match(MatchBuffer, CurrentMatchLen, VariableTable);
- if (i == 1)
- FirstMatchPos = LastPos + MatchPos;
-
- // report
- if (MatchPos == StringRef::npos) {
- PrintNoMatch(true, SM, *this, i, MatchBuffer, VariableTable,
- Req.VerboseVerbose, Diags);
- return StringRef::npos;
- }
- PrintMatch(true, SM, *this, i, MatchBuffer, VariableTable, MatchPos,
- CurrentMatchLen, Req, Diags);
-
- // move start point after the match
- LastMatchEnd += MatchPos + CurrentMatchLen;
- }
- // Full match len counts from first match pos.
- MatchLen = LastMatchEnd - FirstMatchPos;
-
- // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
- // or CHECK-NOT
- if (!IsLabelScanMode) {
- size_t MatchPos = FirstMatchPos - LastPos;
- StringRef MatchBuffer = Buffer.substr(LastPos);
- StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos);
-
- // If this check is a "CHECK-NEXT", verify that the previous match was on
- // the previous line (i.e. that there is one newline between them).
- if (CheckNext(SM, SkippedRegion)) {
- ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc,
- Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
- Diags, Req.Verbose);
- return StringRef::npos;
- }
-
- // If this check is a "CHECK-SAME", verify that the previous match was on
- // the same line (i.e. that there is no newline between them).
- if (CheckSame(SM, SkippedRegion)) {
- ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc,
- Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen,
- Diags, Req.Verbose);
- return StringRef::npos;
- }
-
- // If this match had "not strings", verify that they don't exist in the
- // skipped region.
- if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable, Req, Diags))
- return StringRef::npos;
- }
-
- return FirstMatchPos;
-}
-
-/// Verify there is a single line in the given buffer.
-bool FileCheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
- if (Pat.getCheckTy() != Check::CheckNext &&
- Pat.getCheckTy() != Check::CheckEmpty)
- return false;
-
- Twine CheckName =
- Prefix +
- Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT");
-
- // Count the number of newlines between the previous match and this one.
- assert(Buffer.data() !=
- SM.getMemoryBuffer(SM.FindBufferContainingLoc(
- SMLoc::getFromPointer(Buffer.data())))
- ->getBufferStart() &&
- "CHECK-NEXT and CHECK-EMPTY can't be the first check in a file");
-
- const char *FirstNewLine = nullptr;
- unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
-
- if (NumNewLines == 0) {
- SM.PrintMessage(Loc, SourceMgr::DK_Error,
- CheckName + ": is on the same line as previous match");
- SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
- "'next' match was here");
- SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
- "previous match ended here");
- return true;
- }
-
- if (NumNewLines != 1) {
- SM.PrintMessage(Loc, SourceMgr::DK_Error,
- CheckName +
- ": is not on the line after the previous match");
- SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
- "'next' match was here");
- SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
- "previous match ended here");
- SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note,
- "non-matching line after previous match is here");
- return true;
- }
-
- return false;
-}
-
-/// Verify there is no newline in the given buffer.
-bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
- if (Pat.getCheckTy() != Check::CheckSame)
- return false;
-
- // Count the number of newlines between the previous match and this one.
- assert(Buffer.data() !=
- SM.getMemoryBuffer(SM.FindBufferContainingLoc(
- SMLoc::getFromPointer(Buffer.data())))
- ->getBufferStart() &&
- "CHECK-SAME can't be the first check in a file");
-
- const char *FirstNewLine = nullptr;
- unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
-
- if (NumNewLines != 0) {
- SM.PrintMessage(Loc, SourceMgr::DK_Error,
- Prefix +
- "-SAME: is not on the same line as the previous match");
- SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
- "'next' match was here");
- SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
- "previous match ended here");
- return true;
- }
-
- return false;
-}
-
-/// Verify there's no "not strings" in the given buffer.
-bool FileCheckString::CheckNot(
- const SourceMgr &SM, StringRef Buffer,
- const std::vector<const FileCheckPattern *> &NotStrings,
- StringMap<StringRef> &VariableTable, const FileCheckRequest &Req,
- std::vector<FileCheckDiag> *Diags) const {
- for (const FileCheckPattern *Pat : NotStrings) {
- assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
-
- size_t MatchLen = 0;
- size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable);
-
- if (Pos == StringRef::npos) {
- PrintNoMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer,
- VariableTable, Req.VerboseVerbose, Diags);
- continue;
- }
-
- PrintMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer, VariableTable,
- Pos, MatchLen, Req, Diags);
-
- return true;
- }
-
- return false;
-}
-
-/// Match "dag strings" and their mixed "not strings".
-size_t
-FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
- std::vector<const FileCheckPattern *> &NotStrings,
- StringMap<StringRef> &VariableTable,
- const FileCheckRequest &Req,
- std::vector<FileCheckDiag> *Diags) const {
- if (DagNotStrings.empty())
- return 0;
-
- // The start of the search range.
- size_t StartPos = 0;
-
- struct MatchRange {
- size_t Pos;
- size_t End;
- };
- // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
- // ranges are erased from this list once they are no longer in the search
- // range.
- std::list<MatchRange> MatchRanges;
-
- // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
- // group, so we don't use a range-based for loop here.
- for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end();
- PatItr != PatEnd; ++PatItr) {
- const FileCheckPattern &Pat = *PatItr;
- assert((Pat.getCheckTy() == Check::CheckDAG ||
- Pat.getCheckTy() == Check::CheckNot) &&
- "Invalid CHECK-DAG or CHECK-NOT!");
-
- if (Pat.getCheckTy() == Check::CheckNot) {
- NotStrings.push_back(&Pat);
- continue;
- }
-
- assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
-
- // CHECK-DAG always matches from the start.
- size_t MatchLen = 0, MatchPos = StartPos;
-
- // Search for a match that doesn't overlap a previous match in this
- // CHECK-DAG group.
- for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) {
- StringRef MatchBuffer = Buffer.substr(MatchPos);
- size_t MatchPosBuf = Pat.Match(MatchBuffer, MatchLen, VariableTable);
- // With a group of CHECK-DAGs, a single mismatching means the match on
- // that group of CHECK-DAGs fails immediately.
- if (MatchPosBuf == StringRef::npos) {
- PrintNoMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, MatchBuffer,
- VariableTable, Req.VerboseVerbose, Diags);
- return StringRef::npos;
- }
- // Re-calc it as the offset relative to the start of the original string.
- MatchPos += MatchPosBuf;
- if (Req.VerboseVerbose)
- PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer,
- VariableTable, MatchPos, MatchLen, Req, Diags);
- MatchRange M{MatchPos, MatchPos + MatchLen};
- if (Req.AllowDeprecatedDagOverlap) {
- // We don't need to track all matches in this mode, so we just maintain
- // one match range that encompasses the current CHECK-DAG group's
- // matches.
- if (MatchRanges.empty())
- MatchRanges.insert(MatchRanges.end(), M);
- else {
- auto Block = MatchRanges.begin();
- Block->Pos = std::min(Block->Pos, M.Pos);
- Block->End = std::max(Block->End, M.End);
- }
- break;
- }
- // Iterate previous matches until overlapping match or insertion point.
- bool Overlap = false;
- for (; MI != ME; ++MI) {
- if (M.Pos < MI->End) {
- // !Overlap => New match has no overlap and is before this old match.
- // Overlap => New match overlaps this old match.
- Overlap = MI->Pos < M.End;
- break;
- }
- }
- if (!Overlap) {
- // Insert non-overlapping match into list.
- MatchRanges.insert(MI, M);
- break;
- }
- if (Req.VerboseVerbose) {
- SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos);
- SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End);
- SMRange OldRange(OldStart, OldEnd);
- SM.PrintMessage(OldStart, SourceMgr::DK_Note,
- "match discarded, overlaps earlier DAG match here",
- {OldRange});
- if (Diags)
- Diags->rbegin()->MatchTy = FileCheckDiag::MatchFoundButDiscarded;
- }
- MatchPos = MI->End;
- }
- if (!Req.VerboseVerbose)
- PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, VariableTable,
- MatchPos, MatchLen, Req, Diags);
-
- // Handle the end of a CHECK-DAG group.
- if (std::next(PatItr) == PatEnd ||
- std::next(PatItr)->getCheckTy() == Check::CheckNot) {
- if (!NotStrings.empty()) {
- // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
- // CHECK-DAG, verify that there are no 'not' strings occurred in that
- // region.
- StringRef SkippedRegion =
- Buffer.slice(StartPos, MatchRanges.begin()->Pos);
- if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable, Req, Diags))
- return StringRef::npos;
- // Clear "not strings".
- NotStrings.clear();
- }
- // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
- // end of this CHECK-DAG group's match range.
- StartPos = MatchRanges.rbegin()->End;
- // Don't waste time checking for (impossible) overlaps before that.
- MatchRanges.clear();
- }
- }
-
- return StartPos;
-}
-
-// A check prefix must contain only alphanumeric, hyphens and underscores.
-static bool ValidateCheckPrefix(StringRef CheckPrefix) {
- Regex Validator("^[a-zA-Z0-9_-]*$");
- return Validator.match(CheckPrefix);
-}
-
-bool llvm::FileCheck::ValidateCheckPrefixes() {
- StringSet<> PrefixSet;
-
- for (StringRef Prefix : Req.CheckPrefixes) {
- // Reject empty prefixes.
- if (Prefix == "")
- return false;
-
- if (!PrefixSet.insert(Prefix).second)
- return false;
-
- if (!ValidateCheckPrefix(Prefix))
- return false;
- }
-
- return true;
-}
-
-// Combines the check prefixes into a single regex so that we can efficiently
-// scan for any of the set.
-//
-// The semantics are that the longest-match wins which matches our regex
-// library.
-Regex llvm::FileCheck::buildCheckPrefixRegex() {
- // I don't think there's a way to specify an initial value for cl::list,
- // so if nothing was specified, add the default
- if (Req.CheckPrefixes.empty())
- Req.CheckPrefixes.push_back("CHECK");
-
- // We already validated the contents of CheckPrefixes so just concatenate
- // them as alternatives.
- SmallString<32> PrefixRegexStr;
- for (StringRef Prefix : Req.CheckPrefixes) {
- if (Prefix != Req.CheckPrefixes.front())
- PrefixRegexStr.push_back('|');
-
- PrefixRegexStr.append(Prefix);
- }
-
- return Regex(PrefixRegexStr);
-}
-
-// Remove local variables from \p VariableTable. Global variables
-// (start with '$') are preserved.
-static void ClearLocalVars(StringMap<StringRef> &VariableTable) {
- SmallVector<StringRef, 16> LocalVars;
- for (const auto &Var : VariableTable)
- if (Var.first()[0] != '$')
- LocalVars.push_back(Var.first());
-
- for (const auto &Var : LocalVars)
- VariableTable.erase(Var);
-}
-
-/// Check the input to FileCheck provided in the \p Buffer against the \p
-/// CheckStrings read from the check file.
-///
-/// Returns false if the input fails to satisfy the checks.
-bool llvm::FileCheck::CheckInput(SourceMgr &SM, StringRef Buffer,
- ArrayRef<FileCheckString> CheckStrings,
- std::vector<FileCheckDiag> *Diags) {
- bool ChecksFailed = false;
-
- /// VariableTable - This holds all the current filecheck variables.
- StringMap<StringRef> VariableTable;
-
- for (const auto& Def : Req.GlobalDefines)
- VariableTable.insert(StringRef(Def).split('='));
-
- unsigned i = 0, j = 0, e = CheckStrings.size();
- while (true) {
- StringRef CheckRegion;
- if (j == e) {
- CheckRegion = Buffer;
- } else {
- const FileCheckString &CheckLabelStr = CheckStrings[j];
- if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
- ++j;
- continue;
- }
-
- // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
- size_t MatchLabelLen = 0;
- size_t MatchLabelPos = CheckLabelStr.Check(
- SM, Buffer, true, MatchLabelLen, VariableTable, Req, Diags);
- if (MatchLabelPos == StringRef::npos)
- // Immediately bail of CHECK-LABEL fails, nothing else we can do.
- return false;
-
- CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen);
- Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen);
- ++j;
- }
-
- if (Req.EnableVarScope)
- ClearLocalVars(VariableTable);
-
- for (; i != j; ++i) {
- const FileCheckString &CheckStr = CheckStrings[i];
-
- // Check each string within the scanned region, including a second check
- // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
- size_t MatchLen = 0;
- size_t MatchPos = CheckStr.Check(SM, CheckRegion, false, MatchLen,
- VariableTable, Req, Diags);
-
- if (MatchPos == StringRef::npos) {
- ChecksFailed = true;
- i = j;
- break;
- }
-
- CheckRegion = CheckRegion.substr(MatchPos + MatchLen);
- }
-
- if (j == e)
- break;
- }
-
- // Success if no checks failed.
- return !ChecksFailed;
-}
diff --git a/gnu/llvm/lib/Support/FileOutputBuffer.cpp b/gnu/llvm/lib/Support/FileOutputBuffer.cpp
deleted file mode 100644
index b8223126227..00000000000
--- a/gnu/llvm/lib/Support/FileOutputBuffer.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-//===- FileOutputBuffer.cpp - File Output Buffer ----------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Utility for creating a in-memory buffer that will be written to a file.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Memory.h"
-#include "llvm/Support/Path.h"
-#include <system_error>
-
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-#include <unistd.h>
-#else
-#include <io.h>
-#endif
-
-using namespace llvm;
-using namespace llvm::sys;
-
-namespace {
-// A FileOutputBuffer which creates a temporary file in the same directory
-// as the final output file. The final output file is atomically replaced
-// with the temporary file on commit().
-class OnDiskBuffer : public FileOutputBuffer {
-public:
- OnDiskBuffer(StringRef Path, fs::TempFile Temp,
- std::unique_ptr<fs::mapped_file_region> Buf)
- : FileOutputBuffer(Path), Buffer(std::move(Buf)), Temp(std::move(Temp)) {}
-
- uint8_t *getBufferStart() const override { return (uint8_t *)Buffer->data(); }
-
- uint8_t *getBufferEnd() const override {
- return (uint8_t *)Buffer->data() + Buffer->size();
- }
-
- size_t getBufferSize() const override { return Buffer->size(); }
-
- Error commit() override {
- // Unmap buffer, letting OS flush dirty pages to file on disk.
- Buffer.reset();
-
- // Atomically replace the existing file with the new one.
- return Temp.keep(FinalPath);
- }
-
- ~OnDiskBuffer() override {
- // Close the mapping before deleting the temp file, so that the removal
- // succeeds.
- Buffer.reset();
- consumeError(Temp.discard());
- }
-
- void discard() override {
- // Delete the temp file if it still was open, but keeping the mapping
- // active.
- consumeError(Temp.discard());
- }
-
-private:
- std::unique_ptr<fs::mapped_file_region> Buffer;
- fs::TempFile Temp;
-};
-
-// A FileOutputBuffer which keeps data in memory and writes to the final
-// output file on commit(). This is used only when we cannot use OnDiskBuffer.
-class InMemoryBuffer : public FileOutputBuffer {
-public:
- InMemoryBuffer(StringRef Path, MemoryBlock Buf, unsigned Mode)
- : FileOutputBuffer(Path), Buffer(Buf), Mode(Mode) {}
-
- uint8_t *getBufferStart() const override { return (uint8_t *)Buffer.base(); }
-
- uint8_t *getBufferEnd() const override {
- return (uint8_t *)Buffer.base() + Buffer.size();
- }
-
- size_t getBufferSize() const override { return Buffer.size(); }
-
- Error commit() override {
- using namespace sys::fs;
- int FD;
- std::error_code EC;
- if (auto EC =
- openFileForWrite(FinalPath, FD, CD_CreateAlways, OF_None, Mode))
- return errorCodeToError(EC);
- raw_fd_ostream OS(FD, /*shouldClose=*/true, /*unbuffered=*/true);
- OS << StringRef((const char *)Buffer.base(), Buffer.size());
- return Error::success();
- }
-
-private:
- OwningMemoryBlock Buffer;
- unsigned Mode;
-};
-} // namespace
-
-static Expected<std::unique_ptr<InMemoryBuffer>>
-createInMemoryBuffer(StringRef Path, size_t Size, unsigned Mode) {
- std::error_code EC;
- MemoryBlock MB = Memory::allocateMappedMemory(
- Size, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
- if (EC)
- return errorCodeToError(EC);
- return llvm::make_unique<InMemoryBuffer>(Path, MB, Mode);
-}
-
-static Expected<std::unique_ptr<OnDiskBuffer>>
-createOnDiskBuffer(StringRef Path, size_t Size, bool InitExisting,
- unsigned Mode) {
- Expected<fs::TempFile> FileOrErr =
- fs::TempFile::create(Path + ".tmp%%%%%%%", Mode);
- if (!FileOrErr)
- return FileOrErr.takeError();
- fs::TempFile File = std::move(*FileOrErr);
-
- if (InitExisting) {
- if (auto EC = sys::fs::copy_file(Path, File.FD))
- return errorCodeToError(EC);
- } else {
-#ifndef _WIN32
- // On Windows, CreateFileMapping (the mmap function on Windows)
- // automatically extends the underlying file. We don't need to
- // extend the file beforehand. _chsize (ftruncate on Windows) is
- // pretty slow just like it writes specified amount of bytes,
- // so we should avoid calling that function.
- if (auto EC = fs::resize_file(File.FD, Size)) {
- consumeError(File.discard());
- return errorCodeToError(EC);
- }
-#endif
- }
-
- // Mmap it.
- std::error_code EC;
- auto MappedFile = llvm::make_unique<fs::mapped_file_region>(
- File.FD, fs::mapped_file_region::readwrite, Size, 0, EC);
- if (EC) {
- consumeError(File.discard());
- return errorCodeToError(EC);
- }
- return llvm::make_unique<OnDiskBuffer>(Path, std::move(File),
- std::move(MappedFile));
-}
-
-// Create an instance of FileOutputBuffer.
-Expected<std::unique_ptr<FileOutputBuffer>>
-FileOutputBuffer::create(StringRef Path, size_t Size, unsigned Flags) {
- unsigned Mode = fs::all_read | fs::all_write;
- if (Flags & F_executable)
- Mode |= fs::all_exe;
-
- fs::file_status Stat;
- fs::status(Path, Stat);
-
- if ((Flags & F_modify) && Size == size_t(-1)) {
- if (Stat.type() == fs::file_type::regular_file)
- Size = Stat.getSize();
- else if (Stat.type() == fs::file_type::file_not_found)
- return errorCodeToError(errc::no_such_file_or_directory);
- else
- return errorCodeToError(errc::invalid_argument);
- }
-
- // Usually, we want to create OnDiskBuffer to create a temporary file in
- // the same directory as the destination file and atomically replaces it
- // by rename(2).
- //
- // However, if the destination file is a special file, we don't want to
- // use rename (e.g. we don't want to replace /dev/null with a regular
- // file.) If that's the case, we create an in-memory buffer, open the
- // destination file and write to it on commit().
- switch (Stat.type()) {
- case fs::file_type::directory_file:
- return errorCodeToError(errc::is_a_directory);
- case fs::file_type::regular_file:
- case fs::file_type::file_not_found:
- case fs::file_type::status_error:
- return createOnDiskBuffer(Path, Size, !!(Flags & F_modify), Mode);
- default:
- return createInMemoryBuffer(Path, Size, Mode);
- }
-}
diff --git a/gnu/llvm/lib/Support/FileUtilities.cpp b/gnu/llvm/lib/Support/FileUtilities.cpp
deleted file mode 100644
index 39dbefff5b7..00000000000
--- a/gnu/llvm/lib/Support/FileUtilities.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-//===- Support/FileUtilities.cpp - File System Utilities ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a family of utility functions which are useful for doing
-// various things with files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cctype>
-#include <cmath>
-#include <cstdint>
-#include <cstdlib>
-#include <cstring>
-#include <memory>
-#include <system_error>
-
-using namespace llvm;
-
-static bool isSignedChar(char C) {
- return (C == '+' || C == '-');
-}
-
-static bool isExponentChar(char C) {
- switch (C) {
- case 'D': // Strange exponential notation.
- case 'd': // Strange exponential notation.
- case 'e':
- case 'E': return true;
- default: return false;
- }
-}
-
-static bool isNumberChar(char C) {
- switch (C) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case '.': return true;
- default: return isSignedChar(C) || isExponentChar(C);
- }
-}
-
-static const char *BackupNumber(const char *Pos, const char *FirstChar) {
- // If we didn't stop in the middle of a number, don't backup.
- if (!isNumberChar(*Pos)) return Pos;
-
- // Otherwise, return to the start of the number.
- bool HasPeriod = false;
- while (Pos > FirstChar && isNumberChar(Pos[-1])) {
- // Backup over at most one period.
- if (Pos[-1] == '.') {
- if (HasPeriod)
- break;
- HasPeriod = true;
- }
-
- --Pos;
- if (Pos > FirstChar && isSignedChar(Pos[0]) && !isExponentChar(Pos[-1]))
- break;
- }
- return Pos;
-}
-
-/// EndOfNumber - Return the first character that is not part of the specified
-/// number. This assumes that the buffer is null terminated, so it won't fall
-/// off the end.
-static const char *EndOfNumber(const char *Pos) {
- while (isNumberChar(*Pos))
- ++Pos;
- return Pos;
-}
-
-/// CompareNumbers - compare two numbers, returning true if they are different.
-static bool CompareNumbers(const char *&F1P, const char *&F2P,
- const char *F1End, const char *F2End,
- double AbsTolerance, double RelTolerance,
- std::string *ErrorMsg) {
- const char *F1NumEnd, *F2NumEnd;
- double V1 = 0.0, V2 = 0.0;
-
- // If one of the positions is at a space and the other isn't, chomp up 'til
- // the end of the space.
- while (isspace(static_cast<unsigned char>(*F1P)) && F1P != F1End)
- ++F1P;
- while (isspace(static_cast<unsigned char>(*F2P)) && F2P != F2End)
- ++F2P;
-
- // If we stop on numbers, compare their difference.
- if (!isNumberChar(*F1P) || !isNumberChar(*F2P)) {
- // The diff failed.
- F1NumEnd = F1P;
- F2NumEnd = F2P;
- } else {
- // Note that some ugliness is built into this to permit support for numbers
- // that use "D" or "d" as their exponential marker, e.g. "1.234D45". This
- // occurs in 200.sixtrack in spec2k.
- V1 = strtod(F1P, const_cast<char**>(&F1NumEnd));
- V2 = strtod(F2P, const_cast<char**>(&F2NumEnd));
-
- if (*F1NumEnd == 'D' || *F1NumEnd == 'd') {
- // Copy string into tmp buffer to replace the 'D' with an 'e'.
- SmallString<200> StrTmp(F1P, EndOfNumber(F1NumEnd)+1);
- // Strange exponential notation!
- StrTmp[static_cast<unsigned>(F1NumEnd-F1P)] = 'e';
-
- V1 = strtod(&StrTmp[0], const_cast<char**>(&F1NumEnd));
- F1NumEnd = F1P + (F1NumEnd-&StrTmp[0]);
- }
-
- if (*F2NumEnd == 'D' || *F2NumEnd == 'd') {
- // Copy string into tmp buffer to replace the 'D' with an 'e'.
- SmallString<200> StrTmp(F2P, EndOfNumber(F2NumEnd)+1);
- // Strange exponential notation!
- StrTmp[static_cast<unsigned>(F2NumEnd-F2P)] = 'e';
-
- V2 = strtod(&StrTmp[0], const_cast<char**>(&F2NumEnd));
- F2NumEnd = F2P + (F2NumEnd-&StrTmp[0]);
- }
- }
-
- if (F1NumEnd == F1P || F2NumEnd == F2P) {
- if (ErrorMsg) {
- *ErrorMsg = "FP Comparison failed, not a numeric difference between '";
- *ErrorMsg += F1P[0];
- *ErrorMsg += "' and '";
- *ErrorMsg += F2P[0];
- *ErrorMsg += "'";
- }
- return true;
- }
-
- // Check to see if these are inside the absolute tolerance
- if (AbsTolerance < std::abs(V1-V2)) {
- // Nope, check the relative tolerance...
- double Diff;
- if (V2)
- Diff = std::abs(V1/V2 - 1.0);
- else if (V1)
- Diff = std::abs(V2/V1 - 1.0);
- else
- Diff = 0; // Both zero.
- if (Diff > RelTolerance) {
- if (ErrorMsg) {
- raw_string_ostream(*ErrorMsg)
- << "Compared: " << V1 << " and " << V2 << '\n'
- << "abs. diff = " << std::abs(V1-V2) << " rel.diff = " << Diff << '\n'
- << "Out of tolerance: rel/abs: " << RelTolerance << '/'
- << AbsTolerance;
- }
- return true;
- }
- }
-
- // Otherwise, advance our read pointers to the end of the numbers.
- F1P = F1NumEnd; F2P = F2NumEnd;
- return false;
-}
-
-/// DiffFilesWithTolerance - Compare the two files specified, returning 0 if the
-/// files match, 1 if they are different, and 2 if there is a file error. This
-/// function differs from DiffFiles in that you can specify an absolete and
-/// relative FP error that is allowed to exist. If you specify a string to fill
-/// in for the error option, it will set the string to an error message if an
-/// error occurs, allowing the caller to distinguish between a failed diff and a
-/// file system error.
-///
-int llvm::DiffFilesWithTolerance(StringRef NameA,
- StringRef NameB,
- double AbsTol, double RelTol,
- std::string *Error) {
- // Now its safe to mmap the files into memory because both files
- // have a non-zero size.
- ErrorOr<std::unique_ptr<MemoryBuffer>> F1OrErr = MemoryBuffer::getFile(NameA);
- if (std::error_code EC = F1OrErr.getError()) {
- if (Error)
- *Error = EC.message();
- return 2;
- }
- MemoryBuffer &F1 = *F1OrErr.get();
-
- ErrorOr<std::unique_ptr<MemoryBuffer>> F2OrErr = MemoryBuffer::getFile(NameB);
- if (std::error_code EC = F2OrErr.getError()) {
- if (Error)
- *Error = EC.message();
- return 2;
- }
- MemoryBuffer &F2 = *F2OrErr.get();
-
- // Okay, now that we opened the files, scan them for the first difference.
- const char *File1Start = F1.getBufferStart();
- const char *File2Start = F2.getBufferStart();
- const char *File1End = F1.getBufferEnd();
- const char *File2End = F2.getBufferEnd();
- const char *F1P = File1Start;
- const char *F2P = File2Start;
- uint64_t A_size = F1.getBufferSize();
- uint64_t B_size = F2.getBufferSize();
-
- // Are the buffers identical? Common case: Handle this efficiently.
- if (A_size == B_size &&
- std::memcmp(File1Start, File2Start, A_size) == 0)
- return 0;
-
- // Otherwise, we are done a tolerances are set.
- if (AbsTol == 0 && RelTol == 0) {
- if (Error)
- *Error = "Files differ without tolerance allowance";
- return 1; // Files different!
- }
-
- bool CompareFailed = false;
- while (true) {
- // Scan for the end of file or next difference.
- while (F1P < File1End && F2P < File2End && *F1P == *F2P) {
- ++F1P;
- ++F2P;
- }
-
- if (F1P >= File1End || F2P >= File2End) break;
-
- // Okay, we must have found a difference. Backup to the start of the
- // current number each stream is at so that we can compare from the
- // beginning.
- F1P = BackupNumber(F1P, File1Start);
- F2P = BackupNumber(F2P, File2Start);
-
- // Now that we are at the start of the numbers, compare them, exiting if
- // they don't match.
- if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error)) {
- CompareFailed = true;
- break;
- }
- }
-
- // Okay, we reached the end of file. If both files are at the end, we
- // succeeded.
- bool F1AtEnd = F1P >= File1End;
- bool F2AtEnd = F2P >= File2End;
- if (!CompareFailed && (!F1AtEnd || !F2AtEnd)) {
- // Else, we might have run off the end due to a number: backup and retry.
- if (F1AtEnd && isNumberChar(F1P[-1])) --F1P;
- if (F2AtEnd && isNumberChar(F2P[-1])) --F2P;
- F1P = BackupNumber(F1P, File1Start);
- F2P = BackupNumber(F2P, File2Start);
-
- // Now that we are at the start of the numbers, compare them, exiting if
- // they don't match.
- if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error))
- CompareFailed = true;
-
- // If we found the end, we succeeded.
- if (F1P < File1End || F2P < File2End)
- CompareFailed = true;
- }
-
- return CompareFailed;
-}
diff --git a/gnu/llvm/lib/Support/FoldingSet.cpp b/gnu/llvm/lib/Support/FoldingSet.cpp
deleted file mode 100644
index ee69a64ac97..00000000000
--- a/gnu/llvm/lib/Support/FoldingSet.cpp
+++ /dev/null
@@ -1,464 +0,0 @@
-//===-- Support/FoldingSet.cpp - Uniquing Hash Set --------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a hash set that can be used to remove duplication of
-// nodes in a graph.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/MathExtras.h"
-#include <cassert>
-#include <cstring>
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// FoldingSetNodeIDRef Implementation
-
-/// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
-/// used to lookup the node in the FoldingSetBase.
-unsigned FoldingSetNodeIDRef::ComputeHash() const {
- return static_cast<unsigned>(hash_combine_range(Data, Data+Size));
-}
-
-bool FoldingSetNodeIDRef::operator==(FoldingSetNodeIDRef RHS) const {
- if (Size != RHS.Size) return false;
- return memcmp(Data, RHS.Data, Size*sizeof(*Data)) == 0;
-}
-
-/// Used to compare the "ordering" of two nodes as defined by the
-/// profiled bits and their ordering defined by memcmp().
-bool FoldingSetNodeIDRef::operator<(FoldingSetNodeIDRef RHS) const {
- if (Size != RHS.Size)
- return Size < RHS.Size;
- return memcmp(Data, RHS.Data, Size*sizeof(*Data)) < 0;
-}
-
-//===----------------------------------------------------------------------===//
-// FoldingSetNodeID Implementation
-
-/// Add* - Add various data types to Bit data.
-///
-void FoldingSetNodeID::AddPointer(const void *Ptr) {
- // Note: this adds pointers to the hash using sizes and endianness that
- // depend on the host. It doesn't matter, however, because hashing on
- // pointer values is inherently unstable. Nothing should depend on the
- // ordering of nodes in the folding set.
- static_assert(sizeof(uintptr_t) <= sizeof(unsigned long long),
- "unexpected pointer size");
- AddInteger(reinterpret_cast<uintptr_t>(Ptr));
-}
-void FoldingSetNodeID::AddInteger(signed I) {
- Bits.push_back(I);
-}
-void FoldingSetNodeID::AddInteger(unsigned I) {
- Bits.push_back(I);
-}
-void FoldingSetNodeID::AddInteger(long I) {
- AddInteger((unsigned long)I);
-}
-void FoldingSetNodeID::AddInteger(unsigned long I) {
- if (sizeof(long) == sizeof(int))
- AddInteger(unsigned(I));
- else if (sizeof(long) == sizeof(long long)) {
- AddInteger((unsigned long long)I);
- } else {
- llvm_unreachable("unexpected sizeof(long)");
- }
-}
-void FoldingSetNodeID::AddInteger(long long I) {
- AddInteger((unsigned long long)I);
-}
-void FoldingSetNodeID::AddInteger(unsigned long long I) {
- AddInteger(unsigned(I));
- AddInteger(unsigned(I >> 32));
-}
-
-void FoldingSetNodeID::AddString(StringRef String) {
- unsigned Size = String.size();
- Bits.push_back(Size);
- if (!Size) return;
-
- unsigned Units = Size / 4;
- unsigned Pos = 0;
- const unsigned *Base = (const unsigned*) String.data();
-
- // If the string is aligned do a bulk transfer.
- if (!((intptr_t)Base & 3)) {
- Bits.append(Base, Base + Units);
- Pos = (Units + 1) * 4;
- } else {
- // Otherwise do it the hard way.
- // To be compatible with above bulk transfer, we need to take endianness
- // into account.
- static_assert(sys::IsBigEndianHost || sys::IsLittleEndianHost,
- "Unexpected host endianness");
- if (sys::IsBigEndianHost) {
- for (Pos += 4; Pos <= Size; Pos += 4) {
- unsigned V = ((unsigned char)String[Pos - 4] << 24) |
- ((unsigned char)String[Pos - 3] << 16) |
- ((unsigned char)String[Pos - 2] << 8) |
- (unsigned char)String[Pos - 1];
- Bits.push_back(V);
- }
- } else { // Little-endian host
- for (Pos += 4; Pos <= Size; Pos += 4) {
- unsigned V = ((unsigned char)String[Pos - 1] << 24) |
- ((unsigned char)String[Pos - 2] << 16) |
- ((unsigned char)String[Pos - 3] << 8) |
- (unsigned char)String[Pos - 4];
- Bits.push_back(V);
- }
- }
- }
-
- // With the leftover bits.
- unsigned V = 0;
- // Pos will have overshot size by 4 - #bytes left over.
- // No need to take endianness into account here - this is always executed.
- switch (Pos - Size) {
- case 1: V = (V << 8) | (unsigned char)String[Size - 3]; LLVM_FALLTHROUGH;
- case 2: V = (V << 8) | (unsigned char)String[Size - 2]; LLVM_FALLTHROUGH;
- case 3: V = (V << 8) | (unsigned char)String[Size - 1]; break;
- default: return; // Nothing left.
- }
-
- Bits.push_back(V);
-}
-
-// AddNodeID - Adds the Bit data of another ID to *this.
-void FoldingSetNodeID::AddNodeID(const FoldingSetNodeID &ID) {
- Bits.append(ID.Bits.begin(), ID.Bits.end());
-}
-
-/// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to
-/// lookup the node in the FoldingSetBase.
-unsigned FoldingSetNodeID::ComputeHash() const {
- return FoldingSetNodeIDRef(Bits.data(), Bits.size()).ComputeHash();
-}
-
-/// operator== - Used to compare two nodes to each other.
-///
-bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS) const {
- return *this == FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size());
-}
-
-/// operator== - Used to compare two nodes to each other.
-///
-bool FoldingSetNodeID::operator==(FoldingSetNodeIDRef RHS) const {
- return FoldingSetNodeIDRef(Bits.data(), Bits.size()) == RHS;
-}
-
-/// Used to compare the "ordering" of two nodes as defined by the
-/// profiled bits and their ordering defined by memcmp().
-bool FoldingSetNodeID::operator<(const FoldingSetNodeID &RHS) const {
- return *this < FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size());
-}
-
-bool FoldingSetNodeID::operator<(FoldingSetNodeIDRef RHS) const {
- return FoldingSetNodeIDRef(Bits.data(), Bits.size()) < RHS;
-}
-
-/// Intern - Copy this node's data to a memory region allocated from the
-/// given allocator and return a FoldingSetNodeIDRef describing the
-/// interned data.
-FoldingSetNodeIDRef
-FoldingSetNodeID::Intern(BumpPtrAllocator &Allocator) const {
- unsigned *New = Allocator.Allocate<unsigned>(Bits.size());
- std::uninitialized_copy(Bits.begin(), Bits.end(), New);
- return FoldingSetNodeIDRef(New, Bits.size());
-}
-
-//===----------------------------------------------------------------------===//
-/// Helper functions for FoldingSetBase.
-
-/// GetNextPtr - In order to save space, each bucket is a
-/// singly-linked-list. In order to make deletion more efficient, we make
-/// the list circular, so we can delete a node without computing its hash.
-/// The problem with this is that the start of the hash buckets are not
-/// Nodes. If NextInBucketPtr is a bucket pointer, this method returns null:
-/// use GetBucketPtr when this happens.
-static FoldingSetBase::Node *GetNextPtr(void *NextInBucketPtr) {
- // The low bit is set if this is the pointer back to the bucket.
- if (reinterpret_cast<intptr_t>(NextInBucketPtr) & 1)
- return nullptr;
-
- return static_cast<FoldingSetBase::Node*>(NextInBucketPtr);
-}
-
-
-/// testing.
-static void **GetBucketPtr(void *NextInBucketPtr) {
- intptr_t Ptr = reinterpret_cast<intptr_t>(NextInBucketPtr);
- assert((Ptr & 1) && "Not a bucket pointer");
- return reinterpret_cast<void**>(Ptr & ~intptr_t(1));
-}
-
-/// GetBucketFor - Hash the specified node ID and return the hash bucket for
-/// the specified ID.
-static void **GetBucketFor(unsigned Hash, void **Buckets, unsigned NumBuckets) {
- // NumBuckets is always a power of 2.
- unsigned BucketNum = Hash & (NumBuckets-1);
- return Buckets + BucketNum;
-}
-
-/// AllocateBuckets - Allocated initialized bucket memory.
-static void **AllocateBuckets(unsigned NumBuckets) {
- void **Buckets = static_cast<void**>(safe_calloc(NumBuckets + 1,
- sizeof(void*)));
- // Set the very last bucket to be a non-null "pointer".
- Buckets[NumBuckets] = reinterpret_cast<void*>(-1);
- return Buckets;
-}
-
-//===----------------------------------------------------------------------===//
-// FoldingSetBase Implementation
-
-void FoldingSetBase::anchor() {}
-
-FoldingSetBase::FoldingSetBase(unsigned Log2InitSize) {
- assert(5 < Log2InitSize && Log2InitSize < 32 &&
- "Initial hash table size out of range");
- NumBuckets = 1 << Log2InitSize;
- Buckets = AllocateBuckets(NumBuckets);
- NumNodes = 0;
-}
-
-FoldingSetBase::FoldingSetBase(FoldingSetBase &&Arg)
- : Buckets(Arg.Buckets), NumBuckets(Arg.NumBuckets), NumNodes(Arg.NumNodes) {
- Arg.Buckets = nullptr;
- Arg.NumBuckets = 0;
- Arg.NumNodes = 0;
-}
-
-FoldingSetBase &FoldingSetBase::operator=(FoldingSetBase &&RHS) {
- free(Buckets); // This may be null if the set is in a moved-from state.
- Buckets = RHS.Buckets;
- NumBuckets = RHS.NumBuckets;
- NumNodes = RHS.NumNodes;
- RHS.Buckets = nullptr;
- RHS.NumBuckets = 0;
- RHS.NumNodes = 0;
- return *this;
-}
-
-FoldingSetBase::~FoldingSetBase() {
- free(Buckets);
-}
-
-void FoldingSetBase::clear() {
- // Set all but the last bucket to null pointers.
- memset(Buckets, 0, NumBuckets*sizeof(void*));
-
- // Set the very last bucket to be a non-null "pointer".
- Buckets[NumBuckets] = reinterpret_cast<void*>(-1);
-
- // Reset the node count to zero.
- NumNodes = 0;
-}
-
-void FoldingSetBase::GrowBucketCount(unsigned NewBucketCount) {
- assert((NewBucketCount > NumBuckets) && "Can't shrink a folding set with GrowBucketCount");
- assert(isPowerOf2_32(NewBucketCount) && "Bad bucket count!");
- void **OldBuckets = Buckets;
- unsigned OldNumBuckets = NumBuckets;
-
- // Clear out new buckets.
- Buckets = AllocateBuckets(NewBucketCount);
- // Set NumBuckets only if allocation of new buckets was successful.
- NumBuckets = NewBucketCount;
- NumNodes = 0;
-
- // Walk the old buckets, rehashing nodes into their new place.
- FoldingSetNodeID TempID;
- for (unsigned i = 0; i != OldNumBuckets; ++i) {
- void *Probe = OldBuckets[i];
- if (!Probe) continue;
- while (Node *NodeInBucket = GetNextPtr(Probe)) {
- // Figure out the next link, remove NodeInBucket from the old link.
- Probe = NodeInBucket->getNextInBucket();
- NodeInBucket->SetNextInBucket(nullptr);
-
- // Insert the node into the new bucket, after recomputing the hash.
- InsertNode(NodeInBucket,
- GetBucketFor(ComputeNodeHash(NodeInBucket, TempID),
- Buckets, NumBuckets));
- TempID.clear();
- }
- }
-
- free(OldBuckets);
-}
-
-/// GrowHashTable - Double the size of the hash table and rehash everything.
-///
-void FoldingSetBase::GrowHashTable() {
- GrowBucketCount(NumBuckets * 2);
-}
-
-void FoldingSetBase::reserve(unsigned EltCount) {
- // This will give us somewhere between EltCount / 2 and
- // EltCount buckets. This puts us in the load factor
- // range of 1.0 - 2.0.
- if(EltCount < capacity())
- return;
- GrowBucketCount(PowerOf2Floor(EltCount));
-}
-
-/// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
-/// return it. If not, return the insertion token that will make insertion
-/// faster.
-FoldingSetBase::Node *
-FoldingSetBase::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
- void *&InsertPos) {
- unsigned IDHash = ID.ComputeHash();
- void **Bucket = GetBucketFor(IDHash, Buckets, NumBuckets);
- void *Probe = *Bucket;
-
- InsertPos = nullptr;
-
- FoldingSetNodeID TempID;
- while (Node *NodeInBucket = GetNextPtr(Probe)) {
- if (NodeEquals(NodeInBucket, ID, IDHash, TempID))
- return NodeInBucket;
- TempID.clear();
-
- Probe = NodeInBucket->getNextInBucket();
- }
-
- // Didn't find the node, return null with the bucket as the InsertPos.
- InsertPos = Bucket;
- return nullptr;
-}
-
-/// InsertNode - Insert the specified node into the folding set, knowing that it
-/// is not already in the map. InsertPos must be obtained from
-/// FindNodeOrInsertPos.
-void FoldingSetBase::InsertNode(Node *N, void *InsertPos) {
- assert(!N->getNextInBucket());
- // Do we need to grow the hashtable?
- if (NumNodes+1 > capacity()) {
- GrowHashTable();
- FoldingSetNodeID TempID;
- InsertPos = GetBucketFor(ComputeNodeHash(N, TempID), Buckets, NumBuckets);
- }
-
- ++NumNodes;
-
- /// The insert position is actually a bucket pointer.
- void **Bucket = static_cast<void**>(InsertPos);
-
- void *Next = *Bucket;
-
- // If this is the first insertion into this bucket, its next pointer will be
- // null. Pretend as if it pointed to itself, setting the low bit to indicate
- // that it is a pointer to the bucket.
- if (!Next)
- Next = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(Bucket)|1);
-
- // Set the node's next pointer, and make the bucket point to the node.
- N->SetNextInBucket(Next);
- *Bucket = N;
-}
-
-/// RemoveNode - Remove a node from the folding set, returning true if one was
-/// removed or false if the node was not in the folding set.
-bool FoldingSetBase::RemoveNode(Node *N) {
- // Because each bucket is a circular list, we don't need to compute N's hash
- // to remove it.
- void *Ptr = N->getNextInBucket();
- if (!Ptr) return false; // Not in folding set.
-
- --NumNodes;
- N->SetNextInBucket(nullptr);
-
- // Remember what N originally pointed to, either a bucket or another node.
- void *NodeNextPtr = Ptr;
-
- // Chase around the list until we find the node (or bucket) which points to N.
- while (true) {
- if (Node *NodeInBucket = GetNextPtr(Ptr)) {
- // Advance pointer.
- Ptr = NodeInBucket->getNextInBucket();
-
- // We found a node that points to N, change it to point to N's next node,
- // removing N from the list.
- if (Ptr == N) {
- NodeInBucket->SetNextInBucket(NodeNextPtr);
- return true;
- }
- } else {
- void **Bucket = GetBucketPtr(Ptr);
- Ptr = *Bucket;
-
- // If we found that the bucket points to N, update the bucket to point to
- // whatever is next.
- if (Ptr == N) {
- *Bucket = NodeNextPtr;
- return true;
- }
- }
- }
-}
-
-/// GetOrInsertNode - If there is an existing simple Node exactly
-/// equal to the specified node, return it. Otherwise, insert 'N' and it
-/// instead.
-FoldingSetBase::Node *FoldingSetBase::GetOrInsertNode(FoldingSetBase::Node *N) {
- FoldingSetNodeID ID;
- GetNodeProfile(N, ID);
- void *IP;
- if (Node *E = FindNodeOrInsertPos(ID, IP))
- return E;
- InsertNode(N, IP);
- return N;
-}
-
-//===----------------------------------------------------------------------===//
-// FoldingSetIteratorImpl Implementation
-
-FoldingSetIteratorImpl::FoldingSetIteratorImpl(void **Bucket) {
- // Skip to the first non-null non-self-cycle bucket.
- while (*Bucket != reinterpret_cast<void*>(-1) &&
- (!*Bucket || !GetNextPtr(*Bucket)))
- ++Bucket;
-
- NodePtr = static_cast<FoldingSetNode*>(*Bucket);
-}
-
-void FoldingSetIteratorImpl::advance() {
- // If there is another link within this bucket, go to it.
- void *Probe = NodePtr->getNextInBucket();
-
- if (FoldingSetNode *NextNodeInBucket = GetNextPtr(Probe))
- NodePtr = NextNodeInBucket;
- else {
- // Otherwise, this is the last link in this bucket.
- void **Bucket = GetBucketPtr(Probe);
-
- // Skip to the next non-null non-self-cycle bucket.
- do {
- ++Bucket;
- } while (*Bucket != reinterpret_cast<void*>(-1) &&
- (!*Bucket || !GetNextPtr(*Bucket)));
-
- NodePtr = static_cast<FoldingSetNode*>(*Bucket);
- }
-}
-
-//===----------------------------------------------------------------------===//
-// FoldingSetBucketIteratorImpl Implementation
-
-FoldingSetBucketIteratorImpl::FoldingSetBucketIteratorImpl(void **Bucket) {
- Ptr = (!*Bucket || !GetNextPtr(*Bucket)) ? (void*) Bucket : *Bucket;
-}
diff --git a/gnu/llvm/lib/Support/FormatVariadic.cpp b/gnu/llvm/lib/Support/FormatVariadic.cpp
deleted file mode 100644
index 1f3505d5f74..00000000000
--- a/gnu/llvm/lib/Support/FormatVariadic.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-//===- FormatVariadic.cpp - Format string parsing and analysis ----*-C++-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/FormatVariadic.h"
-
-using namespace llvm;
-
-static Optional<AlignStyle> translateLocChar(char C) {
- switch (C) {
- case '-':
- return AlignStyle::Left;
- case '=':
- return AlignStyle::Center;
- case '+':
- return AlignStyle::Right;
- default:
- return None;
- }
- LLVM_BUILTIN_UNREACHABLE;
-}
-
-bool formatv_object_base::consumeFieldLayout(StringRef &Spec, AlignStyle &Where,
- size_t &Align, char &Pad) {
- Where = AlignStyle::Right;
- Align = 0;
- Pad = ' ';
- if (Spec.empty())
- return true;
-
- if (Spec.size() > 1) {
- // A maximum of 2 characters at the beginning can be used for something
- // other
- // than the width.
- // If Spec[1] is a loc char, then Spec[0] is a pad char and Spec[2:...]
- // contains the width.
- // Otherwise, if Spec[0] is a loc char, then Spec[1:...] contains the width.
- // Otherwise, Spec[0:...] contains the width.
- if (auto Loc = translateLocChar(Spec[1])) {
- Pad = Spec[0];
- Where = *Loc;
- Spec = Spec.drop_front(2);
- } else if (auto Loc = translateLocChar(Spec[0])) {
- Where = *Loc;
- Spec = Spec.drop_front(1);
- }
- }
-
- bool Failed = Spec.consumeInteger(0, Align);
- return !Failed;
-}
-
-Optional<ReplacementItem>
-formatv_object_base::parseReplacementItem(StringRef Spec) {
- StringRef RepString = Spec.trim("{}");
-
- // If the replacement sequence does not start with a non-negative integer,
- // this is an error.
- char Pad = ' ';
- std::size_t Align = 0;
- AlignStyle Where = AlignStyle::Right;
- StringRef Options;
- size_t Index = 0;
- RepString = RepString.trim();
- if (RepString.consumeInteger(0, Index)) {
- assert(false && "Invalid replacement sequence index!");
- return ReplacementItem{};
- }
- RepString = RepString.trim();
- if (!RepString.empty() && RepString.front() == ',') {
- RepString = RepString.drop_front();
- if (!consumeFieldLayout(RepString, Where, Align, Pad))
- assert(false && "Invalid replacement field layout specification!");
- }
- RepString = RepString.trim();
- if (!RepString.empty() && RepString.front() == ':') {
- Options = RepString.drop_front().trim();
- RepString = StringRef();
- }
- RepString = RepString.trim();
- if (!RepString.empty()) {
- assert(false && "Unexpected characters found in replacement string!");
- }
-
- return ReplacementItem{Spec, Index, Align, Where, Pad, Options};
-}
-
-std::pair<ReplacementItem, StringRef>
-formatv_object_base::splitLiteralAndReplacement(StringRef Fmt) {
- std::size_t From = 0;
- while (From < Fmt.size() && From != StringRef::npos) {
- std::size_t BO = Fmt.find_first_of('{', From);
- // Everything up until the first brace is a literal.
- if (BO != 0)
- return std::make_pair(ReplacementItem{Fmt.substr(0, BO)}, Fmt.substr(BO));
-
- StringRef Braces =
- Fmt.drop_front(BO).take_while([](char C) { return C == '{'; });
- // If there is more than one brace, then some of them are escaped. Treat
- // these as replacements.
- if (Braces.size() > 1) {
- size_t NumEscapedBraces = Braces.size() / 2;
- StringRef Middle = Fmt.substr(BO, NumEscapedBraces);
- StringRef Right = Fmt.drop_front(BO + NumEscapedBraces * 2);
- return std::make_pair(ReplacementItem{Middle}, Right);
- }
- // An unterminated open brace is undefined. We treat the rest of the string
- // as a literal replacement, but we assert to indicate that this is
- // undefined and that we consider it an error.
- std::size_t BC = Fmt.find_first_of('}', BO);
- if (BC == StringRef::npos) {
- assert(
- false &&
- "Unterminated brace sequence. Escape with {{ for a literal brace.");
- return std::make_pair(ReplacementItem{Fmt}, StringRef());
- }
-
- // Even if there is a closing brace, if there is another open brace before
- // this closing brace, treat this portion as literal, and try again with the
- // next one.
- std::size_t BO2 = Fmt.find_first_of('{', BO + 1);
- if (BO2 < BC)
- return std::make_pair(ReplacementItem{Fmt.substr(0, BO2)},
- Fmt.substr(BO2));
-
- StringRef Spec = Fmt.slice(BO + 1, BC);
- StringRef Right = Fmt.substr(BC + 1);
-
- auto RI = parseReplacementItem(Spec);
- if (RI.hasValue())
- return std::make_pair(*RI, Right);
-
- // If there was an error parsing the replacement item, treat it as an
- // invalid replacement spec, and just continue.
- From = BC + 1;
- }
- return std::make_pair(ReplacementItem{Fmt}, StringRef());
-}
-
-std::vector<ReplacementItem>
-formatv_object_base::parseFormatString(StringRef Fmt) {
- std::vector<ReplacementItem> Replacements;
- ReplacementItem I;
- while (!Fmt.empty()) {
- std::tie(I, Fmt) = splitLiteralAndReplacement(Fmt);
- if (I.Type != ReplacementType::Empty)
- Replacements.push_back(I);
- }
- return Replacements;
-}
-
-void detail::format_adapter::anchor() { }
diff --git a/gnu/llvm/lib/Support/FormattedStream.cpp b/gnu/llvm/lib/Support/FormattedStream.cpp
deleted file mode 100644
index b0cb06c1daa..00000000000
--- a/gnu/llvm/lib/Support/FormattedStream.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-//===-- llvm/Support/FormattedStream.cpp - Formatted streams ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the implementation of formatted_raw_ostream.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-
-using namespace llvm;
-
-/// UpdatePosition - Examine the given char sequence and figure out which
-/// column we end up in after output, and how many line breaks are contained.
-///
-static void UpdatePosition(std::pair<unsigned, unsigned> &Position, const char *Ptr, size_t Size) {
- unsigned &Column = Position.first;
- unsigned &Line = Position.second;
-
- // Keep track of the current column and line by scanning the string for
- // special characters
- for (const char *End = Ptr + Size; Ptr != End; ++Ptr) {
- ++Column;
- switch (*Ptr) {
- case '\n':
- Line += 1;
- LLVM_FALLTHROUGH;
- case '\r':
- Column = 0;
- break;
- case '\t':
- // Assumes tab stop = 8 characters.
- Column += (8 - (Column & 0x7)) & 0x7;
- break;
- }
- }
-}
-
-/// ComputePosition - Examine the current output and update line and column
-/// counts.
-void formatted_raw_ostream::ComputePosition(const char *Ptr, size_t Size) {
- // If our previous scan pointer is inside the buffer, assume we already
- // scanned those bytes. This depends on raw_ostream to not change our buffer
- // in unexpected ways.
- if (Ptr <= Scanned && Scanned <= Ptr + Size)
- // Scan all characters added since our last scan to determine the new
- // column.
- UpdatePosition(Position, Scanned, Size - (Scanned - Ptr));
- else
- UpdatePosition(Position, Ptr, Size);
-
- // Update the scanning pointer.
- Scanned = Ptr + Size;
-}
-
-/// PadToColumn - Align the output to some column number.
-///
-/// \param NewCol - The column to move to.
-///
-formatted_raw_ostream &formatted_raw_ostream::PadToColumn(unsigned NewCol) {
- // Figure out what's in the buffer and add it to the column count.
- ComputePosition(getBufferStart(), GetNumBytesInBuffer());
-
- // Output spaces until we reach the desired column.
- indent(std::max(int(NewCol - getColumn()), 1));
- return *this;
-}
-
-void formatted_raw_ostream::write_impl(const char *Ptr, size_t Size) {
- // Figure out what's in the buffer and add it to the column count.
- ComputePosition(Ptr, Size);
-
- // Write the data to the underlying stream (which is unbuffered, so
- // the data will be immediately written out).
- TheStream->write(Ptr, Size);
-
- // Reset the scanning pointer.
- Scanned = nullptr;
-}
-
-/// fouts() - This returns a reference to a formatted_raw_ostream for
-/// standard output. Use it like: fouts() << "foo" << "bar";
-formatted_raw_ostream &llvm::fouts() {
- static formatted_raw_ostream S(outs());
- return S;
-}
-
-/// ferrs() - This returns a reference to a formatted_raw_ostream for
-/// standard error. Use it like: ferrs() << "foo" << "bar";
-formatted_raw_ostream &llvm::ferrs() {
- static formatted_raw_ostream S(errs());
- return S;
-}
-
-/// fdbgs() - This returns a reference to a formatted_raw_ostream for
-/// the debug stream. Use it like: fdbgs() << "foo" << "bar";
-formatted_raw_ostream &llvm::fdbgs() {
- static formatted_raw_ostream S(dbgs());
- return S;
-}
diff --git a/gnu/llvm/lib/Support/GlobPattern.cpp b/gnu/llvm/lib/Support/GlobPattern.cpp
deleted file mode 100644
index 4ea110301f1..00000000000
--- a/gnu/llvm/lib/Support/GlobPattern.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-//===-- GlobPattern.cpp - Glob pattern matcher implementation -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a glob pattern matcher.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/GlobPattern.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Errc.h"
-
-using namespace llvm;
-
-static bool hasWildcard(StringRef S) {
- return S.find_first_of("?*[") != StringRef::npos;
-}
-
-// Expands character ranges and returns a bitmap.
-// For example, "a-cf-hz" is expanded to "abcfghz".
-static Expected<BitVector> expand(StringRef S, StringRef Original) {
- BitVector BV(256, false);
-
- // Expand X-Y.
- for (;;) {
- if (S.size() < 3)
- break;
-
- uint8_t Start = S[0];
- uint8_t End = S[2];
-
- // If it doesn't start with something like X-Y,
- // consume the first character and proceed.
- if (S[1] != '-') {
- BV[Start] = true;
- S = S.substr(1);
- continue;
- }
-
- // It must be in the form of X-Y.
- // Validate it and then interpret the range.
- if (Start > End)
- return make_error<StringError>("invalid glob pattern: " + Original,
- errc::invalid_argument);
-
- for (int C = Start; C <= End; ++C)
- BV[(uint8_t)C] = true;
- S = S.substr(3);
- }
-
- for (char C : S)
- BV[(uint8_t)C] = true;
- return BV;
-}
-
-// This is a scanner for the glob pattern.
-// A glob pattern token is one of "*", "?", "[<chars>]", "[^<chars>]"
-// (which is a negative form of "[<chars>]"), or a non-meta character.
-// This function returns the first token in S.
-static Expected<BitVector> scan(StringRef &S, StringRef Original) {
- switch (S[0]) {
- case '*':
- S = S.substr(1);
- // '*' is represented by an empty bitvector.
- // All other bitvectors are 256-bit long.
- return BitVector();
- case '?':
- S = S.substr(1);
- return BitVector(256, true);
- case '[': {
- size_t End = S.find(']', 1);
- if (End == StringRef::npos)
- return make_error<StringError>("invalid glob pattern: " + Original,
- errc::invalid_argument);
-
- StringRef Chars = S.substr(1, End - 1);
- S = S.substr(End + 1);
- if (Chars.startswith("^")) {
- Expected<BitVector> BV = expand(Chars.substr(1), Original);
- if (!BV)
- return BV.takeError();
- return BV->flip();
- }
- return expand(Chars, Original);
- }
- default:
- BitVector BV(256, false);
- BV[(uint8_t)S[0]] = true;
- S = S.substr(1);
- return BV;
- }
-}
-
-Expected<GlobPattern> GlobPattern::create(StringRef S) {
- GlobPattern Pat;
-
- // S doesn't contain any metacharacter,
- // so the regular string comparison should work.
- if (!hasWildcard(S)) {
- Pat.Exact = S;
- return Pat;
- }
-
- // S is something like "foo*". We can use startswith().
- if (S.endswith("*") && !hasWildcard(S.drop_back())) {
- Pat.Prefix = S.drop_back();
- return Pat;
- }
-
- // S is something like "*foo". We can use endswith().
- if (S.startswith("*") && !hasWildcard(S.drop_front())) {
- Pat.Suffix = S.drop_front();
- return Pat;
- }
-
- // Otherwise, we need to do real glob pattern matching.
- // Parse the pattern now.
- StringRef Original = S;
- while (!S.empty()) {
- Expected<BitVector> BV = scan(S, Original);
- if (!BV)
- return BV.takeError();
- Pat.Tokens.push_back(*BV);
- }
- return Pat;
-}
-
-bool GlobPattern::match(StringRef S) const {
- if (Exact)
- return S == *Exact;
- if (Prefix)
- return S.startswith(*Prefix);
- if (Suffix)
- return S.endswith(*Suffix);
- return matchOne(Tokens, S);
-}
-
-// Runs glob pattern Pats against string S.
-bool GlobPattern::matchOne(ArrayRef<BitVector> Pats, StringRef S) const {
- for (;;) {
- if (Pats.empty())
- return S.empty();
-
- // If Pats[0] is '*', try to match Pats[1..] against all possible
- // tail strings of S to see at least one pattern succeeds.
- if (Pats[0].size() == 0) {
- Pats = Pats.slice(1);
- if (Pats.empty())
- // Fast path. If a pattern is '*', it matches anything.
- return true;
- for (size_t I = 0, E = S.size(); I < E; ++I)
- if (matchOne(Pats, S.substr(I)))
- return true;
- return false;
- }
-
- // If Pats[0] is not '*', it must consume one character.
- if (S.empty() || !Pats[0][(uint8_t)S[0]])
- return false;
- Pats = Pats.slice(1);
- S = S.substr(1);
- }
-}
diff --git a/gnu/llvm/lib/Support/GraphWriter.cpp b/gnu/llvm/lib/Support/GraphWriter.cpp
deleted file mode 100644
index 9335daffc3e..00000000000
--- a/gnu/llvm/lib/Support/GraphWriter.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-//===- GraphWriter.cpp - Implements GraphWriter support routines ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements misc. GraphWriter support routines.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/GraphWriter.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <system_error>
-#include <string>
-#include <vector>
-
-using namespace llvm;
-
-static cl::opt<bool> ViewBackground("view-background", cl::Hidden,
- cl::desc("Execute graph viewer in the background. Creates tmp file litter."));
-
-std::string llvm::DOT::EscapeString(const std::string &Label) {
- std::string Str(Label);
- for (unsigned i = 0; i != Str.length(); ++i)
- switch (Str[i]) {
- case '\n':
- Str.insert(Str.begin()+i, '\\'); // Escape character...
- ++i;
- Str[i] = 'n';
- break;
- case '\t':
- Str.insert(Str.begin()+i, ' '); // Convert to two spaces
- ++i;
- Str[i] = ' ';
- break;
- case '\\':
- if (i+1 != Str.length())
- switch (Str[i+1]) {
- case 'l': continue; // don't disturb \l
- case '|': case '{': case '}':
- Str.erase(Str.begin()+i); continue;
- default: break;
- }
- LLVM_FALLTHROUGH;
- case '{': case '}':
- case '<': case '>':
- case '|': case '"':
- Str.insert(Str.begin()+i, '\\'); // Escape character...
- ++i; // don't infinite loop
- break;
- }
- return Str;
-}
-
-/// Get a color string for this node number. Simply round-robin selects
-/// from a reasonable number of colors.
-StringRef llvm::DOT::getColorString(unsigned ColorNumber) {
- static const int NumColors = 20;
- static const char* Colors[NumColors] = {
- "aaaaaa", "aa0000", "00aa00", "aa5500", "0055ff", "aa00aa", "00aaaa",
- "555555", "ff5555", "55ff55", "ffff55", "5555ff", "ff55ff", "55ffff",
- "ffaaaa", "aaffaa", "ffffaa", "aaaaff", "ffaaff", "aaffff"};
- return Colors[ColorNumber % NumColors];
-}
-
-std::string llvm::createGraphFilename(const Twine &Name, int &FD) {
- FD = -1;
- SmallString<128> Filename;
- std::error_code EC = sys::fs::createTemporaryFile(Name, "dot", FD, Filename);
- if (EC) {
- errs() << "Error: " << EC.message() << "\n";
- return "";
- }
-
- errs() << "Writing '" << Filename << "'... ";
- return Filename.str();
-}
-
-// Execute the graph viewer. Return true if there were errors.
-static bool ExecGraphViewer(StringRef ExecPath, std::vector<StringRef> &args,
- StringRef Filename, bool wait,
- std::string &ErrMsg) {
- if (wait) {
- if (sys::ExecuteAndWait(ExecPath, args, None, {}, 0, 0, &ErrMsg)) {
- errs() << "Error: " << ErrMsg << "\n";
- return true;
- }
- sys::fs::remove(Filename);
- errs() << " done. \n";
- } else {
- sys::ExecuteNoWait(ExecPath, args, None, {}, 0, &ErrMsg);
- errs() << "Remember to erase graph file: " << Filename << "\n";
- }
- return false;
-}
-
-namespace {
-
-struct GraphSession {
- std::string LogBuffer;
-
- bool TryFindProgram(StringRef Names, std::string &ProgramPath) {
- raw_string_ostream Log(LogBuffer);
- SmallVector<StringRef, 8> parts;
- Names.split(parts, '|');
- for (auto Name : parts) {
- if (ErrorOr<std::string> P = sys::findProgramByName(Name)) {
- ProgramPath = *P;
- return true;
- }
- Log << " Tried '" << Name << "'\n";
- }
- return false;
- }
-};
-
-} // end anonymous namespace
-
-static const char *getProgramName(GraphProgram::Name program) {
- switch (program) {
- case GraphProgram::DOT:
- return "dot";
- case GraphProgram::FDP:
- return "fdp";
- case GraphProgram::NEATO:
- return "neato";
- case GraphProgram::TWOPI:
- return "twopi";
- case GraphProgram::CIRCO:
- return "circo";
- }
- llvm_unreachable("bad kind");
-}
-
-bool llvm::DisplayGraph(StringRef FilenameRef, bool wait,
- GraphProgram::Name program) {
- std::string Filename = FilenameRef;
- std::string ErrMsg;
- std::string ViewerPath;
- GraphSession S;
-
-#ifdef __APPLE__
- wait &= !ViewBackground;
- if (S.TryFindProgram("open", ViewerPath)) {
- std::vector<StringRef> args;
- args.push_back(ViewerPath);
- if (wait)
- args.push_back("-W");
- args.push_back(Filename);
- errs() << "Trying 'open' program... ";
- if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg))
- return false;
- }
-#endif
- if (S.TryFindProgram("xdg-open", ViewerPath)) {
- std::vector<StringRef> args;
- args.push_back(ViewerPath);
- args.push_back(Filename);
- errs() << "Trying 'xdg-open' program... ";
- if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg))
- return false;
- }
-
- // Graphviz
- if (S.TryFindProgram("Graphviz", ViewerPath)) {
- std::vector<StringRef> args;
- args.push_back(ViewerPath);
- args.push_back(Filename);
-
- errs() << "Running 'Graphviz' program... ";
- return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
- }
-
- // xdot
- if (S.TryFindProgram("xdot|xdot.py", ViewerPath)) {
- std::vector<StringRef> args;
- args.push_back(ViewerPath);
- args.push_back(Filename);
-
- args.push_back("-f");
- args.push_back(getProgramName(program));
-
- errs() << "Running 'xdot.py' program... ";
- return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
- }
-
- enum ViewerKind {
- VK_None,
- VK_OSXOpen,
- VK_XDGOpen,
- VK_Ghostview,
- VK_CmdStart
- };
- ViewerKind Viewer = VK_None;
-#ifdef __APPLE__
- if (!Viewer && S.TryFindProgram("open", ViewerPath))
- Viewer = VK_OSXOpen;
-#endif
- if (!Viewer && S.TryFindProgram("gv", ViewerPath))
- Viewer = VK_Ghostview;
- if (!Viewer && S.TryFindProgram("xdg-open", ViewerPath))
- Viewer = VK_XDGOpen;
-#ifdef _WIN32
- if (!Viewer && S.TryFindProgram("cmd", ViewerPath)) {
- Viewer = VK_CmdStart;
- }
-#endif
-
- // PostScript or PDF graph generator + PostScript/PDF viewer
- std::string GeneratorPath;
- if (Viewer &&
- (S.TryFindProgram(getProgramName(program), GeneratorPath) ||
- S.TryFindProgram("dot|fdp|neato|twopi|circo", GeneratorPath))) {
- std::string OutputFilename =
- Filename + (Viewer == VK_CmdStart ? ".pdf" : ".ps");
-
- std::vector<StringRef> args;
- args.push_back(GeneratorPath);
- if (Viewer == VK_CmdStart)
- args.push_back("-Tpdf");
- else
- args.push_back("-Tps");
- args.push_back("-Nfontname=Courier");
- args.push_back("-Gsize=7.5,10");
- args.push_back(Filename);
- args.push_back("-o");
- args.push_back(OutputFilename);
-
- errs() << "Running '" << GeneratorPath << "' program... ";
-
- if (ExecGraphViewer(GeneratorPath, args, Filename, true, ErrMsg))
- return true;
-
- // The lifetime of StartArg must include the call of ExecGraphViewer
- // because the args are passed as vector of char*.
- std::string StartArg;
-
- args.clear();
- args.push_back(ViewerPath);
- switch (Viewer) {
- case VK_OSXOpen:
- args.push_back("-W");
- args.push_back(OutputFilename);
- break;
- case VK_XDGOpen:
- wait = false;
- args.push_back(OutputFilename);
- break;
- case VK_Ghostview:
- args.push_back("--spartan");
- args.push_back(OutputFilename);
- break;
- case VK_CmdStart:
- args.push_back("/S");
- args.push_back("/C");
- StartArg =
- (StringRef("start ") + (wait ? "/WAIT " : "") + OutputFilename).str();
- args.push_back(StartArg);
- break;
- case VK_None:
- llvm_unreachable("Invalid viewer");
- }
-
- ErrMsg.clear();
- return ExecGraphViewer(ViewerPath, args, OutputFilename, wait, ErrMsg);
- }
-
- // dotty
- if (S.TryFindProgram("dotty", ViewerPath)) {
- std::vector<StringRef> args;
- args.push_back(ViewerPath);
- args.push_back(Filename);
-
-// Dotty spawns another app and doesn't wait until it returns
-#ifdef _WIN32
- wait = false;
-#endif
- errs() << "Running 'dotty' program... ";
- return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
- }
-
- errs() << "Error: Couldn't find a usable graph viewer program:\n";
- errs() << S.LogBuffer << "\n";
- return true;
-}
diff --git a/gnu/llvm/lib/Support/Hashing.cpp b/gnu/llvm/lib/Support/Hashing.cpp
deleted file mode 100644
index 7de25cec737..00000000000
--- a/gnu/llvm/lib/Support/Hashing.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-//===-------------- lib/Support/Hashing.cpp -------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides implementation bits for the LLVM common hashing
-// infrastructure. Documentation and most of the other information is in the
-// header file.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/Hashing.h"
-
-using namespace llvm;
-
-// Provide a definition and static initializer for the fixed seed. This
-// initializer should always be zero to ensure its value can never appear to be
-// non-zero, even during dynamic initialization.
-uint64_t llvm::hashing::detail::fixed_seed_override = 0;
-
-// Implement the function for forced setting of the fixed seed.
-// FIXME: Use atomic operations here so that there is no data race.
-void llvm::set_fixed_execution_hash_seed(uint64_t fixed_value) {
- hashing::detail::fixed_seed_override = fixed_value;
-}
diff --git a/gnu/llvm/lib/Support/Host.cpp b/gnu/llvm/lib/Support/Host.cpp
deleted file mode 100644
index d5a688c7fb9..00000000000
--- a/gnu/llvm/lib/Support/Host.cpp
+++ /dev/null
@@ -1,1440 +0,0 @@
-//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the operating system Host concept.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Host.h"
-#include "llvm/Support/TargetParser.h"
-#include "llvm/ADT/SmallSet.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <assert.h>
-#include <string.h>
-
-// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
-#include "Unix/Host.inc"
-#endif
-#ifdef _WIN32
-#include "Windows/Host.inc"
-#endif
-#ifdef _MSC_VER
-#include <intrin.h>
-#endif
-#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
-#include <mach/host_info.h>
-#include <mach/mach.h>
-#include <mach/mach_host.h>
-#include <mach/machine.h>
-#endif
-
-#define DEBUG_TYPE "host-detection"
-
-//===----------------------------------------------------------------------===//
-//
-// Implementations of the CPU detection routines
-//
-//===----------------------------------------------------------------------===//
-
-using namespace llvm;
-
-static std::unique_ptr<llvm::MemoryBuffer>
- LLVM_ATTRIBUTE_UNUSED getProcCpuinfoContent() {
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
- llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo");
- if (std::error_code EC = Text.getError()) {
- llvm::errs() << "Can't read "
- << "/proc/cpuinfo: " << EC.message() << "\n";
- return nullptr;
- }
- return std::move(*Text);
-}
-
-StringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) {
- // Access to the Processor Version Register (PVR) on PowerPC is privileged,
- // and so we must use an operating-system interface to determine the current
- // processor type. On Linux, this is exposed through the /proc/cpuinfo file.
- const char *generic = "generic";
-
- // The cpu line is second (after the 'processor: 0' line), so if this
- // buffer is too small then something has changed (or is wrong).
- StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin();
- StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end();
-
- StringRef::const_iterator CIP = CPUInfoStart;
-
- StringRef::const_iterator CPUStart = 0;
- size_t CPULen = 0;
-
- // We need to find the first line which starts with cpu, spaces, and a colon.
- // After the colon, there may be some additional spaces and then the cpu type.
- while (CIP < CPUInfoEnd && CPUStart == 0) {
- if (CIP < CPUInfoEnd && *CIP == '\n')
- ++CIP;
-
- if (CIP < CPUInfoEnd && *CIP == 'c') {
- ++CIP;
- if (CIP < CPUInfoEnd && *CIP == 'p') {
- ++CIP;
- if (CIP < CPUInfoEnd && *CIP == 'u') {
- ++CIP;
- while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
- ++CIP;
-
- if (CIP < CPUInfoEnd && *CIP == ':') {
- ++CIP;
- while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
- ++CIP;
-
- if (CIP < CPUInfoEnd) {
- CPUStart = CIP;
- while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
- *CIP != ',' && *CIP != '\n'))
- ++CIP;
- CPULen = CIP - CPUStart;
- }
- }
- }
- }
- }
-
- if (CPUStart == 0)
- while (CIP < CPUInfoEnd && *CIP != '\n')
- ++CIP;
- }
-
- if (CPUStart == 0)
- return generic;
-
- return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
- .Case("604e", "604e")
- .Case("604", "604")
- .Case("7400", "7400")
- .Case("7410", "7400")
- .Case("7447", "7400")
- .Case("7455", "7450")
- .Case("G4", "g4")
- .Case("POWER4", "970")
- .Case("PPC970FX", "970")
- .Case("PPC970MP", "970")
- .Case("G5", "g5")
- .Case("POWER5", "g5")
- .Case("A2", "a2")
- .Case("POWER6", "pwr6")
- .Case("POWER7", "pwr7")
- .Case("POWER8", "pwr8")
- .Case("POWER8E", "pwr8")
- .Case("POWER8NVL", "pwr8")
- .Case("POWER9", "pwr9")
- .Default(generic);
-}
-
-StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) {
- // The cpuid register on arm is not accessible from user space. On Linux,
- // it is exposed through the /proc/cpuinfo file.
-
- // Read 32 lines from /proc/cpuinfo, which should contain the CPU part line
- // in all cases.
- SmallVector<StringRef, 32> Lines;
- ProcCpuinfoContent.split(Lines, "\n");
-
- // Look for the CPU implementer line.
- StringRef Implementer;
- StringRef Hardware;
- for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
- if (Lines[I].startswith("CPU implementer"))
- Implementer = Lines[I].substr(15).ltrim("\t :");
- if (Lines[I].startswith("Hardware"))
- Hardware = Lines[I].substr(8).ltrim("\t :");
- }
-
- if (Implementer == "0x41") { // ARM Ltd.
- // MSM8992/8994 may give cpu part for the core that the kernel is running on,
- // which is undeterministic and wrong. Always return cortex-a53 for these SoC.
- if (Hardware.endswith("MSM8994") || Hardware.endswith("MSM8996"))
- return "cortex-a53";
-
-
- // Look for the CPU part line.
- for (unsigned I = 0, E = Lines.size(); I != E; ++I)
- if (Lines[I].startswith("CPU part"))
- // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
- // values correspond to the "Part number" in the CP15/c0 register. The
- // contents are specified in the various processor manuals.
- return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
- .Case("0x926", "arm926ej-s")
- .Case("0xb02", "mpcore")
- .Case("0xb36", "arm1136j-s")
- .Case("0xb56", "arm1156t2-s")
- .Case("0xb76", "arm1176jz-s")
- .Case("0xc08", "cortex-a8")
- .Case("0xc09", "cortex-a9")
- .Case("0xc0f", "cortex-a15")
- .Case("0xc20", "cortex-m0")
- .Case("0xc23", "cortex-m3")
- .Case("0xc24", "cortex-m4")
- .Case("0xd04", "cortex-a35")
- .Case("0xd03", "cortex-a53")
- .Case("0xd07", "cortex-a57")
- .Case("0xd08", "cortex-a72")
- .Case("0xd09", "cortex-a73")
- .Default("generic");
- }
-
- if (Implementer == "0x42" || Implementer == "0x43") { // Broadcom | Cavium.
- for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
- if (Lines[I].startswith("CPU part")) {
- return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
- .Case("0x516", "thunderx2t99")
- .Case("0x0516", "thunderx2t99")
- .Case("0xaf", "thunderx2t99")
- .Case("0x0af", "thunderx2t99")
- .Case("0xa1", "thunderxt88")
- .Case("0x0a1", "thunderxt88")
- .Default("generic");
- }
- }
- }
-
- if (Implementer == "0x48") // HiSilicon Technologies, Inc.
- // Look for the CPU part line.
- for (unsigned I = 0, E = Lines.size(); I != E; ++I)
- if (Lines[I].startswith("CPU part"))
- // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
- // values correspond to the "Part number" in the CP15/c0 register. The
- // contents are specified in the various processor manuals.
- return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
- .Case("0xd01", "tsv110")
- .Default("generic");
-
- if (Implementer == "0x51") // Qualcomm Technologies, Inc.
- // Look for the CPU part line.
- for (unsigned I = 0, E = Lines.size(); I != E; ++I)
- if (Lines[I].startswith("CPU part"))
- // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The
- // values correspond to the "Part number" in the CP15/c0 register. The
- // contents are specified in the various processor manuals.
- return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :"))
- .Case("0x06f", "krait") // APQ8064
- .Case("0x201", "kryo")
- .Case("0x205", "kryo")
- .Case("0x211", "kryo")
- .Case("0x800", "cortex-a73")
- .Case("0x801", "cortex-a73")
- .Case("0xc00", "falkor")
- .Case("0xc01", "saphira")
- .Default("generic");
-
- if (Implementer == "0x53") { // Samsung Electronics Co., Ltd.
- // The Exynos chips have a convoluted ID scheme that doesn't seem to follow
- // any predictive pattern across variants and parts.
- unsigned Variant = 0, Part = 0;
-
- // Look for the CPU variant line, whose value is a 1 digit hexadecimal
- // number, corresponding to the Variant bits in the CP15/C0 register.
- for (auto I : Lines)
- if (I.consume_front("CPU variant"))
- I.ltrim("\t :").getAsInteger(0, Variant);
-
- // Look for the CPU part line, whose value is a 3 digit hexadecimal
- // number, corresponding to the PartNum bits in the CP15/C0 register.
- for (auto I : Lines)
- if (I.consume_front("CPU part"))
- I.ltrim("\t :").getAsInteger(0, Part);
-
- unsigned Exynos = (Variant << 12) | Part;
- switch (Exynos) {
- default:
- // Default by falling through to Exynos M1.
- LLVM_FALLTHROUGH;
-
- case 0x1001:
- return "exynos-m1";
-
- case 0x4001:
- return "exynos-m2";
- }
- }
-
- return "generic";
-}
-
-StringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) {
- // STIDP is a privileged operation, so use /proc/cpuinfo instead.
-
- // The "processor 0:" line comes after a fair amount of other information,
- // including a cache breakdown, but this should be plenty.
- SmallVector<StringRef, 32> Lines;
- ProcCpuinfoContent.split(Lines, "\n");
-
- // Look for the CPU features.
- SmallVector<StringRef, 32> CPUFeatures;
- for (unsigned I = 0, E = Lines.size(); I != E; ++I)
- if (Lines[I].startswith("features")) {
- size_t Pos = Lines[I].find(":");
- if (Pos != StringRef::npos) {
- Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' ');
- break;
- }
- }
-
- // We need to check for the presence of vector support independently of
- // the machine type, since we may only use the vector register set when
- // supported by the kernel (and hypervisor).
- bool HaveVectorSupport = false;
- for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
- if (CPUFeatures[I] == "vx")
- HaveVectorSupport = true;
- }
-
- // Now check the processor machine type.
- for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
- if (Lines[I].startswith("processor ")) {
- size_t Pos = Lines[I].find("machine = ");
- if (Pos != StringRef::npos) {
- Pos += sizeof("machine = ") - 1;
- unsigned int Id;
- if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) {
- if (Id >= 3906 && HaveVectorSupport)
- return "z14";
- if (Id >= 2964 && HaveVectorSupport)
- return "z13";
- if (Id >= 2827)
- return "zEC12";
- if (Id >= 2817)
- return "z196";
- }
- }
- break;
- }
- }
-
- return "generic";
-}
-
-StringRef sys::detail::getHostCPUNameForBPF() {
-#if !defined(__linux__) || !defined(__x86_64__)
- return "generic";
-#else
- uint8_t insns[40] __attribute__ ((aligned (8))) =
- /* BPF_MOV64_IMM(BPF_REG_0, 0) */
- { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- /* BPF_MOV64_IMM(BPF_REG_2, 1) */
- 0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
- /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */
- 0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
- /* BPF_MOV64_IMM(BPF_REG_0, 1) */
- 0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
- /* BPF_EXIT_INSN() */
- 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
-
- struct bpf_prog_load_attr {
- uint32_t prog_type;
- uint32_t insn_cnt;
- uint64_t insns;
- uint64_t license;
- uint32_t log_level;
- uint32_t log_size;
- uint64_t log_buf;
- uint32_t kern_version;
- uint32_t prog_flags;
- } attr = {};
- attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */
- attr.insn_cnt = 5;
- attr.insns = (uint64_t)insns;
- attr.license = (uint64_t)"DUMMY";
-
- int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr));
- if (fd >= 0) {
- close(fd);
- return "v2";
- }
- return "v1";
-#endif
-}
-
-#if defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64__) || defined(_M_X64)
-
-enum VendorSignatures {
- SIG_INTEL = 0x756e6547 /* Genu */,
- SIG_AMD = 0x68747541 /* Auth */
-};
-
-// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
-// Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID
-// support. Consequently, for i386, the presence of CPUID is checked first
-// via the corresponding eflags bit.
-// Removal of cpuid.h header motivated by PR30384
-// Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp
-// or test-suite, but are used in external projects e.g. libstdcxx
-static bool isCpuIdSupported() {
-#if defined(__GNUC__) || defined(__clang__)
-#if defined(__i386__)
- int __cpuid_supported;
- __asm__(" pushfl\n"
- " popl %%eax\n"
- " movl %%eax,%%ecx\n"
- " xorl $0x00200000,%%eax\n"
- " pushl %%eax\n"
- " popfl\n"
- " pushfl\n"
- " popl %%eax\n"
- " movl $0,%0\n"
- " cmpl %%eax,%%ecx\n"
- " je 1f\n"
- " movl $1,%0\n"
- "1:"
- : "=r"(__cpuid_supported)
- :
- : "eax", "ecx");
- if (!__cpuid_supported)
- return false;
-#endif
- return true;
-#endif
- return true;
-}
-
-/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
-/// the specified arguments. If we can't run cpuid on the host, return true.
-static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
- unsigned *rECX, unsigned *rEDX) {
-#if defined(__GNUC__) || defined(__clang__)
-#if defined(__x86_64__)
- // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
- // FIXME: should we save this for Clang?
- __asm__("movq\t%%rbx, %%rsi\n\t"
- "cpuid\n\t"
- "xchgq\t%%rbx, %%rsi\n\t"
- : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
- : "a"(value));
- return false;
-#elif defined(__i386__)
- __asm__("movl\t%%ebx, %%esi\n\t"
- "cpuid\n\t"
- "xchgl\t%%ebx, %%esi\n\t"
- : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
- : "a"(value));
- return false;
-#else
- return true;
-#endif
-#elif defined(_MSC_VER)
- // The MSVC intrinsic is portable across x86 and x64.
- int registers[4];
- __cpuid(registers, value);
- *rEAX = registers[0];
- *rEBX = registers[1];
- *rECX = registers[2];
- *rEDX = registers[3];
- return false;
-#else
- return true;
-#endif
-}
-
-/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
-/// the 4 values in the specified arguments. If we can't run cpuid on the host,
-/// return true.
-static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
- unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
- unsigned *rEDX) {
-#if defined(__GNUC__) || defined(__clang__)
-#if defined(__x86_64__)
- // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
- // FIXME: should we save this for Clang?
- __asm__("movq\t%%rbx, %%rsi\n\t"
- "cpuid\n\t"
- "xchgq\t%%rbx, %%rsi\n\t"
- : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
- : "a"(value), "c"(subleaf));
- return false;
-#elif defined(__i386__)
- __asm__("movl\t%%ebx, %%esi\n\t"
- "cpuid\n\t"
- "xchgl\t%%ebx, %%esi\n\t"
- : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
- : "a"(value), "c"(subleaf));
- return false;
-#else
- return true;
-#endif
-#elif defined(_MSC_VER)
- int registers[4];
- __cpuidex(registers, value, subleaf);
- *rEAX = registers[0];
- *rEBX = registers[1];
- *rECX = registers[2];
- *rEDX = registers[3];
- return false;
-#else
- return true;
-#endif
-}
-
-// Read control register 0 (XCR0). Used to detect features such as AVX.
-static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
-#if defined(__GNUC__) || defined(__clang__)
- // Check xgetbv; this uses a .byte sequence instead of the instruction
- // directly because older assemblers do not include support for xgetbv and
- // there is no easy way to conditionally compile based on the assembler used.
- __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
- return false;
-#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
- unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
- *rEAX = Result;
- *rEDX = Result >> 32;
- return false;
-#else
- return true;
-#endif
-}
-
-static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
- unsigned *Model) {
- *Family = (EAX >> 8) & 0xf; // Bits 8 - 11
- *Model = (EAX >> 4) & 0xf; // Bits 4 - 7
- if (*Family == 6 || *Family == 0xf) {
- if (*Family == 0xf)
- // Examine extended family ID if family ID is F.
- *Family += (EAX >> 20) & 0xff; // Bits 20 - 27
- // Examine extended model ID if family ID is 6 or F.
- *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
- }
-}
-
-static void
-getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
- unsigned Brand_id, unsigned Features,
- unsigned Features2, unsigned Features3,
- unsigned *Type, unsigned *Subtype) {
- if (Brand_id != 0)
- return;
- switch (Family) {
- case 3:
- *Type = X86::INTEL_i386;
- break;
- case 4:
- *Type = X86::INTEL_i486;
- break;
- case 5:
- if (Features & (1 << X86::FEATURE_MMX)) {
- *Type = X86::INTEL_PENTIUM_MMX;
- break;
- }
- *Type = X86::INTEL_PENTIUM;
- break;
- case 6:
- switch (Model) {
- case 0x01: // Pentium Pro processor
- *Type = X86::INTEL_PENTIUM_PRO;
- break;
- case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor,
- // model 03
- case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor,
- // model 05, and Intel Celeron processor, model 05
- case 0x06: // Celeron processor, model 06
- *Type = X86::INTEL_PENTIUM_II;
- break;
- case 0x07: // Pentium III processor, model 07, and Pentium III Xeon
- // processor, model 07
- case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor,
- // model 08, and Celeron processor, model 08
- case 0x0a: // Pentium III Xeon processor, model 0Ah
- case 0x0b: // Pentium III processor, model 0Bh
- *Type = X86::INTEL_PENTIUM_III;
- break;
- case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09.
- case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model
- // 0Dh. All processors are manufactured using the 90 nm process.
- case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579
- // Integrated Processor with Intel QuickAssist Technology
- *Type = X86::INTEL_PENTIUM_M;
- break;
- case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model
- // 0Eh. All processors are manufactured using the 65 nm process.
- *Type = X86::INTEL_CORE_DUO;
- break; // yonah
- case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
- // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
- // mobile processor, Intel Core 2 Extreme processor, Intel
- // Pentium Dual-Core processor, Intel Xeon processor, model
- // 0Fh. All processors are manufactured using the 65 nm process.
- case 0x16: // Intel Celeron processor model 16h. All processors are
- // manufactured using the 65 nm process
- *Type = X86::INTEL_CORE2; // "core2"
- *Subtype = X86::INTEL_CORE2_65;
- break;
- case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model
- // 17h. All processors are manufactured using the 45 nm process.
- //
- // 45nm: Penryn , Wolfdale, Yorkfield (XE)
- case 0x1d: // Intel Xeon processor MP. All processors are manufactured using
- // the 45 nm process.
- *Type = X86::INTEL_CORE2; // "penryn"
- *Subtype = X86::INTEL_CORE2_45;
- break;
- case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
- // processors are manufactured using the 45 nm process.
- case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz.
- // As found in a Summer 2010 model iMac.
- case 0x1f:
- case 0x2e: // Nehalem EX
- *Type = X86::INTEL_COREI7; // "nehalem"
- *Subtype = X86::INTEL_COREI7_NEHALEM;
- break;
- case 0x25: // Intel Core i7, laptop version.
- case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
- // processors are manufactured using the 32 nm process.
- case 0x2f: // Westmere EX
- *Type = X86::INTEL_COREI7; // "westmere"
- *Subtype = X86::INTEL_COREI7_WESTMERE;
- break;
- case 0x2a: // Intel Core i7 processor. All processors are manufactured
- // using the 32 nm process.
- case 0x2d:
- *Type = X86::INTEL_COREI7; //"sandybridge"
- *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
- break;
- case 0x3a:
- case 0x3e: // Ivy Bridge EP
- *Type = X86::INTEL_COREI7; // "ivybridge"
- *Subtype = X86::INTEL_COREI7_IVYBRIDGE;
- break;
-
- // Haswell:
- case 0x3c:
- case 0x3f:
- case 0x45:
- case 0x46:
- *Type = X86::INTEL_COREI7; // "haswell"
- *Subtype = X86::INTEL_COREI7_HASWELL;
- break;
-
- // Broadwell:
- case 0x3d:
- case 0x47:
- case 0x4f:
- case 0x56:
- *Type = X86::INTEL_COREI7; // "broadwell"
- *Subtype = X86::INTEL_COREI7_BROADWELL;
- break;
-
- // Skylake:
- case 0x4e: // Skylake mobile
- case 0x5e: // Skylake desktop
- case 0x8e: // Kaby Lake mobile
- case 0x9e: // Kaby Lake desktop
- *Type = X86::INTEL_COREI7; // "skylake"
- *Subtype = X86::INTEL_COREI7_SKYLAKE;
- break;
-
- // Skylake Xeon:
- case 0x55:
- *Type = X86::INTEL_COREI7;
- *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; // "skylake-avx512"
- break;
-
- // Cannonlake:
- case 0x66:
- *Type = X86::INTEL_COREI7;
- *Subtype = X86::INTEL_COREI7_CANNONLAKE; // "cannonlake"
- break;
-
- case 0x1c: // Most 45 nm Intel Atom processors
- case 0x26: // 45 nm Atom Lincroft
- case 0x27: // 32 nm Atom Medfield
- case 0x35: // 32 nm Atom Midview
- case 0x36: // 32 nm Atom Midview
- *Type = X86::INTEL_BONNELL;
- break; // "bonnell"
-
- // Atom Silvermont codes from the Intel software optimization guide.
- case 0x37:
- case 0x4a:
- case 0x4d:
- case 0x5a:
- case 0x5d:
- case 0x4c: // really airmont
- *Type = X86::INTEL_SILVERMONT;
- break; // "silvermont"
- // Goldmont:
- case 0x5c: // Apollo Lake
- case 0x5f: // Denverton
- *Type = X86::INTEL_GOLDMONT;
- break; // "goldmont"
- case 0x7a:
- *Type = X86::INTEL_GOLDMONT_PLUS;
- break;
- case 0x57:
- *Type = X86::INTEL_KNL; // knl
- break;
- case 0x85:
- *Type = X86::INTEL_KNM; // knm
- break;
-
- default: // Unknown family 6 CPU, try to guess.
- if (Features & (1 << X86::FEATURE_AVX512VBMI2)) {
- *Type = X86::INTEL_COREI7;
- *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT;
- break;
- }
-
- if (Features & (1 << X86::FEATURE_AVX512VBMI)) {
- *Type = X86::INTEL_COREI7;
- *Subtype = X86::INTEL_COREI7_CANNONLAKE;
- break;
- }
-
- if (Features2 & (1 << (X86::FEATURE_AVX512VNNI - 32))) {
- *Type = X86::INTEL_COREI7;
- *Subtype = X86::INTEL_COREI7_CASCADELAKE;
- break;
- }
-
- if (Features & (1 << X86::FEATURE_AVX512VL)) {
- *Type = X86::INTEL_COREI7;
- *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512;
- break;
- }
-
- if (Features & (1 << X86::FEATURE_AVX512ER)) {
- *Type = X86::INTEL_KNL; // knl
- break;
- }
-
- if (Features3 & (1 << (X86::FEATURE_CLFLUSHOPT - 64))) {
- if (Features3 & (1 << (X86::FEATURE_SHA - 64))) {
- *Type = X86::INTEL_GOLDMONT;
- } else {
- *Type = X86::INTEL_COREI7;
- *Subtype = X86::INTEL_COREI7_SKYLAKE;
- }
- break;
- }
- if (Features3 & (1 << (X86::FEATURE_ADX - 64))) {
- *Type = X86::INTEL_COREI7;
- *Subtype = X86::INTEL_COREI7_BROADWELL;
- break;
- }
- if (Features & (1 << X86::FEATURE_AVX2)) {
- *Type = X86::INTEL_COREI7;
- *Subtype = X86::INTEL_COREI7_HASWELL;
- break;
- }
- if (Features & (1 << X86::FEATURE_AVX)) {
- *Type = X86::INTEL_COREI7;
- *Subtype = X86::INTEL_COREI7_SANDYBRIDGE;
- break;
- }
- if (Features & (1 << X86::FEATURE_SSE4_2)) {
- if (Features3 & (1 << (X86::FEATURE_MOVBE - 64))) {
- *Type = X86::INTEL_SILVERMONT;
- } else {
- *Type = X86::INTEL_COREI7;
- *Subtype = X86::INTEL_COREI7_NEHALEM;
- }
- break;
- }
- if (Features & (1 << X86::FEATURE_SSE4_1)) {
- *Type = X86::INTEL_CORE2; // "penryn"
- *Subtype = X86::INTEL_CORE2_45;
- break;
- }
- if (Features & (1 << X86::FEATURE_SSSE3)) {
- if (Features3 & (1 << (X86::FEATURE_MOVBE - 64))) {
- *Type = X86::INTEL_BONNELL; // "bonnell"
- } else {
- *Type = X86::INTEL_CORE2; // "core2"
- *Subtype = X86::INTEL_CORE2_65;
- }
- break;
- }
- if (Features3 & (1 << (X86::FEATURE_EM64T - 64))) {
- *Type = X86::INTEL_CORE2; // "core2"
- *Subtype = X86::INTEL_CORE2_65;
- break;
- }
- if (Features & (1 << X86::FEATURE_SSE3)) {
- *Type = X86::INTEL_CORE_DUO;
- break;
- }
- if (Features & (1 << X86::FEATURE_SSE2)) {
- *Type = X86::INTEL_PENTIUM_M;
- break;
- }
- if (Features & (1 << X86::FEATURE_SSE)) {
- *Type = X86::INTEL_PENTIUM_III;
- break;
- }
- if (Features & (1 << X86::FEATURE_MMX)) {
- *Type = X86::INTEL_PENTIUM_II;
- break;
- }
- *Type = X86::INTEL_PENTIUM_PRO;
- break;
- }
- break;
- case 15: {
- if (Features3 & (1 << (X86::FEATURE_EM64T - 64))) {
- *Type = X86::INTEL_NOCONA;
- break;
- }
- if (Features & (1 << X86::FEATURE_SSE3)) {
- *Type = X86::INTEL_PRESCOTT;
- break;
- }
- *Type = X86::INTEL_PENTIUM_IV;
- break;
- }
- default:
- break; /*"generic"*/
- }
-}
-
-static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
- unsigned Features, unsigned *Type,
- unsigned *Subtype) {
- // FIXME: this poorly matches the generated SubtargetFeatureKV table. There
- // appears to be no way to generate the wide variety of AMD-specific targets
- // from the information returned from CPUID.
- switch (Family) {
- case 4:
- *Type = X86::AMD_i486;
- break;
- case 5:
- *Type = X86::AMDPENTIUM;
- switch (Model) {
- case 6:
- case 7:
- *Subtype = X86::AMDPENTIUM_K6;
- break; // "k6"
- case 8:
- *Subtype = X86::AMDPENTIUM_K62;
- break; // "k6-2"
- case 9:
- case 13:
- *Subtype = X86::AMDPENTIUM_K63;
- break; // "k6-3"
- case 10:
- *Subtype = X86::AMDPENTIUM_GEODE;
- break; // "geode"
- }
- break;
- case 6:
- if (Features & (1 << X86::FEATURE_SSE)) {
- *Type = X86::AMD_ATHLON_XP;
- break; // "athlon-xp"
- }
- *Type = X86::AMD_ATHLON;
- break; // "athlon"
- case 15:
- if (Features & (1 << X86::FEATURE_SSE3)) {
- *Type = X86::AMD_K8SSE3;
- break; // "k8-sse3"
- }
- *Type = X86::AMD_K8;
- break; // "k8"
- case 16:
- *Type = X86::AMDFAM10H; // "amdfam10"
- switch (Model) {
- case 2:
- *Subtype = X86::AMDFAM10H_BARCELONA;
- break;
- case 4:
- *Subtype = X86::AMDFAM10H_SHANGHAI;
- break;
- case 8:
- *Subtype = X86::AMDFAM10H_ISTANBUL;
- break;
- }
- break;
- case 20:
- *Type = X86::AMD_BTVER1;
- break; // "btver1";
- case 21:
- *Type = X86::AMDFAM15H;
- if (Model >= 0x60 && Model <= 0x7f) {
- *Subtype = X86::AMDFAM15H_BDVER4;
- break; // "bdver4"; 60h-7Fh: Excavator
- }
- if (Model >= 0x30 && Model <= 0x3f) {
- *Subtype = X86::AMDFAM15H_BDVER3;
- break; // "bdver3"; 30h-3Fh: Steamroller
- }
- if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) {
- *Subtype = X86::AMDFAM15H_BDVER2;
- break; // "bdver2"; 02h, 10h-1Fh: Piledriver
- }
- if (Model <= 0x0f) {
- *Subtype = X86::AMDFAM15H_BDVER1;
- break; // "bdver1"; 00h-0Fh: Bulldozer
- }
- break;
- case 22:
- *Type = X86::AMD_BTVER2;
- break; // "btver2"
- case 23:
- *Type = X86::AMDFAM17H;
- *Subtype = X86::AMDFAM17H_ZNVER1;
- break;
- default:
- break; // "generic"
- }
-}
-
-static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
- unsigned *FeaturesOut, unsigned *Features2Out,
- unsigned *Features3Out) {
- unsigned Features = 0;
- unsigned Features2 = 0;
- unsigned Features3 = 0;
- unsigned EAX, EBX;
-
- auto setFeature = [&](unsigned F) {
- if (F < 32)
- Features |= 1U << (F & 0x1f);
- else if (F < 64)
- Features2 |= 1U << ((F - 32) & 0x1f);
- else if (F < 96)
- Features3 |= 1U << ((F - 64) & 0x1f);
- else
- llvm_unreachable("Unexpected FeatureBit");
- };
-
- if ((EDX >> 15) & 1)
- setFeature(X86::FEATURE_CMOV);
- if ((EDX >> 23) & 1)
- setFeature(X86::FEATURE_MMX);
- if ((EDX >> 25) & 1)
- setFeature(X86::FEATURE_SSE);
- if ((EDX >> 26) & 1)
- setFeature(X86::FEATURE_SSE2);
-
- if ((ECX >> 0) & 1)
- setFeature(X86::FEATURE_SSE3);
- if ((ECX >> 1) & 1)
- setFeature(X86::FEATURE_PCLMUL);
- if ((ECX >> 9) & 1)
- setFeature(X86::FEATURE_SSSE3);
- if ((ECX >> 12) & 1)
- setFeature(X86::FEATURE_FMA);
- if ((ECX >> 19) & 1)
- setFeature(X86::FEATURE_SSE4_1);
- if ((ECX >> 20) & 1)
- setFeature(X86::FEATURE_SSE4_2);
- if ((ECX >> 23) & 1)
- setFeature(X86::FEATURE_POPCNT);
- if ((ECX >> 25) & 1)
- setFeature(X86::FEATURE_AES);
-
- if ((ECX >> 22) & 1)
- setFeature(X86::FEATURE_MOVBE);
-
- // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
- // indicates that the AVX registers will be saved and restored on context
- // switch, then we have full AVX support.
- const unsigned AVXBits = (1 << 27) | (1 << 28);
- bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
- ((EAX & 0x6) == 0x6);
- bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
-
- if (HasAVX)
- setFeature(X86::FEATURE_AVX);
-
- bool HasLeaf7 =
- MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
-
- if (HasLeaf7 && ((EBX >> 3) & 1))
- setFeature(X86::FEATURE_BMI);
- if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
- setFeature(X86::FEATURE_AVX2);
- if (HasLeaf7 && ((EBX >> 9) & 1))
- setFeature(X86::FEATURE_BMI2);
- if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512F);
- if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512DQ);
- if (HasLeaf7 && ((EBX >> 19) & 1))
- setFeature(X86::FEATURE_ADX);
- if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512IFMA);
- if (HasLeaf7 && ((EBX >> 23) & 1))
- setFeature(X86::FEATURE_CLFLUSHOPT);
- if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512PF);
- if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512ER);
- if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512CD);
- if (HasLeaf7 && ((EBX >> 29) & 1))
- setFeature(X86::FEATURE_SHA);
- if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512BW);
- if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512VL);
-
- if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512VBMI);
- if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512VBMI2);
- if (HasLeaf7 && ((ECX >> 8) & 1))
- setFeature(X86::FEATURE_GFNI);
- if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)
- setFeature(X86::FEATURE_VPCLMULQDQ);
- if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512VNNI);
- if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512BITALG);
- if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX512VPOPCNTDQ);
-
- if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX5124VNNIW);
- if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
- setFeature(X86::FEATURE_AVX5124FMAPS);
-
- unsigned MaxExtLevel;
- getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
-
- bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
- !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
- if (HasExtLeaf1 && ((ECX >> 6) & 1))
- setFeature(X86::FEATURE_SSE4_A);
- if (HasExtLeaf1 && ((ECX >> 11) & 1))
- setFeature(X86::FEATURE_XOP);
- if (HasExtLeaf1 && ((ECX >> 16) & 1))
- setFeature(X86::FEATURE_FMA4);
-
- if (HasExtLeaf1 && ((EDX >> 29) & 1))
- setFeature(X86::FEATURE_EM64T);
-
- *FeaturesOut = Features;
- *Features2Out = Features2;
- *Features3Out = Features3;
-}
-
-StringRef sys::getHostCPUName() {
- unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
- unsigned MaxLeaf, Vendor;
-
-#if defined(__GNUC__) || defined(__clang__)
- //FIXME: include cpuid.h from clang or copy __get_cpuid_max here
- // and simplify it to not invoke __cpuid (like cpu_model.c in
- // compiler-rt/lib/builtins/cpu_model.c?
- // Opting for the second option.
- if(!isCpuIdSupported())
- return "generic";
-#endif
- if (getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX) || MaxLeaf < 1)
- return "generic";
- getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);
-
- unsigned Brand_id = EBX & 0xff;
- unsigned Family = 0, Model = 0;
- unsigned Features = 0, Features2 = 0, Features3 = 0;
- detectX86FamilyModel(EAX, &Family, &Model);
- getAvailableFeatures(ECX, EDX, MaxLeaf, &Features, &Features2, &Features3);
-
- unsigned Type = 0;
- unsigned Subtype = 0;
-
- if (Vendor == SIG_INTEL) {
- getIntelProcessorTypeAndSubtype(Family, Model, Brand_id, Features,
- Features2, Features3, &Type, &Subtype);
- } else if (Vendor == SIG_AMD) {
- getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype);
- }
-
- // Check subtypes first since those are more specific.
-#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \
- if (Subtype == X86::ENUM) \
- return ARCHNAME;
-#include "llvm/Support/X86TargetParser.def"
-
- // Now check types.
-#define X86_CPU_TYPE(ARCHNAME, ENUM) \
- if (Type == X86::ENUM) \
- return ARCHNAME;
-#include "llvm/Support/X86TargetParser.def"
-
- return "generic";
-}
-
-#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
-StringRef sys::getHostCPUName() {
- host_basic_info_data_t hostInfo;
- mach_msg_type_number_t infoCount;
-
- infoCount = HOST_BASIC_INFO_COUNT;
- mach_port_t hostPort = mach_host_self();
- host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo,
- &infoCount);
- mach_port_deallocate(mach_task_self(), hostPort);
-
- if (hostInfo.cpu_type != CPU_TYPE_POWERPC)
- return "generic";
-
- switch (hostInfo.cpu_subtype) {
- case CPU_SUBTYPE_POWERPC_601:
- return "601";
- case CPU_SUBTYPE_POWERPC_602:
- return "602";
- case CPU_SUBTYPE_POWERPC_603:
- return "603";
- case CPU_SUBTYPE_POWERPC_603e:
- return "603e";
- case CPU_SUBTYPE_POWERPC_603ev:
- return "603ev";
- case CPU_SUBTYPE_POWERPC_604:
- return "604";
- case CPU_SUBTYPE_POWERPC_604e:
- return "604e";
- case CPU_SUBTYPE_POWERPC_620:
- return "620";
- case CPU_SUBTYPE_POWERPC_750:
- return "750";
- case CPU_SUBTYPE_POWERPC_7400:
- return "7400";
- case CPU_SUBTYPE_POWERPC_7450:
- return "7450";
- case CPU_SUBTYPE_POWERPC_970:
- return "970";
- default:;
- }
-
- return "generic";
-}
-#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__))
-StringRef sys::getHostCPUName() {
- std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
- StringRef Content = P ? P->getBuffer() : "";
- return detail::getHostCPUNameForPowerPC(Content);
-}
-#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
-StringRef sys::getHostCPUName() {
- std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
- StringRef Content = P ? P->getBuffer() : "";
- return detail::getHostCPUNameForARM(Content);
-}
-#elif defined(__linux__) && defined(__s390x__)
-StringRef sys::getHostCPUName() {
- std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
- StringRef Content = P ? P->getBuffer() : "";
- return detail::getHostCPUNameForS390x(Content);
-}
-#else
-StringRef sys::getHostCPUName() { return "generic"; }
-#endif
-
-#if defined(__linux__) && defined(__x86_64__)
-// On Linux, the number of physical cores can be computed from /proc/cpuinfo,
-// using the number of unique physical/core id pairs. The following
-// implementation reads the /proc/cpuinfo format on an x86_64 system.
-static int computeHostNumPhysicalCores() {
- // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be
- // mmapped because it appears to have 0 size.
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
- llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo");
- if (std::error_code EC = Text.getError()) {
- llvm::errs() << "Can't read "
- << "/proc/cpuinfo: " << EC.message() << "\n";
- return -1;
- }
- SmallVector<StringRef, 8> strs;
- (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1,
- /*KeepEmpty=*/false);
- int CurPhysicalId = -1;
- int CurCoreId = -1;
- SmallSet<std::pair<int, int>, 32> UniqueItems;
- for (auto &Line : strs) {
- Line = Line.trim();
- if (!Line.startswith("physical id") && !Line.startswith("core id"))
- continue;
- std::pair<StringRef, StringRef> Data = Line.split(':');
- auto Name = Data.first.trim();
- auto Val = Data.second.trim();
- if (Name == "physical id") {
- assert(CurPhysicalId == -1 &&
- "Expected a core id before seeing another physical id");
- Val.getAsInteger(10, CurPhysicalId);
- }
- if (Name == "core id") {
- assert(CurCoreId == -1 &&
- "Expected a physical id before seeing another core id");
- Val.getAsInteger(10, CurCoreId);
- }
- if (CurPhysicalId != -1 && CurCoreId != -1) {
- UniqueItems.insert(std::make_pair(CurPhysicalId, CurCoreId));
- CurPhysicalId = -1;
- CurCoreId = -1;
- }
- }
- return UniqueItems.size();
-}
-#elif defined(__APPLE__) && defined(__x86_64__)
-#include <sys/param.h>
-#include <sys/sysctl.h>
-
-// Gets the number of *physical cores* on the machine.
-static int computeHostNumPhysicalCores() {
- uint32_t count;
- size_t len = sizeof(count);
- sysctlbyname("hw.physicalcpu", &count, &len, NULL, 0);
- if (count < 1) {
- int nm[2];
- nm[0] = CTL_HW;
- nm[1] = HW_AVAILCPU;
- sysctl(nm, 2, &count, &len, NULL, 0);
- if (count < 1)
- return -1;
- }
- return count;
-}
-#else
-// On other systems, return -1 to indicate unknown.
-static int computeHostNumPhysicalCores() { return -1; }
-#endif
-
-int sys::getHostNumPhysicalCores() {
- static int NumCores = computeHostNumPhysicalCores();
- return NumCores;
-}
-
-#if defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64__) || defined(_M_X64)
-bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
- unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
- unsigned MaxLevel;
- union {
- unsigned u[3];
- char c[12];
- } text;
-
- if (getX86CpuIDAndInfo(0, &MaxLevel, text.u + 0, text.u + 2, text.u + 1) ||
- MaxLevel < 1)
- return false;
-
- getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
-
- Features["cmov"] = (EDX >> 15) & 1;
- Features["mmx"] = (EDX >> 23) & 1;
- Features["sse"] = (EDX >> 25) & 1;
- Features["sse2"] = (EDX >> 26) & 1;
-
- Features["sse3"] = (ECX >> 0) & 1;
- Features["pclmul"] = (ECX >> 1) & 1;
- Features["ssse3"] = (ECX >> 9) & 1;
- Features["cx16"] = (ECX >> 13) & 1;
- Features["sse4.1"] = (ECX >> 19) & 1;
- Features["sse4.2"] = (ECX >> 20) & 1;
- Features["movbe"] = (ECX >> 22) & 1;
- Features["popcnt"] = (ECX >> 23) & 1;
- Features["aes"] = (ECX >> 25) & 1;
- Features["rdrnd"] = (ECX >> 30) & 1;
-
- // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
- // indicates that the AVX registers will be saved and restored on context
- // switch, then we have full AVX support.
- bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) &&
- !getX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6);
- // AVX512 requires additional context to be saved by the OS.
- bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
-
- Features["avx"] = HasAVXSave;
- Features["fma"] = ((ECX >> 12) & 1) && HasAVXSave;
- // Only enable XSAVE if OS has enabled support for saving YMM state.
- Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave;
- Features["f16c"] = ((ECX >> 29) & 1) && HasAVXSave;
-
- unsigned MaxExtLevel;
- getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
-
- bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
- !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
- Features["sahf"] = HasExtLeaf1 && ((ECX >> 0) & 1);
- Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1);
- Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1);
- Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1);
- Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave;
- Features["lwp"] = HasExtLeaf1 && ((ECX >> 15) & 1);
- Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave;
- Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1);
- Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1);
-
- Features["64bit"] = HasExtLeaf1 && ((EDX >> 29) & 1);
-
- // Miscellaneous memory related features, detected by
- // using the 0x80000008 leaf of the CPUID instruction
- bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 &&
- !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX);
- Features["clzero"] = HasExtLeaf8 && ((EBX >> 0) & 1);
- Features["wbnoinvd"] = HasExtLeaf8 && ((EBX >> 9) & 1);
-
- bool HasLeaf7 =
- MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
-
- Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1);
- Features["sgx"] = HasLeaf7 && ((EBX >> 2) & 1);
- Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1);
- // AVX2 is only supported if we have the OS save support from AVX.
- Features["avx2"] = HasLeaf7 && ((EBX >> 5) & 1) && HasAVXSave;
- Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1);
- Features["invpcid"] = HasLeaf7 && ((EBX >> 10) & 1);
- Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1);
- // AVX512 is only supported if the OS supports the context save for it.
- Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save;
- Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save;
- Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1);
- Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1);
- Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save;
- Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1);
- Features["clwb"] = HasLeaf7 && ((EBX >> 24) & 1);
- Features["avx512pf"] = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save;
- Features["avx512er"] = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save;
- Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save;
- Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1);
- Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
- Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
-
- Features["prefetchwt1"] = HasLeaf7 && ((ECX >> 0) & 1);
- Features["avx512vbmi"] = HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save;
- Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1);
- Features["waitpkg"] = HasLeaf7 && ((ECX >> 5) & 1);
- Features["avx512vbmi2"] = HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save;
- Features["shstk"] = HasLeaf7 && ((ECX >> 7) & 1);
- Features["gfni"] = HasLeaf7 && ((ECX >> 8) & 1);
- Features["vaes"] = HasLeaf7 && ((ECX >> 9) & 1) && HasAVXSave;
- Features["vpclmulqdq"] = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave;
- Features["avx512vnni"] = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save;
- Features["avx512bitalg"] = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save;
- Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save;
- Features["rdpid"] = HasLeaf7 && ((ECX >> 22) & 1);
- Features["cldemote"] = HasLeaf7 && ((ECX >> 25) & 1);
- Features["movdiri"] = HasLeaf7 && ((ECX >> 27) & 1);
- Features["movdir64b"] = HasLeaf7 && ((ECX >> 28) & 1);
-
- // There are two CPUID leafs which information associated with the pconfig
- // instruction:
- // EAX=0x7, ECX=0x0 indicates the availability of the instruction (via the 18th
- // bit of EDX), while the EAX=0x1b leaf returns information on the
- // availability of specific pconfig leafs.
- // The target feature here only refers to the the first of these two.
- // Users might need to check for the availability of specific pconfig
- // leaves using cpuid, since that information is ignored while
- // detecting features using the "-march=native" flag.
- // For more info, see X86 ISA docs.
- Features["pconfig"] = HasLeaf7 && ((EDX >> 18) & 1);
-
- bool HasLeafD = MaxLevel >= 0xd &&
- !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
-
- // Only enable XSAVE if OS has enabled support for saving YMM state.
- Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave;
- Features["xsavec"] = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave;
- Features["xsaves"] = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave;
-
- bool HasLeaf14 = MaxLevel >= 0x14 &&
- !getX86CpuIDAndInfoEx(0x14, 0x0, &EAX, &EBX, &ECX, &EDX);
-
- Features["ptwrite"] = HasLeaf14 && ((EBX >> 4) & 1);
-
- return true;
-}
-#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
-bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
- std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
- if (!P)
- return false;
-
- SmallVector<StringRef, 32> Lines;
- P->getBuffer().split(Lines, "\n");
-
- SmallVector<StringRef, 32> CPUFeatures;
-
- // Look for the CPU features.
- for (unsigned I = 0, E = Lines.size(); I != E; ++I)
- if (Lines[I].startswith("Features")) {
- Lines[I].split(CPUFeatures, ' ');
- break;
- }
-
-#if defined(__aarch64__)
- // Keep track of which crypto features we have seen
- enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };
- uint32_t crypto = 0;
-#endif
-
- for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
- StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
-#if defined(__aarch64__)
- .Case("asimd", "neon")
- .Case("fp", "fp-armv8")
- .Case("crc32", "crc")
-#else
- .Case("half", "fp16")
- .Case("neon", "neon")
- .Case("vfpv3", "vfp3")
- .Case("vfpv3d16", "d16")
- .Case("vfpv4", "vfp4")
- .Case("idiva", "hwdiv-arm")
- .Case("idivt", "hwdiv")
-#endif
- .Default("");
-
-#if defined(__aarch64__)
- // We need to check crypto separately since we need all of the crypto
- // extensions to enable the subtarget feature
- if (CPUFeatures[I] == "aes")
- crypto |= CAP_AES;
- else if (CPUFeatures[I] == "pmull")
- crypto |= CAP_PMULL;
- else if (CPUFeatures[I] == "sha1")
- crypto |= CAP_SHA1;
- else if (CPUFeatures[I] == "sha2")
- crypto |= CAP_SHA2;
-#endif
-
- if (LLVMFeatureStr != "")
- Features[LLVMFeatureStr] = true;
- }
-
-#if defined(__aarch64__)
- // If we have all crypto bits we can add the feature
- if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2))
- Features["crypto"] = true;
-#endif
-
- return true;
-}
-#else
-bool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; }
-#endif
-
-std::string sys::getProcessTriple() {
- std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE);
- Triple PT(Triple::normalize(TargetTripleString));
-
- if (sizeof(void *) == 8 && PT.isArch32Bit())
- PT = PT.get64BitArchVariant();
- if (sizeof(void *) == 4 && PT.isArch64Bit())
- PT = PT.get32BitArchVariant();
-
- return PT.str();
-}
diff --git a/gnu/llvm/lib/Support/InitLLVM.cpp b/gnu/llvm/lib/Support/InitLLVM.cpp
deleted file mode 100644
index c008d0455c9..00000000000
--- a/gnu/llvm/lib/Support/InitLLVM.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-//===-- InitLLVM.cpp -----------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/Signals.h"
-#include <string>
-
-#ifdef _WIN32
-#include "Windows/WindowsSupport.h"
-#endif
-
-using namespace llvm;
-using namespace llvm::sys;
-
-InitLLVM::InitLLVM(int &Argc, const char **&Argv) : StackPrinter(Argc, Argv) {
- sys::PrintStackTraceOnErrorSignal(Argv[0]);
-
-#ifdef _WIN32
- // We use UTF-8 as the internal character encoding. On Windows,
- // arguments passed to main() may not be encoded in UTF-8. In order
- // to reliably detect encoding of command line arguments, we use an
- // Windows API to obtain arguments, convert them to UTF-8, and then
- // write them back to the Argv vector.
- //
- // There's probably other way to do the same thing (e.g. using
- // wmain() instead of main()), but this way seems less intrusive
- // than that.
- std::string Banner = std::string(Argv[0]) + ": ";
- ExitOnError ExitOnErr(Banner);
-
- ExitOnErr(errorCodeToError(windows::GetCommandLineArguments(Args, Alloc)));
-
- // GetCommandLineArguments doesn't terminate the vector with a
- // nullptr. Do it to make it compatible with the real argv.
- Args.push_back(nullptr);
-
- Argc = Args.size() - 1;
- Argv = Args.data();
-#endif
-}
-
-InitLLVM::~InitLLVM() { llvm_shutdown(); }
diff --git a/gnu/llvm/lib/Support/IntEqClasses.cpp b/gnu/llvm/lib/Support/IntEqClasses.cpp
deleted file mode 100644
index cb6e3a19e8d..00000000000
--- a/gnu/llvm/lib/Support/IntEqClasses.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-//===-- llvm/ADT/IntEqClasses.cpp - Equivalence Classes of Integers -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Equivalence classes for small integers. This is a mapping of the integers
-// 0 .. N-1 into M equivalence classes numbered 0 .. M-1.
-//
-// Initially each integer has its own equivalence class. Classes are joined by
-// passing a representative member of each class to join().
-//
-// Once the classes are built, compress() will number them 0 .. M-1 and prevent
-// further changes.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/IntEqClasses.h"
-
-using namespace llvm;
-
-void IntEqClasses::grow(unsigned N) {
- assert(NumClasses == 0 && "grow() called after compress().");
- EC.reserve(N);
- while (EC.size() < N)
- EC.push_back(EC.size());
-}
-
-unsigned IntEqClasses::join(unsigned a, unsigned b) {
- assert(NumClasses == 0 && "join() called after compress().");
- unsigned eca = EC[a];
- unsigned ecb = EC[b];
- // Update pointers while searching for the leaders, compressing the paths
- // incrementally. The larger leader will eventually be updated, joining the
- // classes.
- while (eca != ecb)
- if (eca < ecb) {
- EC[b] = eca;
- b = ecb;
- ecb = EC[b];
- } else {
- EC[a] = ecb;
- a = eca;
- eca = EC[a];
- }
-
- return eca;
-}
-
-unsigned IntEqClasses::findLeader(unsigned a) const {
- assert(NumClasses == 0 && "findLeader() called after compress().");
- while (a != EC[a])
- a = EC[a];
- return a;
-}
-
-void IntEqClasses::compress() {
- if (NumClasses)
- return;
- for (unsigned i = 0, e = EC.size(); i != e; ++i)
- EC[i] = (EC[i] == i) ? NumClasses++ : EC[EC[i]];
-}
-
-void IntEqClasses::uncompress() {
- if (!NumClasses)
- return;
- SmallVector<unsigned, 8> Leader;
- for (unsigned i = 0, e = EC.size(); i != e; ++i)
- if (EC[i] < Leader.size())
- EC[i] = Leader[EC[i]];
- else
- Leader.push_back(EC[i] = i);
- NumClasses = 0;
-}
diff --git a/gnu/llvm/lib/Support/IntervalMap.cpp b/gnu/llvm/lib/Support/IntervalMap.cpp
deleted file mode 100644
index e11a7f2eb84..00000000000
--- a/gnu/llvm/lib/Support/IntervalMap.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-//===- lib/Support/IntervalMap.cpp - A sorted interval map ----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the few non-templated functions in IntervalMap.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/IntervalMap.h"
-
-namespace llvm {
-namespace IntervalMapImpl {
-
-void Path::replaceRoot(void *Root, unsigned Size, IdxPair Offsets) {
- assert(!path.empty() && "Can't replace missing root");
- path.front() = Entry(Root, Size, Offsets.first);
- path.insert(path.begin() + 1, Entry(subtree(0), Offsets.second));
-}
-
-NodeRef Path::getLeftSibling(unsigned Level) const {
- // The root has no siblings.
- if (Level == 0)
- return NodeRef();
-
- // Go up the tree until we can go left.
- unsigned l = Level - 1;
- while (l && path[l].offset == 0)
- --l;
-
- // We can't go left.
- if (path[l].offset == 0)
- return NodeRef();
-
- // NR is the subtree containing our left sibling.
- NodeRef NR = path[l].subtree(path[l].offset - 1);
-
- // Keep right all the way down.
- for (++l; l != Level; ++l)
- NR = NR.subtree(NR.size() - 1);
- return NR;
-}
-
-void Path::moveLeft(unsigned Level) {
- assert(Level != 0 && "Cannot move the root node");
-
- // Go up the tree until we can go left.
- unsigned l = 0;
- if (valid()) {
- l = Level - 1;
- while (path[l].offset == 0) {
- assert(l != 0 && "Cannot move beyond begin()");
- --l;
- }
- } else if (height() < Level)
- // end() may have created a height=0 path.
- path.resize(Level + 1, Entry(nullptr, 0, 0));
-
- // NR is the subtree containing our left sibling.
- --path[l].offset;
- NodeRef NR = subtree(l);
-
- // Get the rightmost node in the subtree.
- for (++l; l != Level; ++l) {
- path[l] = Entry(NR, NR.size() - 1);
- NR = NR.subtree(NR.size() - 1);
- }
- path[l] = Entry(NR, NR.size() - 1);
-}
-
-NodeRef Path::getRightSibling(unsigned Level) const {
- // The root has no siblings.
- if (Level == 0)
- return NodeRef();
-
- // Go up the tree until we can go right.
- unsigned l = Level - 1;
- while (l && atLastEntry(l))
- --l;
-
- // We can't go right.
- if (atLastEntry(l))
- return NodeRef();
-
- // NR is the subtree containing our right sibling.
- NodeRef NR = path[l].subtree(path[l].offset + 1);
-
- // Keep left all the way down.
- for (++l; l != Level; ++l)
- NR = NR.subtree(0);
- return NR;
-}
-
-void Path::moveRight(unsigned Level) {
- assert(Level != 0 && "Cannot move the root node");
-
- // Go up the tree until we can go right.
- unsigned l = Level - 1;
- while (l && atLastEntry(l))
- --l;
-
- // NR is the subtree containing our right sibling. If we hit end(), we have
- // offset(0) == node(0).size().
- if (++path[l].offset == path[l].size)
- return;
- NodeRef NR = subtree(l);
-
- for (++l; l != Level; ++l) {
- path[l] = Entry(NR, 0);
- NR = NR.subtree(0);
- }
- path[l] = Entry(NR, 0);
-}
-
-
-IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity,
- const unsigned *CurSize, unsigned NewSize[],
- unsigned Position, bool Grow) {
- assert(Elements + Grow <= Nodes * Capacity && "Not enough room for elements");
- assert(Position <= Elements && "Invalid position");
- if (!Nodes)
- return IdxPair();
-
- // Trivial algorithm: left-leaning even distribution.
- const unsigned PerNode = (Elements + Grow) / Nodes;
- const unsigned Extra = (Elements + Grow) % Nodes;
- IdxPair PosPair = IdxPair(Nodes, 0);
- unsigned Sum = 0;
- for (unsigned n = 0; n != Nodes; ++n) {
- Sum += NewSize[n] = PerNode + (n < Extra);
- if (PosPair.first == Nodes && Sum > Position)
- PosPair = IdxPair(n, Position - (Sum - NewSize[n]));
- }
- assert(Sum == Elements + Grow && "Bad distribution sum");
-
- // Subtract the Grow element that was added.
- if (Grow) {
- assert(PosPair.first < Nodes && "Bad algebra");
- assert(NewSize[PosPair.first] && "Too few elements to need Grow");
- --NewSize[PosPair.first];
- }
-
-#ifndef NDEBUG
- Sum = 0;
- for (unsigned n = 0; n != Nodes; ++n) {
- assert(NewSize[n] <= Capacity && "Overallocated node");
- Sum += NewSize[n];
- }
- assert(Sum == Elements && "Bad distribution sum");
-#endif
-
- return PosPair;
-}
-
-} // namespace IntervalMapImpl
-} // namespace llvm
-
diff --git a/gnu/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp b/gnu/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp
deleted file mode 100644
index e55dcd76180..00000000000
--- a/gnu/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp
+++ /dev/null
@@ -1,322 +0,0 @@
-//===----------------- ItaniumManglingCanonicalizer.cpp -------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ItaniumManglingCanonicalizer.h"
-
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Demangle/ItaniumDemangle.h"
-#include "llvm/Support/Allocator.h"
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/StringRef.h"
-
-using namespace llvm;
-using llvm::itanium_demangle::ForwardTemplateReference;
-using llvm::itanium_demangle::Node;
-using llvm::itanium_demangle::NodeKind;
-
-namespace {
-struct FoldingSetNodeIDBuilder {
- llvm::FoldingSetNodeID &ID;
- void operator()(const Node *P) { ID.AddPointer(P); }
- void operator()(StringView Str) {
- ID.AddString(llvm::StringRef(Str.begin(), Str.size()));
- }
- template<typename T>
- typename std::enable_if<std::is_integral<T>::value ||
- std::is_enum<T>::value>::type
- operator()(T V) {
- ID.AddInteger((unsigned long long)V);
- }
- void operator()(itanium_demangle::NodeOrString NS) {
- if (NS.isNode()) {
- ID.AddInteger(0);
- (*this)(NS.asNode());
- } else if (NS.isString()) {
- ID.AddInteger(1);
- (*this)(NS.asString());
- } else {
- ID.AddInteger(2);
- }
- }
- void operator()(itanium_demangle::NodeArray A) {
- ID.AddInteger(A.size());
- for (const Node *N : A)
- (*this)(N);
- }
-};
-
-template<typename ...T>
-void profileCtor(llvm::FoldingSetNodeID &ID, Node::Kind K, T ...V) {
- FoldingSetNodeIDBuilder Builder = {ID};
- Builder(K);
- int VisitInOrder[] = {
- (Builder(V), 0) ...,
- 0 // Avoid empty array if there are no arguments.
- };
- (void)VisitInOrder;
-}
-
-// FIXME: Convert this to a generic lambda when possible.
-template<typename NodeT> struct ProfileSpecificNode {
- FoldingSetNodeID &ID;
- template<typename ...T> void operator()(T ...V) {
- profileCtor(ID, NodeKind<NodeT>::Kind, V...);
- }
-};
-
-struct ProfileNode {
- FoldingSetNodeID &ID;
- template<typename NodeT> void operator()(const NodeT *N) {
- N->match(ProfileSpecificNode<NodeT>{ID});
- }
-};
-
-template<> void ProfileNode::operator()(const ForwardTemplateReference *N) {
- llvm_unreachable("should never canonicalize a ForwardTemplateReference");
-}
-
-void profileNode(llvm::FoldingSetNodeID &ID, const Node *N) {
- N->visit(ProfileNode{ID});
-}
-
-class FoldingNodeAllocator {
- class alignas(alignof(Node *)) NodeHeader : public llvm::FoldingSetNode {
- public:
- // 'Node' in this context names the injected-class-name of the base class.
- itanium_demangle::Node *getNode() {
- return reinterpret_cast<itanium_demangle::Node *>(this + 1);
- }
- void Profile(llvm::FoldingSetNodeID &ID) { profileNode(ID, getNode()); }
- };
-
- BumpPtrAllocator RawAlloc;
- llvm::FoldingSet<NodeHeader> Nodes;
-
-public:
- void reset() {}
-
- template <typename T, typename... Args>
- std::pair<Node *, bool> getOrCreateNode(bool CreateNewNodes, Args &&... As) {
- // FIXME: Don't canonicalize forward template references for now, because
- // they contain state (the resolved template node) that's not known at their
- // point of creation.
- if (std::is_same<T, ForwardTemplateReference>::value) {
- // Note that we don't use if-constexpr here and so we must still write
- // this code in a generic form.
- return {new (RawAlloc.Allocate(sizeof(T), alignof(T)))
- T(std::forward<Args>(As)...),
- true};
- }
-
- llvm::FoldingSetNodeID ID;
- profileCtor(ID, NodeKind<T>::Kind, As...);
-
- void *InsertPos;
- if (NodeHeader *Existing = Nodes.FindNodeOrInsertPos(ID, InsertPos))
- return {static_cast<T*>(Existing->getNode()), false};
-
- if (!CreateNewNodes)
- return {nullptr, true};
-
- static_assert(alignof(T) <= alignof(NodeHeader),
- "underaligned node header for specific node kind");
- void *Storage =
- RawAlloc.Allocate(sizeof(NodeHeader) + sizeof(T), alignof(NodeHeader));
- NodeHeader *New = new (Storage) NodeHeader;
- T *Result = new (New->getNode()) T(std::forward<Args>(As)...);
- Nodes.InsertNode(New, InsertPos);
- return {Result, true};
- }
-
- template<typename T, typename... Args>
- Node *makeNode(Args &&...As) {
- return getOrCreateNode<T>(true, std::forward<Args>(As)...).first;
- }
-
- void *allocateNodeArray(size_t sz) {
- return RawAlloc.Allocate(sizeof(Node *) * sz, alignof(Node *));
- }
-};
-
-class CanonicalizerAllocator : public FoldingNodeAllocator {
- Node *MostRecentlyCreated = nullptr;
- Node *TrackedNode = nullptr;
- bool TrackedNodeIsUsed = false;
- bool CreateNewNodes = true;
- llvm::SmallDenseMap<Node*, Node*, 32> Remappings;
-
- template<typename T, typename ...Args> Node *makeNodeSimple(Args &&...As) {
- std::pair<Node *, bool> Result =
- getOrCreateNode<T>(CreateNewNodes, std::forward<Args>(As)...);
- if (Result.second) {
- // Node is new. Make a note of that.
- MostRecentlyCreated = Result.first;
- } else if (Result.first) {
- // Node is pre-existing; check if it's in our remapping table.
- if (auto *N = Remappings.lookup(Result.first)) {
- Result.first = N;
- assert(Remappings.find(Result.first) == Remappings.end() &&
- "should never need multiple remap steps");
- }
- if (Result.first == TrackedNode)
- TrackedNodeIsUsed = true;
- }
- return Result.first;
- }
-
- /// Helper to allow makeNode to be partially-specialized on T.
- template<typename T> struct MakeNodeImpl {
- CanonicalizerAllocator &Self;
- template<typename ...Args> Node *make(Args &&...As) {
- return Self.makeNodeSimple<T>(std::forward<Args>(As)...);
- }
- };
-
-public:
- template<typename T, typename ...Args> Node *makeNode(Args &&...As) {
- return MakeNodeImpl<T>{*this}.make(std::forward<Args>(As)...);
- }
-
- void reset() { MostRecentlyCreated = nullptr; }
-
- void setCreateNewNodes(bool CNN) { CreateNewNodes = CNN; }
-
- void addRemapping(Node *A, Node *B) {
- // Note, we don't need to check whether B is also remapped, because if it
- // was we would have already remapped it when building it.
- Remappings.insert(std::make_pair(A, B));
- }
-
- bool isMostRecentlyCreated(Node *N) const { return MostRecentlyCreated == N; }
-
- void trackUsesOf(Node *N) {
- TrackedNode = N;
- TrackedNodeIsUsed = false;
- }
- bool trackedNodeIsUsed() const { return TrackedNodeIsUsed; }
-};
-
-/// Convert St3foo to NSt3fooE so that equivalences naming one also affect the
-/// other.
-template<>
-struct CanonicalizerAllocator::MakeNodeImpl<
- itanium_demangle::StdQualifiedName> {
- CanonicalizerAllocator &Self;
- Node *make(Node *Child) {
- Node *StdNamespace = Self.makeNode<itanium_demangle::NameType>("std");
- if (!StdNamespace)
- return nullptr;
- return Self.makeNode<itanium_demangle::NestedName>(StdNamespace, Child);
- }
-};
-
-// FIXME: Also expand built-in substitutions?
-
-using CanonicalizingDemangler =
- itanium_demangle::ManglingParser<CanonicalizerAllocator>;
-}
-
-struct ItaniumManglingCanonicalizer::Impl {
- CanonicalizingDemangler Demangler = {nullptr, nullptr};
-};
-
-ItaniumManglingCanonicalizer::ItaniumManglingCanonicalizer() : P(new Impl) {}
-ItaniumManglingCanonicalizer::~ItaniumManglingCanonicalizer() { delete P; }
-
-ItaniumManglingCanonicalizer::EquivalenceError
-ItaniumManglingCanonicalizer::addEquivalence(FragmentKind Kind, StringRef First,
- StringRef Second) {
- auto &Alloc = P->Demangler.ASTAllocator;
- Alloc.setCreateNewNodes(true);
-
- auto Parse = [&](StringRef Str) {
- P->Demangler.reset(Str.begin(), Str.end());
- Node *N = nullptr;
- switch (Kind) {
- // A <name>, with minor extensions to allow arbitrary namespace and
- // template names that can't easily be written as <name>s.
- case FragmentKind::Name:
- // Very special case: allow "St" as a shorthand for "3std". It's not
- // valid as a <name> mangling, but is nonetheless the most natural
- // way to name the 'std' namespace.
- if (Str.size() == 2 && P->Demangler.consumeIf("St"))
- N = P->Demangler.make<itanium_demangle::NameType>("std");
- // We permit substitutions to name templates without their template
- // arguments. This mostly just falls out, as almost all template names
- // are valid as <name>s, but we also want to parse <substitution>s as
- // <name>s, even though they're not.
- else if (Str.startswith("S"))
- // Parse the substitution and optional following template arguments.
- N = P->Demangler.parseType();
- else
- N = P->Demangler.parseName();
- break;
-
- // A <type>.
- case FragmentKind::Type:
- N = P->Demangler.parseType();
- break;
-
- // An <encoding>.
- case FragmentKind::Encoding:
- N = P->Demangler.parseEncoding();
- break;
- }
-
- // If we have trailing junk, the mangling is invalid.
- if (P->Demangler.numLeft() != 0)
- N = nullptr;
-
- // If any node was created after N, then we cannot safely remap it because
- // it might already be in use by another node.
- return std::make_pair(N, Alloc.isMostRecentlyCreated(N));
- };
-
- Node *FirstNode, *SecondNode;
- bool FirstIsNew, SecondIsNew;
-
- std::tie(FirstNode, FirstIsNew) = Parse(First);
- if (!FirstNode)
- return EquivalenceError::InvalidFirstMangling;
-
- Alloc.trackUsesOf(FirstNode);
- std::tie(SecondNode, SecondIsNew) = Parse(Second);
- if (!SecondNode)
- return EquivalenceError::InvalidSecondMangling;
-
- // If they're already equivalent, there's nothing to do.
- if (FirstNode == SecondNode)
- return EquivalenceError::Success;
-
- if (FirstIsNew && !Alloc.trackedNodeIsUsed())
- Alloc.addRemapping(FirstNode, SecondNode);
- else if (SecondIsNew)
- Alloc.addRemapping(SecondNode, FirstNode);
- else
- return EquivalenceError::ManglingAlreadyUsed;
-
- return EquivalenceError::Success;
-}
-
-ItaniumManglingCanonicalizer::Key
-ItaniumManglingCanonicalizer::canonicalize(StringRef Mangling) {
- P->Demangler.ASTAllocator.setCreateNewNodes(true);
- P->Demangler.reset(Mangling.begin(), Mangling.end());
- return reinterpret_cast<Key>(P->Demangler.parse());
-}
-
-ItaniumManglingCanonicalizer::Key
-ItaniumManglingCanonicalizer::lookup(StringRef Mangling) {
- P->Demangler.ASTAllocator.setCreateNewNodes(false);
- P->Demangler.reset(Mangling.begin(), Mangling.end());
- return reinterpret_cast<Key>(P->Demangler.parse());
-}
diff --git a/gnu/llvm/lib/Support/JSON.cpp b/gnu/llvm/lib/Support/JSON.cpp
deleted file mode 100644
index 07a55681491..00000000000
--- a/gnu/llvm/lib/Support/JSON.cpp
+++ /dev/null
@@ -1,699 +0,0 @@
-//=== JSON.cpp - JSON value, parsing and serialization - C++ -----------*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===---------------------------------------------------------------------===//
-
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/Format.h"
-#include <cctype>
-
-namespace llvm {
-namespace json {
-
-Value &Object::operator[](const ObjectKey &K) {
- return try_emplace(K, nullptr).first->getSecond();
-}
-Value &Object::operator[](ObjectKey &&K) {
- return try_emplace(std::move(K), nullptr).first->getSecond();
-}
-Value *Object::get(StringRef K) {
- auto I = find(K);
- if (I == end())
- return nullptr;
- return &I->second;
-}
-const Value *Object::get(StringRef K) const {
- auto I = find(K);
- if (I == end())
- return nullptr;
- return &I->second;
-}
-llvm::Optional<std::nullptr_t> Object::getNull(StringRef K) const {
- if (auto *V = get(K))
- return V->getAsNull();
- return llvm::None;
-}
-llvm::Optional<bool> Object::getBoolean(StringRef K) const {
- if (auto *V = get(K))
- return V->getAsBoolean();
- return llvm::None;
-}
-llvm::Optional<double> Object::getNumber(StringRef K) const {
- if (auto *V = get(K))
- return V->getAsNumber();
- return llvm::None;
-}
-llvm::Optional<int64_t> Object::getInteger(StringRef K) const {
- if (auto *V = get(K))
- return V->getAsInteger();
- return llvm::None;
-}
-llvm::Optional<llvm::StringRef> Object::getString(StringRef K) const {
- if (auto *V = get(K))
- return V->getAsString();
- return llvm::None;
-}
-const json::Object *Object::getObject(StringRef K) const {
- if (auto *V = get(K))
- return V->getAsObject();
- return nullptr;
-}
-json::Object *Object::getObject(StringRef K) {
- if (auto *V = get(K))
- return V->getAsObject();
- return nullptr;
-}
-const json::Array *Object::getArray(StringRef K) const {
- if (auto *V = get(K))
- return V->getAsArray();
- return nullptr;
-}
-json::Array *Object::getArray(StringRef K) {
- if (auto *V = get(K))
- return V->getAsArray();
- return nullptr;
-}
-bool operator==(const Object &LHS, const Object &RHS) {
- if (LHS.size() != RHS.size())
- return false;
- for (const auto &L : LHS) {
- auto R = RHS.find(L.first);
- if (R == RHS.end() || L.second != R->second)
- return false;
- }
- return true;
-}
-
-Array::Array(std::initializer_list<Value> Elements) {
- V.reserve(Elements.size());
- for (const Value &V : Elements) {
- emplace_back(nullptr);
- back().moveFrom(std::move(V));
- }
-}
-
-Value::Value(std::initializer_list<Value> Elements)
- : Value(json::Array(Elements)) {}
-
-void Value::copyFrom(const Value &M) {
- Type = M.Type;
- switch (Type) {
- case T_Null:
- case T_Boolean:
- case T_Double:
- case T_Integer:
- memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer));
- break;
- case T_StringRef:
- create<StringRef>(M.as<StringRef>());
- break;
- case T_String:
- create<std::string>(M.as<std::string>());
- break;
- case T_Object:
- create<json::Object>(M.as<json::Object>());
- break;
- case T_Array:
- create<json::Array>(M.as<json::Array>());
- break;
- }
-}
-
-void Value::moveFrom(const Value &&M) {
- Type = M.Type;
- switch (Type) {
- case T_Null:
- case T_Boolean:
- case T_Double:
- case T_Integer:
- memcpy(Union.buffer, M.Union.buffer, sizeof(Union.buffer));
- break;
- case T_StringRef:
- create<StringRef>(M.as<StringRef>());
- break;
- case T_String:
- create<std::string>(std::move(M.as<std::string>()));
- M.Type = T_Null;
- break;
- case T_Object:
- create<json::Object>(std::move(M.as<json::Object>()));
- M.Type = T_Null;
- break;
- case T_Array:
- create<json::Array>(std::move(M.as<json::Array>()));
- M.Type = T_Null;
- break;
- }
-}
-
-void Value::destroy() {
- switch (Type) {
- case T_Null:
- case T_Boolean:
- case T_Double:
- case T_Integer:
- break;
- case T_StringRef:
- as<StringRef>().~StringRef();
- break;
- case T_String:
- as<std::string>().~basic_string();
- break;
- case T_Object:
- as<json::Object>().~Object();
- break;
- case T_Array:
- as<json::Array>().~Array();
- break;
- }
-}
-
-bool operator==(const Value &L, const Value &R) {
- if (L.kind() != R.kind())
- return false;
- switch (L.kind()) {
- case Value::Null:
- return *L.getAsNull() == *R.getAsNull();
- case Value::Boolean:
- return *L.getAsBoolean() == *R.getAsBoolean();
- case Value::Number:
- // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323
- // The same integer must convert to the same double, per the standard.
- // However we see 64-vs-80-bit precision comparisons with gcc-7 -O3 -m32.
- // So we avoid floating point promotion for exact comparisons.
- if (L.Type == Value::T_Integer || R.Type == Value::T_Integer)
- return L.getAsInteger() == R.getAsInteger();
- return *L.getAsNumber() == *R.getAsNumber();
- case Value::String:
- return *L.getAsString() == *R.getAsString();
- case Value::Array:
- return *L.getAsArray() == *R.getAsArray();
- case Value::Object:
- return *L.getAsObject() == *R.getAsObject();
- }
- llvm_unreachable("Unknown value kind");
-}
-
-namespace {
-// Simple recursive-descent JSON parser.
-class Parser {
-public:
- Parser(StringRef JSON)
- : Start(JSON.begin()), P(JSON.begin()), End(JSON.end()) {}
-
- bool checkUTF8() {
- size_t ErrOffset;
- if (isUTF8(StringRef(Start, End - Start), &ErrOffset))
- return true;
- P = Start + ErrOffset; // For line/column calculation.
- return parseError("Invalid UTF-8 sequence");
- }
-
- bool parseValue(Value &Out);
-
- bool assertEnd() {
- eatWhitespace();
- if (P == End)
- return true;
- return parseError("Text after end of document");
- }
-
- Error takeError() {
- assert(Err);
- return std::move(*Err);
- }
-
-private:
- void eatWhitespace() {
- while (P != End && (*P == ' ' || *P == '\r' || *P == '\n' || *P == '\t'))
- ++P;
- }
-
- // On invalid syntax, parseX() functions return false and set Err.
- bool parseNumber(char First, Value &Out);
- bool parseString(std::string &Out);
- bool parseUnicode(std::string &Out);
- bool parseError(const char *Msg); // always returns false
-
- char next() { return P == End ? 0 : *P++; }
- char peek() { return P == End ? 0 : *P; }
- static bool isNumber(char C) {
- return C == '0' || C == '1' || C == '2' || C == '3' || C == '4' ||
- C == '5' || C == '6' || C == '7' || C == '8' || C == '9' ||
- C == 'e' || C == 'E' || C == '+' || C == '-' || C == '.';
- }
-
- Optional<Error> Err;
- const char *Start, *P, *End;
-};
-
-bool Parser::parseValue(Value &Out) {
- eatWhitespace();
- if (P == End)
- return parseError("Unexpected EOF");
- switch (char C = next()) {
- // Bare null/true/false are easy - first char identifies them.
- case 'n':
- Out = nullptr;
- return (next() == 'u' && next() == 'l' && next() == 'l') ||
- parseError("Invalid JSON value (null?)");
- case 't':
- Out = true;
- return (next() == 'r' && next() == 'u' && next() == 'e') ||
- parseError("Invalid JSON value (true?)");
- case 'f':
- Out = false;
- return (next() == 'a' && next() == 'l' && next() == 's' && next() == 'e') ||
- parseError("Invalid JSON value (false?)");
- case '"': {
- std::string S;
- if (parseString(S)) {
- Out = std::move(S);
- return true;
- }
- return false;
- }
- case '[': {
- Out = Array{};
- Array &A = *Out.getAsArray();
- eatWhitespace();
- if (peek() == ']') {
- ++P;
- return true;
- }
- for (;;) {
- A.emplace_back(nullptr);
- if (!parseValue(A.back()))
- return false;
- eatWhitespace();
- switch (next()) {
- case ',':
- eatWhitespace();
- continue;
- case ']':
- return true;
- default:
- return parseError("Expected , or ] after array element");
- }
- }
- }
- case '{': {
- Out = Object{};
- Object &O = *Out.getAsObject();
- eatWhitespace();
- if (peek() == '}') {
- ++P;
- return true;
- }
- for (;;) {
- if (next() != '"')
- return parseError("Expected object key");
- std::string K;
- if (!parseString(K))
- return false;
- eatWhitespace();
- if (next() != ':')
- return parseError("Expected : after object key");
- eatWhitespace();
- if (!parseValue(O[std::move(K)]))
- return false;
- eatWhitespace();
- switch (next()) {
- case ',':
- eatWhitespace();
- continue;
- case '}':
- return true;
- default:
- return parseError("Expected , or } after object property");
- }
- }
- }
- default:
- if (isNumber(C))
- return parseNumber(C, Out);
- return parseError("Invalid JSON value");
- }
-}
-
-bool Parser::parseNumber(char First, Value &Out) {
- // Read the number into a string. (Must be null-terminated for strto*).
- SmallString<24> S;
- S.push_back(First);
- while (isNumber(peek()))
- S.push_back(next());
- char *End;
- // Try first to parse as integer, and if so preserve full 64 bits.
- // strtoll returns long long >= 64 bits, so check it's in range too.
- auto I = std::strtoll(S.c_str(), &End, 10);
- if (End == S.end() && I >= std::numeric_limits<int64_t>::min() &&
- I <= std::numeric_limits<int64_t>::max()) {
- Out = int64_t(I);
- return true;
- }
- // If it's not an integer
- Out = std::strtod(S.c_str(), &End);
- return End == S.end() || parseError("Invalid JSON value (number?)");
-}
-
-bool Parser::parseString(std::string &Out) {
- // leading quote was already consumed.
- for (char C = next(); C != '"'; C = next()) {
- if (LLVM_UNLIKELY(P == End))
- return parseError("Unterminated string");
- if (LLVM_UNLIKELY((C & 0x1f) == C))
- return parseError("Control character in string");
- if (LLVM_LIKELY(C != '\\')) {
- Out.push_back(C);
- continue;
- }
- // Handle escape sequence.
- switch (C = next()) {
- case '"':
- case '\\':
- case '/':
- Out.push_back(C);
- break;
- case 'b':
- Out.push_back('\b');
- break;
- case 'f':
- Out.push_back('\f');
- break;
- case 'n':
- Out.push_back('\n');
- break;
- case 'r':
- Out.push_back('\r');
- break;
- case 't':
- Out.push_back('\t');
- break;
- case 'u':
- if (!parseUnicode(Out))
- return false;
- break;
- default:
- return parseError("Invalid escape sequence");
- }
- }
- return true;
-}
-
-static void encodeUtf8(uint32_t Rune, std::string &Out) {
- if (Rune < 0x80) {
- Out.push_back(Rune & 0x7F);
- } else if (Rune < 0x800) {
- uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6);
- uint8_t SecondByte = 0x80 | (Rune & 0x3F);
- Out.push_back(FirstByte);
- Out.push_back(SecondByte);
- } else if (Rune < 0x10000) {
- uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12);
- uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6);
- uint8_t ThirdByte = 0x80 | (Rune & 0x3F);
- Out.push_back(FirstByte);
- Out.push_back(SecondByte);
- Out.push_back(ThirdByte);
- } else if (Rune < 0x110000) {
- uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18);
- uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12);
- uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6);
- uint8_t FourthByte = 0x80 | (Rune & 0x3F);
- Out.push_back(FirstByte);
- Out.push_back(SecondByte);
- Out.push_back(ThirdByte);
- Out.push_back(FourthByte);
- } else {
- llvm_unreachable("Invalid codepoint");
- }
-}
-
-// Parse a UTF-16 \uNNNN escape sequence. "\u" has already been consumed.
-// May parse several sequential escapes to ensure proper surrogate handling.
-// We do not use ConvertUTF.h, it can't accept and replace unpaired surrogates.
-// These are invalid Unicode but valid JSON (RFC 8259, section 8.2).
-bool Parser::parseUnicode(std::string &Out) {
- // Invalid UTF is not a JSON error (RFC 8529§8.2). It gets replaced by U+FFFD.
- auto Invalid = [&] { Out.append(/* UTF-8 */ {'\xef', '\xbf', '\xbd'}); };
- // Decodes 4 hex digits from the stream into Out, returns false on error.
- auto Parse4Hex = [this](uint16_t &Out) -> bool {
- Out = 0;
- char Bytes[] = {next(), next(), next(), next()};
- for (unsigned char C : Bytes) {
- if (!std::isxdigit(C))
- return parseError("Invalid \\u escape sequence");
- Out <<= 4;
- Out |= (C > '9') ? (C & ~0x20) - 'A' + 10 : (C - '0');
- }
- return true;
- };
- uint16_t First; // UTF-16 code unit from the first \u escape.
- if (!Parse4Hex(First))
- return false;
-
- // We loop to allow proper surrogate-pair error handling.
- while (true) {
- // Case 1: the UTF-16 code unit is already a codepoint in the BMP.
- if (LLVM_LIKELY(First < 0xD800 || First >= 0xE000)) {
- encodeUtf8(First, Out);
- return true;
- }
-
- // Case 2: it's an (unpaired) trailing surrogate.
- if (LLVM_UNLIKELY(First >= 0xDC00)) {
- Invalid();
- return true;
- }
-
- // Case 3: it's a leading surrogate. We expect a trailing one next.
- // Case 3a: there's no trailing \u escape. Don't advance in the stream.
- if (LLVM_UNLIKELY(P + 2 > End || *P != '\\' || *(P + 1) != 'u')) {
- Invalid(); // Leading surrogate was unpaired.
- return true;
- }
- P += 2;
- uint16_t Second;
- if (!Parse4Hex(Second))
- return false;
- // Case 3b: there was another \u escape, but it wasn't a trailing surrogate.
- if (LLVM_UNLIKELY(Second < 0xDC00 || Second >= 0xE000)) {
- Invalid(); // Leading surrogate was unpaired.
- First = Second; // Second escape still needs to be processed.
- continue;
- }
- // Case 3c: a valid surrogate pair encoding an astral codepoint.
- encodeUtf8(0x10000 | ((First - 0xD800) << 10) | (Second - 0xDC00), Out);
- return true;
- }
-}
-
-bool Parser::parseError(const char *Msg) {
- int Line = 1;
- const char *StartOfLine = Start;
- for (const char *X = Start; X < P; ++X) {
- if (*X == 0x0A) {
- ++Line;
- StartOfLine = X + 1;
- }
- }
- Err.emplace(
- llvm::make_unique<ParseError>(Msg, Line, P - StartOfLine, P - Start));
- return false;
-}
-} // namespace
-
-Expected<Value> parse(StringRef JSON) {
- Parser P(JSON);
- Value E = nullptr;
- if (P.checkUTF8())
- if (P.parseValue(E))
- if (P.assertEnd())
- return std::move(E);
- return P.takeError();
-}
-char ParseError::ID = 0;
-
-static std::vector<const Object::value_type *> sortedElements(const Object &O) {
- std::vector<const Object::value_type *> Elements;
- for (const auto &E : O)
- Elements.push_back(&E);
- llvm::sort(Elements,
- [](const Object::value_type *L, const Object::value_type *R) {
- return L->first < R->first;
- });
- return Elements;
-}
-
-bool isUTF8(llvm::StringRef S, size_t *ErrOffset) {
- // Fast-path for ASCII, which is valid UTF-8.
- if (LLVM_LIKELY(isASCII(S)))
- return true;
-
- const UTF8 *Data = reinterpret_cast<const UTF8 *>(S.data()), *Rest = Data;
- if (LLVM_LIKELY(isLegalUTF8String(&Rest, Data + S.size())))
- return true;
-
- if (ErrOffset)
- *ErrOffset = Rest - Data;
- return false;
-}
-
-std::string fixUTF8(llvm::StringRef S) {
- // This isn't particularly efficient, but is only for error-recovery.
- std::vector<UTF32> Codepoints(S.size()); // 1 codepoint per byte suffices.
- const UTF8 *In8 = reinterpret_cast<const UTF8 *>(S.data());
- UTF32 *Out32 = Codepoints.data();
- ConvertUTF8toUTF32(&In8, In8 + S.size(), &Out32, Out32 + Codepoints.size(),
- lenientConversion);
- Codepoints.resize(Out32 - Codepoints.data());
- std::string Res(4 * Codepoints.size(), 0); // 4 bytes per codepoint suffice
- const UTF32 *In32 = Codepoints.data();
- UTF8 *Out8 = reinterpret_cast<UTF8 *>(&Res[0]);
- ConvertUTF32toUTF8(&In32, In32 + Codepoints.size(), &Out8, Out8 + Res.size(),
- strictConversion);
- Res.resize(reinterpret_cast<char *>(Out8) - Res.data());
- return Res;
-}
-
-} // namespace json
-} // namespace llvm
-
-static void quote(llvm::raw_ostream &OS, llvm::StringRef S) {
- OS << '\"';
- for (unsigned char C : S) {
- if (C == 0x22 || C == 0x5C)
- OS << '\\';
- if (C >= 0x20) {
- OS << C;
- continue;
- }
- OS << '\\';
- switch (C) {
- // A few characters are common enough to make short escapes worthwhile.
- case '\t':
- OS << 't';
- break;
- case '\n':
- OS << 'n';
- break;
- case '\r':
- OS << 'r';
- break;
- default:
- OS << 'u';
- llvm::write_hex(OS, C, llvm::HexPrintStyle::Lower, 4);
- break;
- }
- }
- OS << '\"';
-}
-
-enum IndenterAction {
- Indent,
- Outdent,
- Newline,
- Space,
-};
-
-// Prints JSON. The indenter can be used to control formatting.
-template <typename Indenter>
-void llvm::json::Value::print(raw_ostream &OS, const Indenter &I) const {
- switch (Type) {
- case T_Null:
- OS << "null";
- break;
- case T_Boolean:
- OS << (as<bool>() ? "true" : "false");
- break;
- case T_Double:
- OS << format("%.*g", std::numeric_limits<double>::max_digits10,
- as<double>());
- break;
- case T_Integer:
- OS << as<int64_t>();
- break;
- case T_StringRef:
- quote(OS, as<StringRef>());
- break;
- case T_String:
- quote(OS, as<std::string>());
- break;
- case T_Object: {
- bool Comma = false;
- OS << '{';
- I(Indent);
- for (const auto *P : sortedElements(as<json::Object>())) {
- if (Comma)
- OS << ',';
- Comma = true;
- I(Newline);
- quote(OS, P->first);
- OS << ':';
- I(Space);
- P->second.print(OS, I);
- }
- I(Outdent);
- if (Comma)
- I(Newline);
- OS << '}';
- break;
- }
- case T_Array: {
- bool Comma = false;
- OS << '[';
- I(Indent);
- for (const auto &E : as<json::Array>()) {
- if (Comma)
- OS << ',';
- Comma = true;
- I(Newline);
- E.print(OS, I);
- }
- I(Outdent);
- if (Comma)
- I(Newline);
- OS << ']';
- break;
- }
- }
-}
-
-void llvm::format_provider<llvm::json::Value>::format(
- const llvm::json::Value &E, raw_ostream &OS, StringRef Options) {
- if (Options.empty()) {
- OS << E;
- return;
- }
- unsigned IndentAmount = 0;
- if (Options.getAsInteger(/*Radix=*/10, IndentAmount))
- llvm_unreachable("json::Value format options should be an integer");
- unsigned IndentLevel = 0;
- E.print(OS, [&](IndenterAction A) {
- switch (A) {
- case Newline:
- OS << '\n';
- OS.indent(IndentLevel);
- break;
- case Space:
- OS << ' ';
- break;
- case Indent:
- IndentLevel += IndentAmount;
- break;
- case Outdent:
- IndentLevel -= IndentAmount;
- break;
- };
- });
-}
-
-llvm::raw_ostream &llvm::json::operator<<(raw_ostream &OS, const Value &E) {
- E.print(OS, [](IndenterAction A) { /*ignore*/ });
- return OS;
-}
diff --git a/gnu/llvm/lib/Support/JamCRC.cpp b/gnu/llvm/lib/Support/JamCRC.cpp
deleted file mode 100644
index 17c55f565e0..00000000000
--- a/gnu/llvm/lib/Support/JamCRC.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-//===-- JamCRC.cpp - Cyclic Redundancy Check --------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains an implementation of JamCRC.
-//
-//===----------------------------------------------------------------------===//
-//
-// The implementation technique is the one mentioned in:
-// D. V. Sarwate. 1988. Computation of cyclic redundancy checks via table
-// look-up. Commun. ACM 31, 8 (August 1988)
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/JamCRC.h"
-#include "llvm/ADT/ArrayRef.h"
-
-using namespace llvm;
-
-static const uint32_t CRCTable[256] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
- 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
- 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
- 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
- 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
- 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
- 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
- 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
- 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
- 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
- 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
- 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
- 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
- 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
- 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
- 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
- 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
- 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
- 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
- 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
- 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
- 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-void JamCRC::update(ArrayRef<char> Data) {
- for (char Byte : Data) {
- int TableIdx = (CRC ^ Byte) & 0xff;
- CRC = CRCTable[TableIdx] ^ (CRC >> 8);
- }
-}
diff --git a/gnu/llvm/lib/Support/KnownBits.cpp b/gnu/llvm/lib/Support/KnownBits.cpp
deleted file mode 100644
index ac790ebed35..00000000000
--- a/gnu/llvm/lib/Support/KnownBits.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-//===-- KnownBits.cpp - Stores known zeros/ones ---------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains a class for representing known zeros and ones used by
-// computeKnownBits.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/KnownBits.h"
-
-using namespace llvm;
-
-KnownBits KnownBits::computeForAddSub(bool Add, bool NSW,
- const KnownBits &LHS, KnownBits RHS) {
- // Carry in a 1 for a subtract, rather than 0.
- bool CarryIn = false;
- if (!Add) {
- // Sum = LHS + ~RHS + 1
- std::swap(RHS.Zero, RHS.One);
- CarryIn = true;
- }
-
- APInt PossibleSumZero = ~LHS.Zero + ~RHS.Zero + CarryIn;
- APInt PossibleSumOne = LHS.One + RHS.One + CarryIn;
-
- // Compute known bits of the carry.
- APInt CarryKnownZero = ~(PossibleSumZero ^ LHS.Zero ^ RHS.Zero);
- APInt CarryKnownOne = PossibleSumOne ^ LHS.One ^ RHS.One;
-
- // Compute set of known bits (where all three relevant bits are known).
- APInt LHSKnownUnion = LHS.Zero | LHS.One;
- APInt RHSKnownUnion = RHS.Zero | RHS.One;
- APInt CarryKnownUnion = std::move(CarryKnownZero) | CarryKnownOne;
- APInt Known = std::move(LHSKnownUnion) & RHSKnownUnion & CarryKnownUnion;
-
- assert((PossibleSumZero & Known) == (PossibleSumOne & Known) &&
- "known bits of sum differ");
-
- // Compute known bits of the result.
- KnownBits KnownOut;
- KnownOut.Zero = ~std::move(PossibleSumZero) & Known;
- KnownOut.One = std::move(PossibleSumOne) & Known;
-
- // Are we still trying to solve for the sign bit?
- if (!Known.isSignBitSet()) {
- if (NSW) {
- // Adding two non-negative numbers, or subtracting a negative number from
- // a non-negative one, can't wrap into negative.
- if (LHS.isNonNegative() && RHS.isNonNegative())
- KnownOut.makeNonNegative();
- // Adding two negative numbers, or subtracting a non-negative number from
- // a negative one, can't wrap into non-negative.
- else if (LHS.isNegative() && RHS.isNegative())
- KnownOut.makeNegative();
- }
- }
-
- return KnownOut;
-}
diff --git a/gnu/llvm/lib/Support/LEB128.cpp b/gnu/llvm/lib/Support/LEB128.cpp
deleted file mode 100644
index 449626f2d45..00000000000
--- a/gnu/llvm/lib/Support/LEB128.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- LEB128.cpp - LEB128 utility functions implementation -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements some utility functions for encoding SLEB128 and
-// ULEB128 values.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/LEB128.h"
-
-namespace llvm {
-
-/// Utility function to get the size of the ULEB128-encoded value.
-unsigned getULEB128Size(uint64_t Value) {
- unsigned Size = 0;
- do {
- Value >>= 7;
- Size += sizeof(int8_t);
- } while (Value);
- return Size;
-}
-
-/// Utility function to get the size of the SLEB128-encoded value.
-unsigned getSLEB128Size(int64_t Value) {
- unsigned Size = 0;
- int Sign = Value >> (8 * sizeof(Value) - 1);
- bool IsMore;
-
- do {
- unsigned Byte = Value & 0x7f;
- Value >>= 7;
- IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
- Size += sizeof(int8_t);
- } while (IsMore);
- return Size;
-}
-
-} // namespace llvm
diff --git a/gnu/llvm/lib/Support/LLVMBuild.txt b/gnu/llvm/lib/Support/LLVMBuild.txt
deleted file mode 100644
index 4c751397041..00000000000
--- a/gnu/llvm/lib/Support/LLVMBuild.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-;===- ./lib/Support/LLVMBuild.txt ------------------------------*- Conf -*--===;
-;
-; The LLVM Compiler Infrastructure
-;
-; This file is distributed under the University of Illinois Open Source
-; License. See LICENSE.TXT for details.
-;
-;===------------------------------------------------------------------------===;
-;
-; This is an LLVMBuild description file for the components in this subdirectory.
-;
-; For more information on the LLVMBuild system, please see:
-;
-; http://llvm.org/docs/LLVMBuild.html
-;
-;===------------------------------------------------------------------------===;
-
-[component_0]
-type = Library
-name = Support
-parent = Libraries
-required_libraries = Demangle
diff --git a/gnu/llvm/lib/Support/LineIterator.cpp b/gnu/llvm/lib/Support/LineIterator.cpp
deleted file mode 100644
index 5baa1a37f38..00000000000
--- a/gnu/llvm/lib/Support/LineIterator.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-//===- LineIterator.cpp - Implementation of line iteration ----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/LineIterator.h"
-#include "llvm/Support/MemoryBuffer.h"
-
-using namespace llvm;
-
-static bool isAtLineEnd(const char *P) {
- if (*P == '\n')
- return true;
- if (*P == '\r' && *(P + 1) == '\n')
- return true;
- return false;
-}
-
-static bool skipIfAtLineEnd(const char *&P) {
- if (*P == '\n') {
- ++P;
- return true;
- }
- if (*P == '\r' && *(P + 1) == '\n') {
- P += 2;
- return true;
- }
- return false;
-}
-
-line_iterator::line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks,
- char CommentMarker)
- : Buffer(Buffer.getBufferSize() ? &Buffer : nullptr),
- CommentMarker(CommentMarker), SkipBlanks(SkipBlanks), LineNumber(1),
- CurrentLine(Buffer.getBufferSize() ? Buffer.getBufferStart() : nullptr,
- 0) {
- // Ensure that if we are constructed on a non-empty memory buffer that it is
- // a null terminated buffer.
- if (Buffer.getBufferSize()) {
- assert(Buffer.getBufferEnd()[0] == '\0');
- // Make sure we don't skip a leading newline if we're keeping blanks
- if (SkipBlanks || !isAtLineEnd(Buffer.getBufferStart()))
- advance();
- }
-}
-
-void line_iterator::advance() {
- assert(Buffer && "Cannot advance past the end!");
-
- const char *Pos = CurrentLine.end();
- assert(Pos == Buffer->getBufferStart() || isAtLineEnd(Pos) || *Pos == '\0');
-
- if (skipIfAtLineEnd(Pos))
- ++LineNumber;
- if (!SkipBlanks && isAtLineEnd(Pos)) {
- // Nothing to do for a blank line.
- } else if (CommentMarker == '\0') {
- // If we're not stripping comments, this is simpler.
- while (skipIfAtLineEnd(Pos))
- ++LineNumber;
- } else {
- // Skip comments and count line numbers, which is a bit more complex.
- for (;;) {
- if (isAtLineEnd(Pos) && !SkipBlanks)
- break;
- if (*Pos == CommentMarker)
- do {
- ++Pos;
- } while (*Pos != '\0' && !isAtLineEnd(Pos));
- if (!skipIfAtLineEnd(Pos))
- break;
- ++LineNumber;
- }
- }
-
- if (*Pos == '\0') {
- // We've hit the end of the buffer, reset ourselves to the end state.
- Buffer = nullptr;
- CurrentLine = StringRef();
- return;
- }
-
- // Measure the line.
- size_t Length = 0;
- while (Pos[Length] != '\0' && !isAtLineEnd(&Pos[Length])) {
- ++Length;
- }
-
- CurrentLine = StringRef(Pos, Length);
-}
diff --git a/gnu/llvm/lib/Support/Locale.cpp b/gnu/llvm/lib/Support/Locale.cpp
deleted file mode 100644
index 1b3300b90f2..00000000000
--- a/gnu/llvm/lib/Support/Locale.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "llvm/Support/Locale.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Unicode.h"
-
-namespace llvm {
-namespace sys {
-namespace locale {
-
-int columnWidth(StringRef Text) {
- return llvm::sys::unicode::columnWidthUTF8(Text);
-}
-
-bool isPrint(int UCS) {
- return llvm::sys::unicode::isPrintable(UCS);
-}
-
-} // namespace locale
-} // namespace sys
-} // namespace llvm
diff --git a/gnu/llvm/lib/Support/LockFileManager.cpp b/gnu/llvm/lib/Support/LockFileManager.cpp
deleted file mode 100644
index c166230ba3a..00000000000
--- a/gnu/llvm/lib/Support/LockFileManager.cpp
+++ /dev/null
@@ -1,356 +0,0 @@
-//===--- LockFileManager.cpp - File-level Locking Utility------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/LockFileManager.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cerrno>
-#include <ctime>
-#include <memory>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <system_error>
-#include <tuple>
-#ifdef _WIN32
-#include <windows.h>
-#endif
-#if LLVM_ON_UNIX
-#include <unistd.h>
-#endif
-
-#if defined(__APPLE__) && defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && (__MAC_OS_X_VERSION_MIN_REQUIRED > 1050)
-#define USE_OSX_GETHOSTUUID 1
-#else
-#define USE_OSX_GETHOSTUUID 0
-#endif
-
-#if USE_OSX_GETHOSTUUID
-#include <uuid/uuid.h>
-#endif
-
-using namespace llvm;
-
-/// Attempt to read the lock file with the given name, if it exists.
-///
-/// \param LockFileName The name of the lock file to read.
-///
-/// \returns The process ID of the process that owns this lock file
-Optional<std::pair<std::string, int> >
-LockFileManager::readLockFile(StringRef LockFileName) {
- // Read the owning host and PID out of the lock file. If it appears that the
- // owning process is dead, the lock file is invalid.
- ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
- MemoryBuffer::getFile(LockFileName);
- if (!MBOrErr) {
- sys::fs::remove(LockFileName);
- return None;
- }
- MemoryBuffer &MB = *MBOrErr.get();
-
- StringRef Hostname;
- StringRef PIDStr;
- std::tie(Hostname, PIDStr) = getToken(MB.getBuffer(), " ");
- PIDStr = PIDStr.substr(PIDStr.find_first_not_of(" "));
- int PID;
- if (!PIDStr.getAsInteger(10, PID)) {
- auto Owner = std::make_pair(std::string(Hostname), PID);
- if (processStillExecuting(Owner.first, Owner.second))
- return Owner;
- }
-
- // Delete the lock file. It's invalid anyway.
- sys::fs::remove(LockFileName);
- return None;
-}
-
-static std::error_code getHostID(SmallVectorImpl<char> &HostID) {
- HostID.clear();
-
-#if USE_OSX_GETHOSTUUID
- // On OS X, use the more stable hardware UUID instead of hostname.
- struct timespec wait = {1, 0}; // 1 second.
- uuid_t uuid;
- if (gethostuuid(uuid, &wait) != 0)
- return std::error_code(errno, std::system_category());
-
- uuid_string_t UUIDStr;
- uuid_unparse(uuid, UUIDStr);
- StringRef UUIDRef(UUIDStr);
- HostID.append(UUIDRef.begin(), UUIDRef.end());
-
-#elif LLVM_ON_UNIX
- char HostName[256];
- HostName[255] = 0;
- HostName[0] = 0;
- gethostname(HostName, 255);
- StringRef HostNameRef(HostName);
- HostID.append(HostNameRef.begin(), HostNameRef.end());
-
-#else
- StringRef Dummy("localhost");
- HostID.append(Dummy.begin(), Dummy.end());
-#endif
-
- return std::error_code();
-}
-
-bool LockFileManager::processStillExecuting(StringRef HostID, int PID) {
-#if LLVM_ON_UNIX && !defined(__ANDROID__)
- SmallString<256> StoredHostID;
- if (getHostID(StoredHostID))
- return true; // Conservatively assume it's executing on error.
-
- // Check whether the process is dead. If so, we're done.
- if (StoredHostID == HostID && getsid(PID) == -1 && errno == ESRCH)
- return false;
-#endif
-
- return true;
-}
-
-namespace {
-
-/// An RAII helper object ensure that the unique lock file is removed.
-///
-/// Ensures that if there is an error or a signal before we finish acquiring the
-/// lock, the unique file will be removed. And if we successfully take the lock,
-/// the signal handler is left in place so that signals while the lock is held
-/// will remove the unique lock file. The caller should ensure there is a
-/// matching call to sys::DontRemoveFileOnSignal when the lock is released.
-class RemoveUniqueLockFileOnSignal {
- StringRef Filename;
- bool RemoveImmediately;
-public:
- RemoveUniqueLockFileOnSignal(StringRef Name)
- : Filename(Name), RemoveImmediately(true) {
- sys::RemoveFileOnSignal(Filename, nullptr);
- }
-
- ~RemoveUniqueLockFileOnSignal() {
- if (!RemoveImmediately) {
- // Leave the signal handler enabled. It will be removed when the lock is
- // released.
- return;
- }
- sys::fs::remove(Filename);
- sys::DontRemoveFileOnSignal(Filename);
- }
-
- void lockAcquired() { RemoveImmediately = false; }
-};
-
-} // end anonymous namespace
-
-LockFileManager::LockFileManager(StringRef FileName)
-{
- this->FileName = FileName;
- if (std::error_code EC = sys::fs::make_absolute(this->FileName)) {
- std::string S("failed to obtain absolute path for ");
- S.append(this->FileName.str());
- setError(EC, S);
- return;
- }
- LockFileName = this->FileName;
- LockFileName += ".lock";
-
- // If the lock file already exists, don't bother to try to create our own
- // lock file; it won't work anyway. Just figure out who owns this lock file.
- if ((Owner = readLockFile(LockFileName)))
- return;
-
- // Create a lock file that is unique to this instance.
- UniqueLockFileName = LockFileName;
- UniqueLockFileName += "-%%%%%%%%";
- int UniqueLockFileID;
- if (std::error_code EC = sys::fs::createUniqueFile(
- UniqueLockFileName, UniqueLockFileID, UniqueLockFileName)) {
- std::string S("failed to create unique file ");
- S.append(UniqueLockFileName.str());
- setError(EC, S);
- return;
- }
-
- // Write our process ID to our unique lock file.
- {
- SmallString<256> HostID;
- if (auto EC = getHostID(HostID)) {
- setError(EC, "failed to get host id");
- return;
- }
-
- raw_fd_ostream Out(UniqueLockFileID, /*shouldClose=*/true);
- Out << HostID << ' ';
-#if LLVM_ON_UNIX
- Out << getpid();
-#else
- Out << "1";
-#endif
- Out.close();
-
- if (Out.has_error()) {
- // We failed to write out PID, so report the error, remove the
- // unique lock file, and fail.
- std::string S("failed to write to ");
- S.append(UniqueLockFileName.str());
- setError(Out.error(), S);
- sys::fs::remove(UniqueLockFileName);
- return;
- }
- }
-
- // Clean up the unique file on signal, which also releases the lock if it is
- // held since the .lock symlink will point to a nonexistent file.
- RemoveUniqueLockFileOnSignal RemoveUniqueFile(UniqueLockFileName);
-
- while (true) {
- // Create a link from the lock file name. If this succeeds, we're done.
- std::error_code EC =
- sys::fs::create_link(UniqueLockFileName, LockFileName);
- if (!EC) {
- RemoveUniqueFile.lockAcquired();
- return;
- }
-
- if (EC != errc::file_exists) {
- std::string S("failed to create link ");
- raw_string_ostream OSS(S);
- OSS << LockFileName.str() << " to " << UniqueLockFileName.str();
- setError(EC, OSS.str());
- return;
- }
-
- // Someone else managed to create the lock file first. Read the process ID
- // from the lock file.
- if ((Owner = readLockFile(LockFileName))) {
- // Wipe out our unique lock file (it's useless now)
- sys::fs::remove(UniqueLockFileName);
- return;
- }
-
- if (!sys::fs::exists(LockFileName)) {
- // The previous owner released the lock file before we could read it.
- // Try to get ownership again.
- continue;
- }
-
- // There is a lock file that nobody owns; try to clean it up and get
- // ownership.
- if ((EC = sys::fs::remove(LockFileName))) {
- std::string S("failed to remove lockfile ");
- S.append(UniqueLockFileName.str());
- setError(EC, S);
- return;
- }
- }
-}
-
-LockFileManager::LockFileState LockFileManager::getState() const {
- if (Owner)
- return LFS_Shared;
-
- if (ErrorCode)
- return LFS_Error;
-
- return LFS_Owned;
-}
-
-std::string LockFileManager::getErrorMessage() const {
- if (ErrorCode) {
- std::string Str(ErrorDiagMsg);
- std::string ErrCodeMsg = ErrorCode.message();
- raw_string_ostream OSS(Str);
- if (!ErrCodeMsg.empty())
- OSS << ": " << ErrCodeMsg;
- return OSS.str();
- }
- return "";
-}
-
-LockFileManager::~LockFileManager() {
- if (getState() != LFS_Owned)
- return;
-
- // Since we own the lock, remove the lock file and our own unique lock file.
- sys::fs::remove(LockFileName);
- sys::fs::remove(UniqueLockFileName);
- // The unique file is now gone, so remove it from the signal handler. This
- // matches a sys::RemoveFileOnSignal() in LockFileManager().
- sys::DontRemoveFileOnSignal(UniqueLockFileName);
-}
-
-LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() {
- if (getState() != LFS_Shared)
- return Res_Success;
-
-#ifdef _WIN32
- unsigned long Interval = 1;
-#else
- struct timespec Interval;
- Interval.tv_sec = 0;
- Interval.tv_nsec = 1000000;
-#endif
- // Don't wait more than 40s per iteration. Total timeout for the file
- // to appear is ~1.5 minutes.
- const unsigned MaxSeconds = 40;
- do {
- // Sleep for the designated interval, to allow the owning process time to
- // finish up and remove the lock file.
- // FIXME: Should we hook in to system APIs to get a notification when the
- // lock file is deleted?
-#ifdef _WIN32
- Sleep(Interval);
-#else
- nanosleep(&Interval, nullptr);
-#endif
-
- if (sys::fs::access(LockFileName.c_str(), sys::fs::AccessMode::Exist) ==
- errc::no_such_file_or_directory) {
- // If the original file wasn't created, somone thought the lock was dead.
- if (!sys::fs::exists(FileName))
- return Res_OwnerDied;
- return Res_Success;
- }
-
- // If the process owning the lock died without cleaning up, just bail out.
- if (!processStillExecuting((*Owner).first, (*Owner).second))
- return Res_OwnerDied;
-
- // Exponentially increase the time we wait for the lock to be removed.
-#ifdef _WIN32
- Interval *= 2;
-#else
- Interval.tv_sec *= 2;
- Interval.tv_nsec *= 2;
- if (Interval.tv_nsec >= 1000000000) {
- ++Interval.tv_sec;
- Interval.tv_nsec -= 1000000000;
- }
-#endif
- } while (
-#ifdef _WIN32
- Interval < MaxSeconds * 1000
-#else
- Interval.tv_sec < (time_t)MaxSeconds
-#endif
- );
-
- // Give up.
- return Res_Timeout;
-}
-
-std::error_code LockFileManager::unsafeRemoveLockFile() {
- return sys::fs::remove(LockFileName);
-}
diff --git a/gnu/llvm/lib/Support/LowLevelType.cpp b/gnu/llvm/lib/Support/LowLevelType.cpp
deleted file mode 100644
index cb2187405d6..00000000000
--- a/gnu/llvm/lib/Support/LowLevelType.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-//===-- llvm/Support/LowLevelType.cpp -------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file This file implements the more header-heavy bits of the LLT class to
-/// avoid polluting users' namespaces.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/LowLevelTypeImpl.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-LLT::LLT(MVT VT) {
- if (VT.isVector()) {
- init(/*isPointer=*/false, VT.getVectorNumElements() > 1,
- VT.getVectorNumElements(), VT.getVectorElementType().getSizeInBits(),
- /*AddressSpace=*/0);
- } else if (VT.isValid()) {
- // Aggregates are no different from real scalars as far as GlobalISel is
- // concerned.
- assert(VT.getSizeInBits() != 0 && "invalid zero-sized type");
- init(/*isPointer=*/false, /*isVector=*/false, /*NumElements=*/0,
- VT.getSizeInBits(), /*AddressSpace=*/0);
- } else {
- IsPointer = false;
- IsVector = false;
- RawData = 0;
- }
-}
-
-void LLT::print(raw_ostream &OS) const {
- if (isVector())
- OS << "<" << getNumElements() << " x " << getElementType() << ">";
- else if (isPointer())
- OS << "p" << getAddressSpace();
- else if (isValid()) {
- assert(isScalar() && "unexpected type");
- OS << "s" << getScalarSizeInBits();
- } else
- OS << "LLT_invalid";
-}
-
-const constexpr LLT::BitFieldInfo LLT::ScalarSizeFieldInfo;
-const constexpr LLT::BitFieldInfo LLT::PointerSizeFieldInfo;
-const constexpr LLT::BitFieldInfo LLT::PointerAddressSpaceFieldInfo;
-const constexpr LLT::BitFieldInfo LLT::VectorElementsFieldInfo;
-const constexpr LLT::BitFieldInfo LLT::VectorSizeFieldInfo;
-const constexpr LLT::BitFieldInfo LLT::PointerVectorElementsFieldInfo;
-const constexpr LLT::BitFieldInfo LLT::PointerVectorSizeFieldInfo;
-const constexpr LLT::BitFieldInfo LLT::PointerVectorAddressSpaceFieldInfo;
diff --git a/gnu/llvm/lib/Support/MD5.cpp b/gnu/llvm/lib/Support/MD5.cpp
deleted file mode 100644
index 9b02f62912f..00000000000
--- a/gnu/llvm/lib/Support/MD5.cpp
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * This code is derived from (original license follows):
- *
- * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
- * MD5 Message-Digest Algorithm (RFC 1321).
- *
- * Homepage:
- * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
- *
- * Author:
- * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
- *
- * This software was written by Alexander Peslyak in 2001. No copyright is
- * claimed, and the software is hereby placed in the public domain.
- * In case this attempt to disclaim copyright and place the software in the
- * public domain is deemed null and void, then the software is
- * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
- * general public under the following terms:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted.
- *
- * There's ABSOLUTELY NO WARRANTY, express or implied.
- *
- * (This is a heavily cut-down "BSD license".)
- *
- * This differs from Colin Plumb's older public domain implementation in that
- * no exactly 32-bit integer data type is required (any 32-bit or wider
- * unsigned integer data type will do), there's no compile-time endianness
- * configuration, and the function prototypes match OpenSSL's. No code from
- * Colin Plumb's implementation has been reused; this comment merely compares
- * the properties of the two independent implementations.
- *
- * The primary goals of this implementation are portability and ease of use.
- * It is meant to be fast, but not as fast as possible. Some known
- * optimizations are not included to reduce source code size and avoid
- * compile-time configuration.
- */
-
-#include "llvm/Support/MD5.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-#include <array>
-#include <cstdint>
-#include <cstring>
-
-// The basic MD5 functions.
-
-// F and G are optimized compared to their RFC 1321 definitions for
-// architectures that lack an AND-NOT instruction, just like in Colin Plumb's
-// implementation.
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-
-// The MD5 transformation for all four rounds.
-#define STEP(f, a, b, c, d, x, t, s) \
- (a) += f((b), (c), (d)) + (x) + (t); \
- (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
- (a) += (b);
-
-// SET reads 4 input bytes in little-endian byte order and stores them
-// in a properly aligned word in host byte order.
-#define SET(n) \
- (block[(n)] = \
- (MD5_u32plus) ptr[(n) * 4] | ((MD5_u32plus) ptr[(n) * 4 + 1] << 8) | \
- ((MD5_u32plus) ptr[(n) * 4 + 2] << 16) | \
- ((MD5_u32plus) ptr[(n) * 4 + 3] << 24))
-#define GET(n) (block[(n)])
-
-using namespace llvm;
-
-/// This processes one or more 64-byte data blocks, but does NOT update
-///the bit counters. There are no alignment requirements.
-const uint8_t *MD5::body(ArrayRef<uint8_t> Data) {
- const uint8_t *ptr;
- MD5_u32plus a, b, c, d;
- MD5_u32plus saved_a, saved_b, saved_c, saved_d;
- unsigned long Size = Data.size();
-
- ptr = Data.data();
-
- a = this->a;
- b = this->b;
- c = this->c;
- d = this->d;
-
- do {
- saved_a = a;
- saved_b = b;
- saved_c = c;
- saved_d = d;
-
- // Round 1
- STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
- STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
- STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
- STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
- STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
- STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
- STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
- STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
- STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
- STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
- STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
- STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
- STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
- STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
- STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
- STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
-
- // Round 2
- STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
- STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
- STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
- STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
- STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
- STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
- STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
- STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
- STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
- STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
- STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
- STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
- STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
- STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
- STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
- STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
-
- // Round 3
- STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
- STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
- STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
- STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
- STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
- STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
- STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
- STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
- STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
- STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
- STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
- STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
- STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
- STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
- STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
- STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
-
- // Round 4
- STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
- STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
- STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
- STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
- STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
- STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
- STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
- STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
- STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
- STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
- STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
- STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
- STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
- STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
- STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
- STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
-
- a += saved_a;
- b += saved_b;
- c += saved_c;
- d += saved_d;
-
- ptr += 64;
- } while (Size -= 64);
-
- this->a = a;
- this->b = b;
- this->c = c;
- this->d = d;
-
- return ptr;
-}
-
-MD5::MD5() = default;
-
-/// Incrementally add the bytes in \p Data to the hash.
-void MD5::update(ArrayRef<uint8_t> Data) {
- MD5_u32plus saved_lo;
- unsigned long used, free;
- const uint8_t *Ptr = Data.data();
- unsigned long Size = Data.size();
-
- saved_lo = lo;
- if ((lo = (saved_lo + Size) & 0x1fffffff) < saved_lo)
- hi++;
- hi += Size >> 29;
-
- used = saved_lo & 0x3f;
-
- if (used) {
- free = 64 - used;
-
- if (Size < free) {
- memcpy(&buffer[used], Ptr, Size);
- return;
- }
-
- memcpy(&buffer[used], Ptr, free);
- Ptr = Ptr + free;
- Size -= free;
- body(makeArrayRef(buffer, 64));
- }
-
- if (Size >= 64) {
- Ptr = body(makeArrayRef(Ptr, Size & ~(unsigned long) 0x3f));
- Size &= 0x3f;
- }
-
- memcpy(buffer, Ptr, Size);
-}
-
-/// Add the bytes in the StringRef \p Str to the hash.
-// Note that this isn't a string and so this won't include any trailing NULL
-// bytes.
-void MD5::update(StringRef Str) {
- ArrayRef<uint8_t> SVal((const uint8_t *)Str.data(), Str.size());
- update(SVal);
-}
-
-/// Finish the hash and place the resulting hash into \p result.
-/// \param Result is assumed to be a minimum of 16-bytes in size.
-void MD5::final(MD5Result &Result) {
- unsigned long used, free;
-
- used = lo & 0x3f;
-
- buffer[used++] = 0x80;
-
- free = 64 - used;
-
- if (free < 8) {
- memset(&buffer[used], 0, free);
- body(makeArrayRef(buffer, 64));
- used = 0;
- free = 64;
- }
-
- memset(&buffer[used], 0, free - 8);
-
- lo <<= 3;
- support::endian::write32le(&buffer[56], lo);
- support::endian::write32le(&buffer[60], hi);
-
- body(makeArrayRef(buffer, 64));
-
- support::endian::write32le(&Result[0], a);
- support::endian::write32le(&Result[4], b);
- support::endian::write32le(&Result[8], c);
- support::endian::write32le(&Result[12], d);
-}
-
-SmallString<32> MD5::MD5Result::digest() const {
- SmallString<32> Str;
- raw_svector_ostream Res(Str);
- for (int i = 0; i < 16; ++i)
- Res << format("%.2x", Bytes[i]);
- return Str;
-}
-
-void MD5::stringifyResult(MD5Result &Result, SmallString<32> &Str) {
- Str = Result.digest();
-}
-
-std::array<uint8_t, 16> MD5::hash(ArrayRef<uint8_t> Data) {
- MD5 Hash;
- Hash.update(Data);
- MD5::MD5Result Res;
- Hash.final(Res);
-
- return Res;
-}
diff --git a/gnu/llvm/lib/Support/ManagedStatic.cpp b/gnu/llvm/lib/Support/ManagedStatic.cpp
deleted file mode 100644
index 74f71a38502..00000000000
--- a/gnu/llvm/lib/Support/ManagedStatic.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the ManagedStatic class and llvm_shutdown().
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/MutexGuard.h"
-#include "llvm/Support/Threading.h"
-#include <cassert>
-using namespace llvm;
-
-static const ManagedStaticBase *StaticList = nullptr;
-static sys::Mutex *ManagedStaticMutex = nullptr;
-static llvm::once_flag mutex_init_flag;
-
-static void initializeMutex() {
- ManagedStaticMutex = new sys::Mutex();
-}
-
-static sys::Mutex* getManagedStaticMutex() {
- llvm::call_once(mutex_init_flag, initializeMutex);
- return ManagedStaticMutex;
-}
-
-void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
- void (*Deleter)(void*)) const {
- assert(Creator);
- if (llvm_is_multithreaded()) {
- MutexGuard Lock(*getManagedStaticMutex());
-
- if (!Ptr.load(std::memory_order_relaxed)) {
- void *Tmp = Creator();
-
- Ptr.store(Tmp, std::memory_order_release);
- DeleterFn = Deleter;
-
- // Add to list of managed statics.
- Next = StaticList;
- StaticList = this;
- }
- } else {
- assert(!Ptr && !DeleterFn && !Next &&
- "Partially initialized ManagedStatic!?");
- Ptr = Creator();
- DeleterFn = Deleter;
-
- // Add to list of managed statics.
- Next = StaticList;
- StaticList = this;
- }
-}
-
-void ManagedStaticBase::destroy() const {
- assert(DeleterFn && "ManagedStatic not initialized correctly!");
- assert(StaticList == this &&
- "Not destroyed in reverse order of construction?");
- // Unlink from list.
- StaticList = Next;
- Next = nullptr;
-
- // Destroy memory.
- DeleterFn(Ptr);
-
- // Cleanup.
- Ptr = nullptr;
- DeleterFn = nullptr;
-}
-
-/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
-void llvm::llvm_shutdown() {
- MutexGuard Lock(*getManagedStaticMutex());
-
- while (StaticList)
- StaticList->destroy();
-}
diff --git a/gnu/llvm/lib/Support/MathExtras.cpp b/gnu/llvm/lib/Support/MathExtras.cpp
deleted file mode 100644
index ba0924540ce..00000000000
--- a/gnu/llvm/lib/Support/MathExtras.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===-- MathExtras.cpp - Implement the MathExtras header --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the MathExtras.h header
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/MathExtras.h"
-
-#ifdef _MSC_VER
-#include <limits>
-#else
-#include <math.h>
-#endif
-
-namespace llvm {
-
-#if defined(_MSC_VER)
- // Visual Studio defines the HUGE_VAL class of macros using purposeful
- // constant arithmetic overflow, which it then warns on when encountered.
- const float huge_valf = std::numeric_limits<float>::infinity();
-#else
- const float huge_valf = HUGE_VALF;
-#endif
-
-}
diff --git a/gnu/llvm/lib/Support/Memory.cpp b/gnu/llvm/lib/Support/Memory.cpp
deleted file mode 100644
index c245eedd2c1..00000000000
--- a/gnu/llvm/lib/Support/Memory.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- Memory.cpp - Memory Handling Support ---------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines some helpful functions for allocating memory and dealing
-// with memory mapped files
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Memory.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Valgrind.h"
-
-// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
-#include "Unix/Memory.inc"
-#endif
-#ifdef _WIN32
-#include "Windows/Memory.inc"
-#endif
diff --git a/gnu/llvm/lib/Support/MemoryBuffer.cpp b/gnu/llvm/lib/Support/MemoryBuffer.cpp
deleted file mode 100644
index ef9159bac28..00000000000
--- a/gnu/llvm/lib/Support/MemoryBuffer.cpp
+++ /dev/null
@@ -1,536 +0,0 @@
-//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the MemoryBuffer interface.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Errno.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/SmallVectorMemoryBuffer.h"
-#include <cassert>
-#include <cerrno>
-#include <cstring>
-#include <new>
-#include <sys/types.h>
-#include <system_error>
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-#include <unistd.h>
-#else
-#include <io.h>
-#endif
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// MemoryBuffer implementation itself.
-//===----------------------------------------------------------------------===//
-
-MemoryBuffer::~MemoryBuffer() { }
-
-/// init - Initialize this MemoryBuffer as a reference to externally allocated
-/// memory, memory that we know is already null terminated.
-void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
- bool RequiresNullTerminator) {
- assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
- "Buffer is not null terminated!");
- BufferStart = BufStart;
- BufferEnd = BufEnd;
-}
-
-//===----------------------------------------------------------------------===//
-// MemoryBufferMem implementation.
-//===----------------------------------------------------------------------===//
-
-/// CopyStringRef - Copies contents of a StringRef into a block of memory and
-/// null-terminates it.
-static void CopyStringRef(char *Memory, StringRef Data) {
- if (!Data.empty())
- memcpy(Memory, Data.data(), Data.size());
- Memory[Data.size()] = 0; // Null terminate string.
-}
-
-namespace {
-struct NamedBufferAlloc {
- const Twine &Name;
- NamedBufferAlloc(const Twine &Name) : Name(Name) {}
-};
-}
-
-void *operator new(size_t N, const NamedBufferAlloc &Alloc) {
- SmallString<256> NameBuf;
- StringRef NameRef = Alloc.Name.toStringRef(NameBuf);
-
- char *Mem = static_cast<char *>(operator new(N + NameRef.size() + 1));
- CopyStringRef(Mem + N, NameRef);
- return Mem;
-}
-
-namespace {
-/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
-template<typename MB>
-class MemoryBufferMem : public MB {
-public:
- MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
- MemoryBuffer::init(InputData.begin(), InputData.end(),
- RequiresNullTerminator);
- }
-
- /// Disable sized deallocation for MemoryBufferMem, because it has
- /// tail-allocated data.
- void operator delete(void *p) { ::operator delete(p); }
-
- StringRef getBufferIdentifier() const override {
- // The name is stored after the class itself.
- return StringRef(reinterpret_cast<const char *>(this + 1));
- }
-
- MemoryBuffer::BufferKind getBufferKind() const override {
- return MemoryBuffer::MemoryBuffer_Malloc;
- }
-};
-}
-
-template <typename MB>
-static ErrorOr<std::unique_ptr<MB>>
-getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
- uint64_t Offset, bool RequiresNullTerminator, bool IsVolatile);
-
-std::unique_ptr<MemoryBuffer>
-MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName,
- bool RequiresNullTerminator) {
- auto *Ret = new (NamedBufferAlloc(BufferName))
- MemoryBufferMem<MemoryBuffer>(InputData, RequiresNullTerminator);
- return std::unique_ptr<MemoryBuffer>(Ret);
-}
-
-std::unique_ptr<MemoryBuffer>
-MemoryBuffer::getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator) {
- return std::unique_ptr<MemoryBuffer>(getMemBuffer(
- Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator));
-}
-
-static ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
-getMemBufferCopyImpl(StringRef InputData, const Twine &BufferName) {
- auto Buf = WritableMemoryBuffer::getNewUninitMemBuffer(InputData.size(), BufferName);
- if (!Buf)
- return make_error_code(errc::not_enough_memory);
- memcpy(Buf->getBufferStart(), InputData.data(), InputData.size());
- return std::move(Buf);
-}
-
-std::unique_ptr<MemoryBuffer>
-MemoryBuffer::getMemBufferCopy(StringRef InputData, const Twine &BufferName) {
- auto Buf = getMemBufferCopyImpl(InputData, BufferName);
- if (Buf)
- return std::move(*Buf);
- return nullptr;
-}
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize,
- bool RequiresNullTerminator) {
- SmallString<256> NameBuf;
- StringRef NameRef = Filename.toStringRef(NameBuf);
-
- if (NameRef == "-")
- return getSTDIN();
- return getFile(Filename, FileSize, RequiresNullTerminator);
-}
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize,
- uint64_t Offset, bool IsVolatile) {
- return getFileAux<MemoryBuffer>(FilePath, -1, MapSize, Offset, false,
- IsVolatile);
-}
-
-//===----------------------------------------------------------------------===//
-// MemoryBuffer::getFile implementation.
-//===----------------------------------------------------------------------===//
-
-namespace {
-/// Memory maps a file descriptor using sys::fs::mapped_file_region.
-///
-/// This handles converting the offset into a legal offset on the platform.
-template<typename MB>
-class MemoryBufferMMapFile : public MB {
- sys::fs::mapped_file_region MFR;
-
- static uint64_t getLegalMapOffset(uint64_t Offset) {
- return Offset & ~(sys::fs::mapped_file_region::alignment() - 1);
- }
-
- static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) {
- return Len + (Offset - getLegalMapOffset(Offset));
- }
-
- const char *getStart(uint64_t Len, uint64_t Offset) {
- return MFR.const_data() + (Offset - getLegalMapOffset(Offset));
- }
-
-public:
- MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len,
- uint64_t Offset, std::error_code &EC)
- : MFR(FD, MB::Mapmode, getLegalMapSize(Len, Offset),
- getLegalMapOffset(Offset), EC) {
- if (!EC) {
- const char *Start = getStart(Len, Offset);
- MemoryBuffer::init(Start, Start + Len, RequiresNullTerminator);
- }
- }
-
- /// Disable sized deallocation for MemoryBufferMMapFile, because it has
- /// tail-allocated data.
- void operator delete(void *p) { ::operator delete(p); }
-
- StringRef getBufferIdentifier() const override {
- // The name is stored after the class itself.
- return StringRef(reinterpret_cast<const char *>(this + 1));
- }
-
- MemoryBuffer::BufferKind getBufferKind() const override {
- return MemoryBuffer::MemoryBuffer_MMap;
- }
-};
-}
-
-static ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
-getMemoryBufferForStream(int FD, const Twine &BufferName) {
- const ssize_t ChunkSize = 4096*4;
- SmallString<ChunkSize> Buffer;
- ssize_t ReadBytes;
- // Read into Buffer until we hit EOF.
- do {
- Buffer.reserve(Buffer.size() + ChunkSize);
- ReadBytes = sys::RetryAfterSignal(-1, ::read, FD, Buffer.end(), ChunkSize);
- if (ReadBytes == -1)
- return std::error_code(errno, std::generic_category());
- Buffer.set_size(Buffer.size() + ReadBytes);
- } while (ReadBytes != 0);
-
- return getMemBufferCopyImpl(Buffer, BufferName);
-}
-
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize,
- bool RequiresNullTerminator, bool IsVolatile) {
- return getFileAux<MemoryBuffer>(Filename, FileSize, FileSize, 0,
- RequiresNullTerminator, IsVolatile);
-}
-
-template <typename MB>
-static ErrorOr<std::unique_ptr<MB>>
-getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
- uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
- bool IsVolatile);
-
-template <typename MB>
-static ErrorOr<std::unique_ptr<MB>>
-getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
- uint64_t Offset, bool RequiresNullTerminator, bool IsVolatile) {
- int FD;
- std::error_code EC = sys::fs::openFileForRead(Filename, FD, sys::fs::OF_None);
-
- if (EC)
- return EC;
-
- auto Ret = getOpenFileImpl<MB>(FD, Filename, FileSize, MapSize, Offset,
- RequiresNullTerminator, IsVolatile);
- close(FD);
- return Ret;
-}
-
-ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
-WritableMemoryBuffer::getFile(const Twine &Filename, int64_t FileSize,
- bool IsVolatile) {
- return getFileAux<WritableMemoryBuffer>(Filename, FileSize, FileSize, 0,
- /*RequiresNullTerminator*/ false,
- IsVolatile);
-}
-
-ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
-WritableMemoryBuffer::getFileSlice(const Twine &Filename, uint64_t MapSize,
- uint64_t Offset, bool IsVolatile) {
- return getFileAux<WritableMemoryBuffer>(Filename, -1, MapSize, Offset, false,
- IsVolatile);
-}
-
-std::unique_ptr<WritableMemoryBuffer>
-WritableMemoryBuffer::getNewUninitMemBuffer(size_t Size, const Twine &BufferName) {
- using MemBuffer = MemoryBufferMem<WritableMemoryBuffer>;
- // Allocate space for the MemoryBuffer, the data and the name. It is important
- // that MemoryBuffer and data are aligned so PointerIntPair works with them.
- // TODO: Is 16-byte alignment enough? We copy small object files with large
- // alignment expectations into this buffer.
- SmallString<256> NameBuf;
- StringRef NameRef = BufferName.toStringRef(NameBuf);
- size_t AlignedStringLen = alignTo(sizeof(MemBuffer) + NameRef.size() + 1, 16);
- size_t RealLen = AlignedStringLen + Size + 1;
- char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
- if (!Mem)
- return nullptr;
-
- // The name is stored after the class itself.
- CopyStringRef(Mem + sizeof(MemBuffer), NameRef);
-
- // The buffer begins after the name and must be aligned.
- char *Buf = Mem + AlignedStringLen;
- Buf[Size] = 0; // Null terminate buffer.
-
- auto *Ret = new (Mem) MemBuffer(StringRef(Buf, Size), true);
- return std::unique_ptr<WritableMemoryBuffer>(Ret);
-}
-
-std::unique_ptr<WritableMemoryBuffer>
-WritableMemoryBuffer::getNewMemBuffer(size_t Size, const Twine &BufferName) {
- auto SB = WritableMemoryBuffer::getNewUninitMemBuffer(Size, BufferName);
- if (!SB)
- return nullptr;
- memset(SB->getBufferStart(), 0, Size);
- return SB;
-}
-
-static bool shouldUseMmap(int FD,
- size_t FileSize,
- size_t MapSize,
- off_t Offset,
- bool RequiresNullTerminator,
- int PageSize,
- bool IsVolatile) {
- // mmap may leave the buffer without null terminator if the file size changed
- // by the time the last page is mapped in, so avoid it if the file size is
- // likely to change.
- if (IsVolatile)
- return false;
-
- // We don't use mmap for small files because this can severely fragment our
- // address space.
- if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize)
- return false;
-
- if (!RequiresNullTerminator)
- return true;
-
- // If we don't know the file size, use fstat to find out. fstat on an open
- // file descriptor is cheaper than stat on a random path.
- // FIXME: this chunk of code is duplicated, but it avoids a fstat when
- // RequiresNullTerminator = false and MapSize != -1.
- if (FileSize == size_t(-1)) {
- sys::fs::file_status Status;
- if (sys::fs::status(FD, Status))
- return false;
- FileSize = Status.getSize();
- }
-
- // If we need a null terminator and the end of the map is inside the file,
- // we cannot use mmap.
- size_t End = Offset + MapSize;
- assert(End <= FileSize);
- if (End != FileSize)
- return false;
-
- // Don't try to map files that are exactly a multiple of the system page size
- // if we need a null terminator.
- if ((FileSize & (PageSize -1)) == 0)
- return false;
-
-#if defined(__CYGWIN__)
- // Don't try to map files that are exactly a multiple of the physical page size
- // if we need a null terminator.
- // FIXME: We should reorganize again getPageSize() on Win32.
- if ((FileSize & (4096 - 1)) == 0)
- return false;
-#endif
-
- return true;
-}
-
-static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
-getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize,
- uint64_t Offset) {
- int FD;
- std::error_code EC = sys::fs::openFileForReadWrite(
- Filename, FD, sys::fs::CD_OpenExisting, sys::fs::OF_None);
-
- if (EC)
- return EC;
-
- // Default is to map the full file.
- if (MapSize == uint64_t(-1)) {
- // If we don't know the file size, use fstat to find out. fstat on an open
- // file descriptor is cheaper than stat on a random path.
- if (FileSize == uint64_t(-1)) {
- sys::fs::file_status Status;
- std::error_code EC = sys::fs::status(FD, Status);
- if (EC)
- return EC;
-
- // If this not a file or a block device (e.g. it's a named pipe
- // or character device), we can't mmap it, so error out.
- sys::fs::file_type Type = Status.type();
- if (Type != sys::fs::file_type::regular_file &&
- Type != sys::fs::file_type::block_file)
- return make_error_code(errc::invalid_argument);
-
- FileSize = Status.getSize();
- }
- MapSize = FileSize;
- }
-
- std::unique_ptr<WriteThroughMemoryBuffer> Result(
- new (NamedBufferAlloc(Filename))
- MemoryBufferMMapFile<WriteThroughMemoryBuffer>(false, FD, MapSize,
- Offset, EC));
- if (EC)
- return EC;
- return std::move(Result);
-}
-
-ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
-WriteThroughMemoryBuffer::getFile(const Twine &Filename, int64_t FileSize) {
- return getReadWriteFile(Filename, FileSize, FileSize, 0);
-}
-
-/// Map a subrange of the specified file as a WritableMemoryBuffer.
-ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
-WriteThroughMemoryBuffer::getFileSlice(const Twine &Filename, uint64_t MapSize,
- uint64_t Offset) {
- return getReadWriteFile(Filename, -1, MapSize, Offset);
-}
-
-template <typename MB>
-static ErrorOr<std::unique_ptr<MB>>
-getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
- uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
- bool IsVolatile) {
- static int PageSize = sys::Process::getPageSize();
-
- // Default is to map the full file.
- if (MapSize == uint64_t(-1)) {
- // If we don't know the file size, use fstat to find out. fstat on an open
- // file descriptor is cheaper than stat on a random path.
- if (FileSize == uint64_t(-1)) {
- sys::fs::file_status Status;
- std::error_code EC = sys::fs::status(FD, Status);
- if (EC)
- return EC;
-
- // If this not a file or a block device (e.g. it's a named pipe
- // or character device), we can't trust the size. Create the memory
- // buffer by copying off the stream.
- sys::fs::file_type Type = Status.type();
- if (Type != sys::fs::file_type::regular_file &&
- Type != sys::fs::file_type::block_file)
- return getMemoryBufferForStream(FD, Filename);
-
- FileSize = Status.getSize();
- }
- MapSize = FileSize;
- }
-
- if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
- PageSize, IsVolatile)) {
- std::error_code EC;
- std::unique_ptr<MB> Result(
- new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile<MB>(
- RequiresNullTerminator, FD, MapSize, Offset, EC));
- if (!EC)
- return std::move(Result);
- }
-
- auto Buf = WritableMemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
- if (!Buf) {
- // Failed to create a buffer. The only way it can fail is if
- // new(std::nothrow) returns 0.
- return make_error_code(errc::not_enough_memory);
- }
-
- char *BufPtr = Buf.get()->getBufferStart();
-
- size_t BytesLeft = MapSize;
-#ifndef HAVE_PREAD
- if (lseek(FD, Offset, SEEK_SET) == -1)
- return std::error_code(errno, std::generic_category());
-#endif
-
- while (BytesLeft) {
-#ifdef HAVE_PREAD
- ssize_t NumRead = sys::RetryAfterSignal(-1, ::pread, FD, BufPtr, BytesLeft,
- MapSize - BytesLeft + Offset);
-#else
- ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, BufPtr, BytesLeft);
-#endif
- if (NumRead == -1) {
- // Error while reading.
- return std::error_code(errno, std::generic_category());
- }
- if (NumRead == 0) {
- memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer.
- break;
- }
- BytesLeft -= NumRead;
- BufPtr += NumRead;
- }
-
- return std::move(Buf);
-}
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-MemoryBuffer::getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
- bool RequiresNullTerminator, bool IsVolatile) {
- return getOpenFileImpl<MemoryBuffer>(FD, Filename, FileSize, FileSize, 0,
- RequiresNullTerminator, IsVolatile);
-}
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-MemoryBuffer::getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
- int64_t Offset, bool IsVolatile) {
- assert(MapSize != uint64_t(-1));
- return getOpenFileImpl<MemoryBuffer>(FD, Filename, -1, MapSize, Offset, false,
- IsVolatile);
-}
-
-ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() {
- // Read in all of the data from stdin, we cannot mmap stdin.
- //
- // FIXME: That isn't necessarily true, we should try to mmap stdin and
- // fallback if it fails.
- sys::ChangeStdinToBinary();
-
- return getMemoryBufferForStream(0, "<stdin>");
-}
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-MemoryBuffer::getFileAsStream(const Twine &Filename) {
- int FD;
- std::error_code EC = sys::fs::openFileForRead(Filename, FD, sys::fs::OF_None);
- if (EC)
- return EC;
- ErrorOr<std::unique_ptr<MemoryBuffer>> Ret =
- getMemoryBufferForStream(FD, Filename);
- close(FD);
- return Ret;
-}
-
-MemoryBufferRef MemoryBuffer::getMemBufferRef() const {
- StringRef Data = getBuffer();
- StringRef Identifier = getBufferIdentifier();
- return MemoryBufferRef(Data, Identifier);
-}
-
-SmallVectorMemoryBuffer::~SmallVectorMemoryBuffer() {}
diff --git a/gnu/llvm/lib/Support/Mutex.cpp b/gnu/llvm/lib/Support/Mutex.cpp
deleted file mode 100644
index 7138c7a4b98..00000000000
--- a/gnu/llvm/lib/Support/Mutex.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-//===- Mutex.cpp - Mutual Exclusion Lock ------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the llvm::sys::Mutex class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Mutex.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/ErrorHandling.h"
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
-
-#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
-// Define all methods as no-ops if threading is explicitly disabled
-namespace llvm {
-using namespace sys;
-MutexImpl::MutexImpl( bool recursive) { }
-MutexImpl::~MutexImpl() { }
-bool MutexImpl::acquire() { return true; }
-bool MutexImpl::release() { return true; }
-bool MutexImpl::tryacquire() { return true; }
-}
-#else
-
-#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK)
-
-#include <cassert>
-#include <pthread.h>
-#include <stdlib.h>
-
-namespace llvm {
-using namespace sys;
-
-// Construct a Mutex using pthread calls
-MutexImpl::MutexImpl( bool recursive)
- : data_(nullptr)
-{
- // Declare the pthread_mutex data structures
- pthread_mutex_t* mutex =
- static_cast<pthread_mutex_t*>(safe_malloc(sizeof(pthread_mutex_t)));
-
- pthread_mutexattr_t attr;
-
- // Initialize the mutex attributes
- int errorcode = pthread_mutexattr_init(&attr);
- assert(errorcode == 0); (void)errorcode;
-
- // Initialize the mutex as a recursive mutex, if requested, or normal
- // otherwise.
- int kind = ( recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL );
- errorcode = pthread_mutexattr_settype(&attr, kind);
- assert(errorcode == 0);
-
- // Initialize the mutex
- errorcode = pthread_mutex_init(mutex, &attr);
- assert(errorcode == 0);
-
- // Destroy the attributes
- errorcode = pthread_mutexattr_destroy(&attr);
- assert(errorcode == 0);
-
- // Assign the data member
- data_ = mutex;
-}
-
-// Destruct a Mutex
-MutexImpl::~MutexImpl()
-{
- pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
- assert(mutex != nullptr);
- pthread_mutex_destroy(mutex);
- free(mutex);
-}
-
-bool
-MutexImpl::acquire()
-{
- pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
- assert(mutex != nullptr);
-
- int errorcode = pthread_mutex_lock(mutex);
- return errorcode == 0;
-}
-
-bool
-MutexImpl::release()
-{
- pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
- assert(mutex != nullptr);
-
- int errorcode = pthread_mutex_unlock(mutex);
- return errorcode == 0;
-}
-
-bool
-MutexImpl::tryacquire()
-{
- pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
- assert(mutex != nullptr);
-
- int errorcode = pthread_mutex_trylock(mutex);
- return errorcode == 0;
-}
-
-}
-
-#elif defined(LLVM_ON_UNIX)
-#include "Unix/Mutex.inc"
-#elif defined( _WIN32)
-#include "Windows/Mutex.inc"
-#else
-#warning Neither LLVM_ON_UNIX nor _WIN32 was set in Support/Mutex.cpp
-#endif
-#endif
diff --git a/gnu/llvm/lib/Support/NativeFormatting.cpp b/gnu/llvm/lib/Support/NativeFormatting.cpp
deleted file mode 100644
index 85b4bfb8156..00000000000
--- a/gnu/llvm/lib/Support/NativeFormatting.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-//===- NativeFormatting.cpp - Low level formatting helpers -------*- C++-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/NativeFormatting.h"
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Format.h"
-
-#include <float.h>
-
-using namespace llvm;
-
-template<typename T, std::size_t N>
-static int format_to_buffer(T Value, char (&Buffer)[N]) {
- char *EndPtr = std::end(Buffer);
- char *CurPtr = EndPtr;
-
- do {
- *--CurPtr = '0' + char(Value % 10);
- Value /= 10;
- } while (Value);
- return EndPtr - CurPtr;
-}
-
-static void writeWithCommas(raw_ostream &S, ArrayRef<char> Buffer) {
- assert(!Buffer.empty());
-
- ArrayRef<char> ThisGroup;
- int InitialDigits = ((Buffer.size() - 1) % 3) + 1;
- ThisGroup = Buffer.take_front(InitialDigits);
- S.write(ThisGroup.data(), ThisGroup.size());
-
- Buffer = Buffer.drop_front(InitialDigits);
- assert(Buffer.size() % 3 == 0);
- while (!Buffer.empty()) {
- S << ',';
- ThisGroup = Buffer.take_front(3);
- S.write(ThisGroup.data(), 3);
- Buffer = Buffer.drop_front(3);
- }
-}
-
-template <typename T>
-static void write_unsigned_impl(raw_ostream &S, T N, size_t MinDigits,
- IntegerStyle Style, bool IsNegative) {
- static_assert(std::is_unsigned<T>::value, "Value is not unsigned!");
-
- char NumberBuffer[128];
- std::memset(NumberBuffer, '0', sizeof(NumberBuffer));
-
- size_t Len = 0;
- Len = format_to_buffer(N, NumberBuffer);
-
- if (IsNegative)
- S << '-';
-
- if (Len < MinDigits && Style != IntegerStyle::Number) {
- for (size_t I = Len; I < MinDigits; ++I)
- S << '0';
- }
-
- if (Style == IntegerStyle::Number) {
- writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len));
- } else {
- S.write(std::end(NumberBuffer) - Len, Len);
- }
-}
-
-template <typename T>
-static void write_unsigned(raw_ostream &S, T N, size_t MinDigits,
- IntegerStyle Style, bool IsNegative = false) {
- // Output using 32-bit div/mod if possible.
- if (N == static_cast<uint32_t>(N))
- write_unsigned_impl(S, static_cast<uint32_t>(N), MinDigits, Style,
- IsNegative);
- else
- write_unsigned_impl(S, N, MinDigits, Style, IsNegative);
-}
-
-template <typename T>
-static void write_signed(raw_ostream &S, T N, size_t MinDigits,
- IntegerStyle Style) {
- static_assert(std::is_signed<T>::value, "Value is not signed!");
-
- using UnsignedT = typename std::make_unsigned<T>::type;
-
- if (N >= 0) {
- write_unsigned(S, static_cast<UnsignedT>(N), MinDigits, Style);
- return;
- }
-
- UnsignedT UN = -(UnsignedT)N;
- write_unsigned(S, UN, MinDigits, Style, true);
-}
-
-void llvm::write_integer(raw_ostream &S, unsigned int N, size_t MinDigits,
- IntegerStyle Style) {
- write_unsigned(S, N, MinDigits, Style);
-}
-
-void llvm::write_integer(raw_ostream &S, int N, size_t MinDigits,
- IntegerStyle Style) {
- write_signed(S, N, MinDigits, Style);
-}
-
-void llvm::write_integer(raw_ostream &S, unsigned long N, size_t MinDigits,
- IntegerStyle Style) {
- write_unsigned(S, N, MinDigits, Style);
-}
-
-void llvm::write_integer(raw_ostream &S, long N, size_t MinDigits,
- IntegerStyle Style) {
- write_signed(S, N, MinDigits, Style);
-}
-
-void llvm::write_integer(raw_ostream &S, unsigned long long N, size_t MinDigits,
- IntegerStyle Style) {
- write_unsigned(S, N, MinDigits, Style);
-}
-
-void llvm::write_integer(raw_ostream &S, long long N, size_t MinDigits,
- IntegerStyle Style) {
- write_signed(S, N, MinDigits, Style);
-}
-
-void llvm::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
- Optional<size_t> Width) {
- const size_t kMaxWidth = 128u;
-
- size_t W = std::min(kMaxWidth, Width.getValueOr(0u));
-
- unsigned Nibbles = (64 - countLeadingZeros(N) + 3) / 4;
- bool Prefix = (Style == HexPrintStyle::PrefixLower ||
- Style == HexPrintStyle::PrefixUpper);
- bool Upper =
- (Style == HexPrintStyle::Upper || Style == HexPrintStyle::PrefixUpper);
- unsigned PrefixChars = Prefix ? 2 : 0;
- unsigned NumChars =
- std::max(static_cast<unsigned>(W), std::max(1u, Nibbles) + PrefixChars);
-
- char NumberBuffer[kMaxWidth];
- ::memset(NumberBuffer, '0', llvm::array_lengthof(NumberBuffer));
- if (Prefix)
- NumberBuffer[1] = 'x';
- char *EndPtr = NumberBuffer + NumChars;
- char *CurPtr = EndPtr;
- while (N) {
- unsigned char x = static_cast<unsigned char>(N) % 16;
- *--CurPtr = hexdigit(x, !Upper);
- N /= 16;
- }
-
- S.write(NumberBuffer, NumChars);
-}
-
-void llvm::write_double(raw_ostream &S, double N, FloatStyle Style,
- Optional<size_t> Precision) {
- size_t Prec = Precision.getValueOr(getDefaultPrecision(Style));
-
- if (std::isnan(N)) {
- S << "nan";
- return;
- } else if (std::isinf(N)) {
- S << "INF";
- return;
- }
-
- char Letter;
- if (Style == FloatStyle::Exponent)
- Letter = 'e';
- else if (Style == FloatStyle::ExponentUpper)
- Letter = 'E';
- else
- Letter = 'f';
-
- SmallString<8> Spec;
- llvm::raw_svector_ostream Out(Spec);
- Out << "%." << Prec << Letter;
-
- if (Style == FloatStyle::Exponent || Style == FloatStyle::ExponentUpper) {
-#ifdef _WIN32
-// On MSVCRT and compatible, output of %e is incompatible to Posix
-// by default. Number of exponent digits should be at least 2. "%+03d"
-// FIXME: Implement our formatter to here or Support/Format.h!
-#if defined(__MINGW32__)
- // FIXME: It should be generic to C++11.
- if (N == 0.0 && std::signbit(N)) {
- char NegativeZero[] = "-0.000000e+00";
- if (Style == FloatStyle::ExponentUpper)
- NegativeZero[strlen(NegativeZero) - 4] = 'E';
- S << NegativeZero;
- return;
- }
-#else
- int fpcl = _fpclass(N);
-
- // negative zero
- if (fpcl == _FPCLASS_NZ) {
- char NegativeZero[] = "-0.000000e+00";
- if (Style == FloatStyle::ExponentUpper)
- NegativeZero[strlen(NegativeZero) - 4] = 'E';
- S << NegativeZero;
- return;
- }
-#endif
-
- char buf[32];
- unsigned len;
- len = format(Spec.c_str(), N).snprint(buf, sizeof(buf));
- if (len <= sizeof(buf) - 2) {
- if (len >= 5 && (buf[len - 5] == 'e' || buf[len - 5] == 'E') &&
- buf[len - 3] == '0') {
- int cs = buf[len - 4];
- if (cs == '+' || cs == '-') {
- int c1 = buf[len - 2];
- int c0 = buf[len - 1];
- if (isdigit(static_cast<unsigned char>(c1)) &&
- isdigit(static_cast<unsigned char>(c0))) {
- // Trim leading '0': "...e+012" -> "...e+12\0"
- buf[len - 3] = c1;
- buf[len - 2] = c0;
- buf[--len] = 0;
- }
- }
- }
- S << buf;
- return;
- }
-#endif
- }
-
- if (Style == FloatStyle::Percent)
- N *= 100.0;
-
- char Buf[32];
- format(Spec.c_str(), N).snprint(Buf, sizeof(Buf));
- S << Buf;
- if (Style == FloatStyle::Percent)
- S << '%';
-}
-
-bool llvm::isPrefixedHexStyle(HexPrintStyle S) {
- return (S == HexPrintStyle::PrefixLower || S == HexPrintStyle::PrefixUpper);
-}
-
-size_t llvm::getDefaultPrecision(FloatStyle Style) {
- switch (Style) {
- case FloatStyle::Exponent:
- case FloatStyle::ExponentUpper:
- return 6; // Number of decimal places.
- case FloatStyle::Fixed:
- case FloatStyle::Percent:
- return 2; // Number of decimal places.
- }
- LLVM_BUILTIN_UNREACHABLE;
-}
diff --git a/gnu/llvm/lib/Support/Options.cpp b/gnu/llvm/lib/Support/Options.cpp
deleted file mode 100644
index 71258450efa..00000000000
--- a/gnu/llvm/lib/Support/Options.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- llvm/Support/Options.cpp - Debug options support ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the helper objects for defining debug options using the
-// new API built on cl::opt, but not requiring the use of static globals.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Options.h"
-#include "llvm/Support/ManagedStatic.h"
-
-using namespace llvm;
-
-OptionRegistry::~OptionRegistry() {
- for (auto IT = Options.begin(); IT != Options.end(); ++IT)
- delete IT->second;
-}
-
-void OptionRegistry::addOption(void *Key, cl::Option *O) {
- assert(Options.find(Key) == Options.end() &&
- "Argument with this key already registerd");
- Options.insert(std::make_pair(Key, O));
-}
-
-static ManagedStatic<OptionRegistry> OR;
-
-OptionRegistry &OptionRegistry::instance() { return *OR; }
diff --git a/gnu/llvm/lib/Support/Parallel.cpp b/gnu/llvm/lib/Support/Parallel.cpp
deleted file mode 100644
index 1844003b9d3..00000000000
--- a/gnu/llvm/lib/Support/Parallel.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-//===- llvm/Support/Parallel.cpp - Parallel algorithms --------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Parallel.h"
-#include "llvm/Config/llvm-config.h"
-
-#if LLVM_ENABLE_THREADS
-
-#include "llvm/Support/Threading.h"
-
-#include <atomic>
-#include <stack>
-#include <thread>
-
-using namespace llvm;
-
-namespace {
-
-/// An abstract class that takes closures and runs them asynchronously.
-class Executor {
-public:
- virtual ~Executor() = default;
- virtual void add(std::function<void()> func) = 0;
-
- static Executor *getDefaultExecutor();
-};
-
-#if defined(_MSC_VER)
-/// An Executor that runs tasks via ConcRT.
-class ConcRTExecutor : public Executor {
- struct Taskish {
- Taskish(std::function<void()> Task) : Task(Task) {}
-
- std::function<void()> Task;
-
- static void run(void *P) {
- Taskish *Self = static_cast<Taskish *>(P);
- Self->Task();
- concurrency::Free(Self);
- }
- };
-
-public:
- virtual void add(std::function<void()> F) {
- Concurrency::CurrentScheduler::ScheduleTask(
- Taskish::run, new (concurrency::Alloc(sizeof(Taskish))) Taskish(F));
- }
-};
-
-Executor *Executor::getDefaultExecutor() {
- static ConcRTExecutor exec;
- return &exec;
-}
-
-#else
-/// An implementation of an Executor that runs closures on a thread pool
-/// in filo order.
-class ThreadPoolExecutor : public Executor {
-public:
- explicit ThreadPoolExecutor(unsigned ThreadCount = hardware_concurrency())
- : Done(ThreadCount) {
- // Spawn all but one of the threads in another thread as spawning threads
- // can take a while.
- std::thread([&, ThreadCount] {
- for (size_t i = 1; i < ThreadCount; ++i) {
- std::thread([=] { work(); }).detach();
- }
- work();
- }).detach();
- }
-
- ~ThreadPoolExecutor() override {
- std::unique_lock<std::mutex> Lock(Mutex);
- Stop = true;
- Lock.unlock();
- Cond.notify_all();
- // Wait for ~Latch.
- }
-
- void add(std::function<void()> F) override {
- std::unique_lock<std::mutex> Lock(Mutex);
- WorkStack.push(F);
- Lock.unlock();
- Cond.notify_one();
- }
-
-private:
- void work() {
- while (true) {
- std::unique_lock<std::mutex> Lock(Mutex);
- Cond.wait(Lock, [&] { return Stop || !WorkStack.empty(); });
- if (Stop)
- break;
- auto Task = WorkStack.top();
- WorkStack.pop();
- Lock.unlock();
- Task();
- }
- Done.dec();
- }
-
- std::atomic<bool> Stop{false};
- std::stack<std::function<void()>> WorkStack;
- std::mutex Mutex;
- std::condition_variable Cond;
- parallel::detail::Latch Done;
-};
-
-Executor *Executor::getDefaultExecutor() {
- static ThreadPoolExecutor exec;
- return &exec;
-}
-#endif
-}
-
-void parallel::detail::TaskGroup::spawn(std::function<void()> F) {
- L.inc();
- Executor::getDefaultExecutor()->add([&, F] {
- F();
- L.dec();
- });
-}
-#endif // LLVM_ENABLE_THREADS
diff --git a/gnu/llvm/lib/Support/Path.cpp b/gnu/llvm/lib/Support/Path.cpp
deleted file mode 100644
index 5ce2f50ebda..00000000000
--- a/gnu/llvm/lib/Support/Path.cpp
+++ /dev/null
@@ -1,1243 +0,0 @@
-//===-- Path.cpp - Implement OS Path Concept ------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the operating system Path API.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Path.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/Signals.h"
-#include <cctype>
-#include <cstring>
-
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-#include <unistd.h>
-#else
-#include <io.h>
-#endif
-
-using namespace llvm;
-using namespace llvm::support::endian;
-
-namespace {
- using llvm::StringRef;
- using llvm::sys::path::is_separator;
- using llvm::sys::path::Style;
-
- inline Style real_style(Style style) {
-#ifdef _WIN32
- return (style == Style::posix) ? Style::posix : Style::windows;
-#else
- return (style == Style::windows) ? Style::windows : Style::posix;
-#endif
- }
-
- inline const char *separators(Style style) {
- if (real_style(style) == Style::windows)
- return "\\/";
- return "/";
- }
-
- inline char preferred_separator(Style style) {
- if (real_style(style) == Style::windows)
- return '\\';
- return '/';
- }
-
- StringRef find_first_component(StringRef path, Style style) {
- // Look for this first component in the following order.
- // * empty (in this case we return an empty string)
- // * either C: or {//,\\}net.
- // * {/,\}
- // * {file,directory}name
-
- if (path.empty())
- return path;
-
- if (real_style(style) == Style::windows) {
- // C:
- if (path.size() >= 2 &&
- std::isalpha(static_cast<unsigned char>(path[0])) && path[1] == ':')
- return path.substr(0, 2);
- }
-
- // //net
- if ((path.size() > 2) && is_separator(path[0], style) &&
- path[0] == path[1] && !is_separator(path[2], style)) {
- // Find the next directory separator.
- size_t end = path.find_first_of(separators(style), 2);
- return path.substr(0, end);
- }
-
- // {/,\}
- if (is_separator(path[0], style))
- return path.substr(0, 1);
-
- // * {file,directory}name
- size_t end = path.find_first_of(separators(style));
- return path.substr(0, end);
- }
-
- // Returns the first character of the filename in str. For paths ending in
- // '/', it returns the position of the '/'.
- size_t filename_pos(StringRef str, Style style) {
- if (str.size() > 0 && is_separator(str[str.size() - 1], style))
- return str.size() - 1;
-
- size_t pos = str.find_last_of(separators(style), str.size() - 1);
-
- if (real_style(style) == Style::windows) {
- if (pos == StringRef::npos)
- pos = str.find_last_of(':', str.size() - 2);
- }
-
- if (pos == StringRef::npos || (pos == 1 && is_separator(str[0], style)))
- return 0;
-
- return pos + 1;
- }
-
- // Returns the position of the root directory in str. If there is no root
- // directory in str, it returns StringRef::npos.
- size_t root_dir_start(StringRef str, Style style) {
- // case "c:/"
- if (real_style(style) == Style::windows) {
- if (str.size() > 2 && str[1] == ':' && is_separator(str[2], style))
- return 2;
- }
-
- // case "//net"
- if (str.size() > 3 && is_separator(str[0], style) && str[0] == str[1] &&
- !is_separator(str[2], style)) {
- return str.find_first_of(separators(style), 2);
- }
-
- // case "/"
- if (str.size() > 0 && is_separator(str[0], style))
- return 0;
-
- return StringRef::npos;
- }
-
- // Returns the position past the end of the "parent path" of path. The parent
- // path will not end in '/', unless the parent is the root directory. If the
- // path has no parent, 0 is returned.
- size_t parent_path_end(StringRef path, Style style) {
- size_t end_pos = filename_pos(path, style);
-
- bool filename_was_sep =
- path.size() > 0 && is_separator(path[end_pos], style);
-
- // Skip separators until we reach root dir (or the start of the string).
- size_t root_dir_pos = root_dir_start(path, style);
- while (end_pos > 0 &&
- (root_dir_pos == StringRef::npos || end_pos > root_dir_pos) &&
- is_separator(path[end_pos - 1], style))
- --end_pos;
-
- if (end_pos == root_dir_pos && !filename_was_sep) {
- // We've reached the root dir and the input path was *not* ending in a
- // sequence of slashes. Include the root dir in the parent path.
- return root_dir_pos + 1;
- }
-
- // Otherwise, just include before the last slash.
- return end_pos;
- }
-} // end unnamed namespace
-
-enum FSEntity {
- FS_Dir,
- FS_File,
- FS_Name
-};
-
-static std::error_code
-createUniqueEntity(const Twine &Model, int &ResultFD,
- SmallVectorImpl<char> &ResultPath, bool MakeAbsolute,
- unsigned Mode, FSEntity Type,
- sys::fs::OpenFlags Flags = sys::fs::OF_None) {
- SmallString<128> ModelStorage;
- Model.toVector(ModelStorage);
-
- if (MakeAbsolute) {
- // Make model absolute by prepending a temp directory if it's not already.
- if (!sys::path::is_absolute(Twine(ModelStorage))) {
- SmallString<128> TDir;
- sys::path::system_temp_directory(true, TDir);
- sys::path::append(TDir, Twine(ModelStorage));
- ModelStorage.swap(TDir);
- }
- }
-
- // From here on, DO NOT modify model. It may be needed if the randomly chosen
- // path already exists.
- ResultPath = ModelStorage;
- // Null terminate.
- ResultPath.push_back(0);
- ResultPath.pop_back();
-
- // Limit the number of attempts we make, so that we don't infinite loop. E.g.
- // "permission denied" could be for a specific file (so we retry with a
- // different name) or for the whole directory (retry would always fail).
- // Checking which is racy, so we try a number of times, then give up.
- std::error_code EC;
- for (int Retries = 128; Retries > 0; --Retries) {
- // Replace '%' with random chars.
- for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
- if (ModelStorage[i] == '%')
- ResultPath[i] =
- "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
- }
-
- // Try to open + create the file.
- switch (Type) {
- case FS_File: {
- EC = sys::fs::openFileForReadWrite(Twine(ResultPath.begin()), ResultFD,
- sys::fs::CD_CreateNew, Flags, Mode);
- if (EC) {
- // errc::permission_denied happens on Windows when we try to open a file
- // that has been marked for deletion.
- if (EC == errc::file_exists || EC == errc::permission_denied)
- continue;
- return EC;
- }
-
- return std::error_code();
- }
-
- case FS_Name: {
- EC = sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
- if (EC == errc::no_such_file_or_directory)
- return std::error_code();
- if (EC)
- return EC;
- continue;
- }
-
- case FS_Dir: {
- EC = sys::fs::create_directory(ResultPath.begin(), false);
- if (EC) {
- if (EC == errc::file_exists)
- continue;
- return EC;
- }
- return std::error_code();
- }
- }
- llvm_unreachable("Invalid Type");
- }
- return EC;
-}
-
-namespace llvm {
-namespace sys {
-namespace path {
-
-const_iterator begin(StringRef path, Style style) {
- const_iterator i;
- i.Path = path;
- i.Component = find_first_component(path, style);
- i.Position = 0;
- i.S = style;
- return i;
-}
-
-const_iterator end(StringRef path) {
- const_iterator i;
- i.Path = path;
- i.Position = path.size();
- return i;
-}
-
-const_iterator &const_iterator::operator++() {
- assert(Position < Path.size() && "Tried to increment past end!");
-
- // Increment Position to past the current component
- Position += Component.size();
-
- // Check for end.
- if (Position == Path.size()) {
- Component = StringRef();
- return *this;
- }
-
- // Both POSIX and Windows treat paths that begin with exactly two separators
- // specially.
- bool was_net = Component.size() > 2 && is_separator(Component[0], S) &&
- Component[1] == Component[0] && !is_separator(Component[2], S);
-
- // Handle separators.
- if (is_separator(Path[Position], S)) {
- // Root dir.
- if (was_net ||
- // c:/
- (real_style(S) == Style::windows && Component.endswith(":"))) {
- Component = Path.substr(Position, 1);
- return *this;
- }
-
- // Skip extra separators.
- while (Position != Path.size() && is_separator(Path[Position], S)) {
- ++Position;
- }
-
- // Treat trailing '/' as a '.', unless it is the root dir.
- if (Position == Path.size() && Component != "/") {
- --Position;
- Component = ".";
- return *this;
- }
- }
-
- // Find next component.
- size_t end_pos = Path.find_first_of(separators(S), Position);
- Component = Path.slice(Position, end_pos);
-
- return *this;
-}
-
-bool const_iterator::operator==(const const_iterator &RHS) const {
- return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
-}
-
-ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
- return Position - RHS.Position;
-}
-
-reverse_iterator rbegin(StringRef Path, Style style) {
- reverse_iterator I;
- I.Path = Path;
- I.Position = Path.size();
- I.S = style;
- return ++I;
-}
-
-reverse_iterator rend(StringRef Path) {
- reverse_iterator I;
- I.Path = Path;
- I.Component = Path.substr(0, 0);
- I.Position = 0;
- return I;
-}
-
-reverse_iterator &reverse_iterator::operator++() {
- size_t root_dir_pos = root_dir_start(Path, S);
-
- // Skip separators unless it's the root directory.
- size_t end_pos = Position;
- while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
- is_separator(Path[end_pos - 1], S))
- --end_pos;
-
- // Treat trailing '/' as a '.', unless it is the root dir.
- if (Position == Path.size() && !Path.empty() &&
- is_separator(Path.back(), S) &&
- (root_dir_pos == StringRef::npos || end_pos - 1 > root_dir_pos)) {
- --Position;
- Component = ".";
- return *this;
- }
-
- // Find next separator.
- size_t start_pos = filename_pos(Path.substr(0, end_pos), S);
- Component = Path.slice(start_pos, end_pos);
- Position = start_pos;
- return *this;
-}
-
-bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
- return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
- Position == RHS.Position;
-}
-
-ptrdiff_t reverse_iterator::operator-(const reverse_iterator &RHS) const {
- return Position - RHS.Position;
-}
-
-StringRef root_path(StringRef path, Style style) {
- const_iterator b = begin(path, style), pos = b, e = end(path);
- if (b != e) {
- bool has_net =
- b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
- bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
-
- if (has_net || has_drive) {
- if ((++pos != e) && is_separator((*pos)[0], style)) {
- // {C:/,//net/}, so get the first two components.
- return path.substr(0, b->size() + pos->size());
- } else {
- // just {C:,//net}, return the first component.
- return *b;
- }
- }
-
- // POSIX style root directory.
- if (is_separator((*b)[0], style)) {
- return *b;
- }
- }
-
- return StringRef();
-}
-
-StringRef root_name(StringRef path, Style style) {
- const_iterator b = begin(path, style), e = end(path);
- if (b != e) {
- bool has_net =
- b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
- bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
-
- if (has_net || has_drive) {
- // just {C:,//net}, return the first component.
- return *b;
- }
- }
-
- // No path or no name.
- return StringRef();
-}
-
-StringRef root_directory(StringRef path, Style style) {
- const_iterator b = begin(path, style), pos = b, e = end(path);
- if (b != e) {
- bool has_net =
- b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
- bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
-
- if ((has_net || has_drive) &&
- // {C:,//net}, skip to the next component.
- (++pos != e) && is_separator((*pos)[0], style)) {
- return *pos;
- }
-
- // POSIX style root directory.
- if (!has_net && is_separator((*b)[0], style)) {
- return *b;
- }
- }
-
- // No path or no root.
- return StringRef();
-}
-
-StringRef relative_path(StringRef path, Style style) {
- StringRef root = root_path(path, style);
- return path.substr(root.size());
-}
-
-void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
- const Twine &b, const Twine &c, const Twine &d) {
- SmallString<32> a_storage;
- SmallString<32> b_storage;
- SmallString<32> c_storage;
- SmallString<32> d_storage;
-
- SmallVector<StringRef, 4> components;
- if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
- if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
- if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
- if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
-
- for (auto &component : components) {
- bool path_has_sep =
- !path.empty() && is_separator(path[path.size() - 1], style);
- if (path_has_sep) {
- // Strip separators from beginning of component.
- size_t loc = component.find_first_not_of(separators(style));
- StringRef c = component.substr(loc);
-
- // Append it.
- path.append(c.begin(), c.end());
- continue;
- }
-
- bool component_has_sep =
- !component.empty() && is_separator(component[0], style);
- if (!component_has_sep &&
- !(path.empty() || has_root_name(component, style))) {
- // Add a separator.
- path.push_back(preferred_separator(style));
- }
-
- path.append(component.begin(), component.end());
- }
-}
-
-void append(SmallVectorImpl<char> &path, const Twine &a, const Twine &b,
- const Twine &c, const Twine &d) {
- append(path, Style::native, a, b, c, d);
-}
-
-void append(SmallVectorImpl<char> &path, const_iterator begin,
- const_iterator end, Style style) {
- for (; begin != end; ++begin)
- path::append(path, style, *begin);
-}
-
-StringRef parent_path(StringRef path, Style style) {
- size_t end_pos = parent_path_end(path, style);
- if (end_pos == StringRef::npos)
- return StringRef();
- else
- return path.substr(0, end_pos);
-}
-
-void remove_filename(SmallVectorImpl<char> &path, Style style) {
- size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()), style);
- if (end_pos != StringRef::npos)
- path.set_size(end_pos);
-}
-
-void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
- Style style) {
- StringRef p(path.begin(), path.size());
- SmallString<32> ext_storage;
- StringRef ext = extension.toStringRef(ext_storage);
-
- // Erase existing extension.
- size_t pos = p.find_last_of('.');
- if (pos != StringRef::npos && pos >= filename_pos(p, style))
- path.set_size(pos);
-
- // Append '.' if needed.
- if (ext.size() > 0 && ext[0] != '.')
- path.push_back('.');
-
- // Append extension.
- path.append(ext.begin(), ext.end());
-}
-
-void replace_path_prefix(SmallVectorImpl<char> &Path,
- const StringRef &OldPrefix, const StringRef &NewPrefix,
- Style style) {
- if (OldPrefix.empty() && NewPrefix.empty())
- return;
-
- StringRef OrigPath(Path.begin(), Path.size());
- if (!OrigPath.startswith(OldPrefix))
- return;
-
- // If prefixes have the same size we can simply copy the new one over.
- if (OldPrefix.size() == NewPrefix.size()) {
- llvm::copy(NewPrefix, Path.begin());
- return;
- }
-
- StringRef RelPath = OrigPath.substr(OldPrefix.size());
- SmallString<256> NewPath;
- path::append(NewPath, style, NewPrefix);
- path::append(NewPath, style, RelPath);
- Path.swap(NewPath);
-}
-
-void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
- assert((!path.isSingleStringRef() ||
- path.getSingleStringRef().data() != result.data()) &&
- "path and result are not allowed to overlap!");
- // Clear result.
- result.clear();
- path.toVector(result);
- native(result, style);
-}
-
-void native(SmallVectorImpl<char> &Path, Style style) {
- if (Path.empty())
- return;
- if (real_style(style) == Style::windows) {
- std::replace(Path.begin(), Path.end(), '/', '\\');
- if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) {
- SmallString<128> PathHome;
- home_directory(PathHome);
- PathHome.append(Path.begin() + 1, Path.end());
- Path = PathHome;
- }
- } else {
- for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
- if (*PI == '\\') {
- auto PN = PI + 1;
- if (PN < PE && *PN == '\\')
- ++PI; // increment once, the for loop will move over the escaped slash
- else
- *PI = '/';
- }
- }
- }
-}
-
-std::string convert_to_slash(StringRef path, Style style) {
- if (real_style(style) != Style::windows)
- return path;
-
- std::string s = path.str();
- std::replace(s.begin(), s.end(), '\\', '/');
- return s;
-}
-
-StringRef filename(StringRef path, Style style) { return *rbegin(path, style); }
-
-StringRef stem(StringRef path, Style style) {
- StringRef fname = filename(path, style);
- size_t pos = fname.find_last_of('.');
- if (pos == StringRef::npos)
- return fname;
- else
- if ((fname.size() == 1 && fname == ".") ||
- (fname.size() == 2 && fname == ".."))
- return fname;
- else
- return fname.substr(0, pos);
-}
-
-StringRef extension(StringRef path, Style style) {
- StringRef fname = filename(path, style);
- size_t pos = fname.find_last_of('.');
- if (pos == StringRef::npos)
- return StringRef();
- else
- if ((fname.size() == 1 && fname == ".") ||
- (fname.size() == 2 && fname == ".."))
- return StringRef();
- else
- return fname.substr(pos);
-}
-
-bool is_separator(char value, Style style) {
- if (value == '/')
- return true;
- if (real_style(style) == Style::windows)
- return value == '\\';
- return false;
-}
-
-StringRef get_separator(Style style) {
- if (real_style(style) == Style::windows)
- return "\\";
- return "/";
-}
-
-bool has_root_name(const Twine &path, Style style) {
- SmallString<128> path_storage;
- StringRef p = path.toStringRef(path_storage);
-
- return !root_name(p, style).empty();
-}
-
-bool has_root_directory(const Twine &path, Style style) {
- SmallString<128> path_storage;
- StringRef p = path.toStringRef(path_storage);
-
- return !root_directory(p, style).empty();
-}
-
-bool has_root_path(const Twine &path, Style style) {
- SmallString<128> path_storage;
- StringRef p = path.toStringRef(path_storage);
-
- return !root_path(p, style).empty();
-}
-
-bool has_relative_path(const Twine &path, Style style) {
- SmallString<128> path_storage;
- StringRef p = path.toStringRef(path_storage);
-
- return !relative_path(p, style).empty();
-}
-
-bool has_filename(const Twine &path, Style style) {
- SmallString<128> path_storage;
- StringRef p = path.toStringRef(path_storage);
-
- return !filename(p, style).empty();
-}
-
-bool has_parent_path(const Twine &path, Style style) {
- SmallString<128> path_storage;
- StringRef p = path.toStringRef(path_storage);
-
- return !parent_path(p, style).empty();
-}
-
-bool has_stem(const Twine &path, Style style) {
- SmallString<128> path_storage;
- StringRef p = path.toStringRef(path_storage);
-
- return !stem(p, style).empty();
-}
-
-bool has_extension(const Twine &path, Style style) {
- SmallString<128> path_storage;
- StringRef p = path.toStringRef(path_storage);
-
- return !extension(p, style).empty();
-}
-
-bool is_absolute(const Twine &path, Style style) {
- SmallString<128> path_storage;
- StringRef p = path.toStringRef(path_storage);
-
- bool rootDir = has_root_directory(p, style);
- bool rootName =
- (real_style(style) != Style::windows) || has_root_name(p, style);
-
- return rootDir && rootName;
-}
-
-bool is_relative(const Twine &path, Style style) {
- return !is_absolute(path, style);
-}
-
-StringRef remove_leading_dotslash(StringRef Path, Style style) {
- // Remove leading "./" (or ".//" or "././" etc.)
- while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1], style)) {
- Path = Path.substr(2);
- while (Path.size() > 0 && is_separator(Path[0], style))
- Path = Path.substr(1);
- }
- return Path;
-}
-
-static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot,
- Style style) {
- SmallVector<StringRef, 16> components;
-
- // Skip the root path, then look for traversal in the components.
- StringRef rel = path::relative_path(path, style);
- for (StringRef C :
- llvm::make_range(path::begin(rel, style), path::end(rel))) {
- if (C == ".")
- continue;
- // Leading ".." will remain in the path unless it's at the root.
- if (remove_dot_dot && C == "..") {
- if (!components.empty() && components.back() != "..") {
- components.pop_back();
- continue;
- }
- if (path::is_absolute(path, style))
- continue;
- }
- components.push_back(C);
- }
-
- SmallString<256> buffer = path::root_path(path, style);
- for (StringRef C : components)
- path::append(buffer, style, C);
- return buffer;
-}
-
-bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot,
- Style style) {
- StringRef p(path.data(), path.size());
-
- SmallString<256> result = remove_dots(p, remove_dot_dot, style);
- if (result == path)
- return false;
-
- path.swap(result);
- return true;
-}
-
-} // end namespace path
-
-namespace fs {
-
-std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
- file_status Status;
- std::error_code EC = status(Path, Status);
- if (EC)
- return EC;
- Result = Status.getUniqueID();
- return std::error_code();
-}
-
-std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
- SmallVectorImpl<char> &ResultPath,
- unsigned Mode) {
- return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
-}
-
-static std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
- SmallVectorImpl<char> &ResultPath,
- unsigned Mode, OpenFlags Flags) {
- return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File,
- Flags);
-}
-
-std::error_code createUniqueFile(const Twine &Model,
- SmallVectorImpl<char> &ResultPath,
- unsigned Mode) {
- int FD;
- auto EC = createUniqueFile(Model, FD, ResultPath, Mode);
- if (EC)
- return EC;
- // FD is only needed to avoid race conditions. Close it right away.
- close(FD);
- return EC;
-}
-
-static std::error_code
-createTemporaryFile(const Twine &Model, int &ResultFD,
- llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
- SmallString<128> Storage;
- StringRef P = Model.toNullTerminatedStringRef(Storage);
- assert(P.find_first_of(separators(Style::native)) == StringRef::npos &&
- "Model must be a simple filename.");
- // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
- return createUniqueEntity(P.begin(), ResultFD, ResultPath, true,
- owner_read | owner_write, Type);
-}
-
-static std::error_code
-createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
- llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
- const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
- return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
- Type);
-}
-
-std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
- int &ResultFD,
- SmallVectorImpl<char> &ResultPath) {
- return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
-}
-
-std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
- SmallVectorImpl<char> &ResultPath) {
- int FD;
- auto EC = createTemporaryFile(Prefix, Suffix, FD, ResultPath);
- if (EC)
- return EC;
- // FD is only needed to avoid race conditions. Close it right away.
- close(FD);
- return EC;
-}
-
-
-// This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
-// for consistency. We should try using mkdtemp.
-std::error_code createUniqueDirectory(const Twine &Prefix,
- SmallVectorImpl<char> &ResultPath) {
- int Dummy;
- return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath, true, 0,
- FS_Dir);
-}
-
-std::error_code
-getPotentiallyUniqueFileName(const Twine &Model,
- SmallVectorImpl<char> &ResultPath) {
- int Dummy;
- return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
-}
-
-std::error_code
-getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
- SmallVectorImpl<char> &ResultPath) {
- int Dummy;
- return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
-}
-
-void make_absolute(const Twine &current_directory,
- SmallVectorImpl<char> &path) {
- StringRef p(path.data(), path.size());
-
- bool rootDirectory = path::has_root_directory(p);
- bool rootName =
- (real_style(Style::native) != Style::windows) || path::has_root_name(p);
-
- // Already absolute.
- if (rootName && rootDirectory)
- return;
-
- // All of the following conditions will need the current directory.
- SmallString<128> current_dir;
- current_directory.toVector(current_dir);
-
- // Relative path. Prepend the current directory.
- if (!rootName && !rootDirectory) {
- // Append path to the current directory.
- path::append(current_dir, p);
- // Set path to the result.
- path.swap(current_dir);
- return;
- }
-
- if (!rootName && rootDirectory) {
- StringRef cdrn = path::root_name(current_dir);
- SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
- path::append(curDirRootName, p);
- // Set path to the result.
- path.swap(curDirRootName);
- return;
- }
-
- if (rootName && !rootDirectory) {
- StringRef pRootName = path::root_name(p);
- StringRef bRootDirectory = path::root_directory(current_dir);
- StringRef bRelativePath = path::relative_path(current_dir);
- StringRef pRelativePath = path::relative_path(p);
-
- SmallString<128> res;
- path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
- path.swap(res);
- return;
- }
-
- llvm_unreachable("All rootName and rootDirectory combinations should have "
- "occurred above!");
-}
-
-std::error_code make_absolute(SmallVectorImpl<char> &path) {
- if (path::is_absolute(path))
- return {};
-
- SmallString<128> current_dir;
- if (std::error_code ec = current_path(current_dir))
- return ec;
-
- make_absolute(current_dir, path);
- return {};
-}
-
-std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
- perms Perms) {
- SmallString<128> PathStorage;
- StringRef P = Path.toStringRef(PathStorage);
-
- // Be optimistic and try to create the directory
- std::error_code EC = create_directory(P, IgnoreExisting, Perms);
- // If we succeeded, or had any error other than the parent not existing, just
- // return it.
- if (EC != errc::no_such_file_or_directory)
- return EC;
-
- // We failed because of a no_such_file_or_directory, try to create the
- // parent.
- StringRef Parent = path::parent_path(P);
- if (Parent.empty())
- return EC;
-
- if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
- return EC;
-
- return create_directory(P, IgnoreExisting, Perms);
-}
-
-static std::error_code copy_file_internal(int ReadFD, int WriteFD) {
- const size_t BufSize = 4096;
- char *Buf = new char[BufSize];
- int BytesRead = 0, BytesWritten = 0;
- for (;;) {
- BytesRead = read(ReadFD, Buf, BufSize);
- if (BytesRead <= 0)
- break;
- while (BytesRead) {
- BytesWritten = write(WriteFD, Buf, BytesRead);
- if (BytesWritten < 0)
- break;
- BytesRead -= BytesWritten;
- }
- if (BytesWritten < 0)
- break;
- }
- delete[] Buf;
-
- if (BytesRead < 0 || BytesWritten < 0)
- return std::error_code(errno, std::generic_category());
- return std::error_code();
-}
-
-std::error_code copy_file(const Twine &From, const Twine &To) {
- int ReadFD, WriteFD;
- if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
- return EC;
- if (std::error_code EC =
- openFileForWrite(To, WriteFD, CD_CreateAlways, OF_None)) {
- close(ReadFD);
- return EC;
- }
-
- std::error_code EC = copy_file_internal(ReadFD, WriteFD);
-
- close(ReadFD);
- close(WriteFD);
-
- return EC;
-}
-
-std::error_code copy_file(const Twine &From, int ToFD) {
- int ReadFD;
- if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
- return EC;
-
- std::error_code EC = copy_file_internal(ReadFD, ToFD);
-
- close(ReadFD);
-
- return EC;
-}
-
-ErrorOr<MD5::MD5Result> md5_contents(int FD) {
- MD5 Hash;
-
- constexpr size_t BufSize = 4096;
- std::vector<uint8_t> Buf(BufSize);
- int BytesRead = 0;
- for (;;) {
- BytesRead = read(FD, Buf.data(), BufSize);
- if (BytesRead <= 0)
- break;
- Hash.update(makeArrayRef(Buf.data(), BytesRead));
- }
-
- if (BytesRead < 0)
- return std::error_code(errno, std::generic_category());
- MD5::MD5Result Result;
- Hash.final(Result);
- return Result;
-}
-
-ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) {
- int FD;
- if (auto EC = openFileForRead(Path, FD, OF_None))
- return EC;
-
- auto Result = md5_contents(FD);
- close(FD);
- return Result;
-}
-
-bool exists(const basic_file_status &status) {
- return status_known(status) && status.type() != file_type::file_not_found;
-}
-
-bool status_known(const basic_file_status &s) {
- return s.type() != file_type::status_error;
-}
-
-file_type get_file_type(const Twine &Path, bool Follow) {
- file_status st;
- if (status(Path, st, Follow))
- return file_type::status_error;
- return st.type();
-}
-
-bool is_directory(const basic_file_status &status) {
- return status.type() == file_type::directory_file;
-}
-
-std::error_code is_directory(const Twine &path, bool &result) {
- file_status st;
- if (std::error_code ec = status(path, st))
- return ec;
- result = is_directory(st);
- return std::error_code();
-}
-
-bool is_regular_file(const basic_file_status &status) {
- return status.type() == file_type::regular_file;
-}
-
-std::error_code is_regular_file(const Twine &path, bool &result) {
- file_status st;
- if (std::error_code ec = status(path, st))
- return ec;
- result = is_regular_file(st);
- return std::error_code();
-}
-
-bool is_symlink_file(const basic_file_status &status) {
- return status.type() == file_type::symlink_file;
-}
-
-std::error_code is_symlink_file(const Twine &path, bool &result) {
- file_status st;
- if (std::error_code ec = status(path, st, false))
- return ec;
- result = is_symlink_file(st);
- return std::error_code();
-}
-
-bool is_other(const basic_file_status &status) {
- return exists(status) &&
- !is_regular_file(status) &&
- !is_directory(status);
-}
-
-std::error_code is_other(const Twine &Path, bool &Result) {
- file_status FileStatus;
- if (std::error_code EC = status(Path, FileStatus))
- return EC;
- Result = is_other(FileStatus);
- return std::error_code();
-}
-
-void directory_entry::replace_filename(const Twine &Filename, file_type Type,
- basic_file_status Status) {
- SmallString<128> PathStr = path::parent_path(Path);
- path::append(PathStr, Filename);
- this->Path = PathStr.str();
- this->Type = Type;
- this->Status = Status;
-}
-
-ErrorOr<perms> getPermissions(const Twine &Path) {
- file_status Status;
- if (std::error_code EC = status(Path, Status))
- return EC;
-
- return Status.permissions();
-}
-
-} // end namespace fs
-} // end namespace sys
-} // end namespace llvm
-
-// Include the truly platform-specific parts.
-#if defined(LLVM_ON_UNIX)
-#include "Unix/Path.inc"
-#endif
-#if defined(_WIN32)
-#include "Windows/Path.inc"
-#endif
-
-namespace llvm {
-namespace sys {
-namespace fs {
-TempFile::TempFile(StringRef Name, int FD) : TmpName(Name), FD(FD) {}
-TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); }
-TempFile &TempFile::operator=(TempFile &&Other) {
- TmpName = std::move(Other.TmpName);
- FD = Other.FD;
- Other.Done = true;
- return *this;
-}
-
-TempFile::~TempFile() { assert(Done); }
-
-Error TempFile::discard() {
- Done = true;
- std::error_code RemoveEC;
-// On windows closing will remove the file.
-#ifndef _WIN32
- // Always try to close and remove.
- if (!TmpName.empty()) {
- RemoveEC = fs::remove(TmpName);
- sys::DontRemoveFileOnSignal(TmpName);
- }
-#endif
-
- if (!RemoveEC)
- TmpName = "";
-
- if (FD != -1 && close(FD) == -1) {
- std::error_code EC = std::error_code(errno, std::generic_category());
- return errorCodeToError(EC);
- }
- FD = -1;
-
- return errorCodeToError(RemoveEC);
-}
-
-Error TempFile::keep(const Twine &Name) {
- assert(!Done);
- Done = true;
- // Always try to close and rename.
-#ifdef _WIN32
- // If we can't cancel the delete don't rename.
- auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
- std::error_code RenameEC = setDeleteDisposition(H, false);
- if (!RenameEC) {
- RenameEC = rename_fd(FD, Name);
- // If rename failed because it's cross-device, copy instead
- if (RenameEC ==
- std::error_code(ERROR_NOT_SAME_DEVICE, std::system_category())) {
- RenameEC = copy_file(TmpName, Name);
- setDeleteDisposition(H, true);
- }
- }
-
- // If we can't rename, discard the temporary file.
- if (RenameEC)
- setDeleteDisposition(H, true);
-#else
- std::error_code RenameEC = fs::rename(TmpName, Name);
- if (RenameEC) {
- // If we can't rename, try to copy to work around cross-device link issues.
- RenameEC = sys::fs::copy_file(TmpName, Name);
- // If we can't rename or copy, discard the temporary file.
- if (RenameEC)
- remove(TmpName);
- }
- sys::DontRemoveFileOnSignal(TmpName);
-#endif
-
- if (!RenameEC)
- TmpName = "";
-
- if (close(FD) == -1) {
- std::error_code EC(errno, std::generic_category());
- return errorCodeToError(EC);
- }
- FD = -1;
-
- return errorCodeToError(RenameEC);
-}
-
-Error TempFile::keep() {
- assert(!Done);
- Done = true;
-
-#ifdef _WIN32
- auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
- if (std::error_code EC = setDeleteDisposition(H, false))
- return errorCodeToError(EC);
-#else
- sys::DontRemoveFileOnSignal(TmpName);
-#endif
-
- TmpName = "";
-
- if (close(FD) == -1) {
- std::error_code EC(errno, std::generic_category());
- return errorCodeToError(EC);
- }
- FD = -1;
-
- return Error::success();
-}
-
-Expected<TempFile> TempFile::create(const Twine &Model, unsigned Mode) {
- int FD;
- SmallString<128> ResultPath;
- if (std::error_code EC =
- createUniqueFile(Model, FD, ResultPath, Mode, OF_Delete))
- return errorCodeToError(EC);
-
- TempFile Ret(ResultPath, FD);
-#ifndef _WIN32
- if (sys::RemoveFileOnSignal(ResultPath)) {
- // Make sure we delete the file when RemoveFileOnSignal fails.
- consumeError(Ret.discard());
- std::error_code EC(errc::operation_not_permitted);
- return errorCodeToError(EC);
- }
-#endif
- return std::move(Ret);
-}
-}
-
-} // end namsspace sys
-} // end namespace llvm
diff --git a/gnu/llvm/lib/Support/PluginLoader.cpp b/gnu/llvm/lib/Support/PluginLoader.cpp
deleted file mode 100644
index 358137f08f5..00000000000
--- a/gnu/llvm/lib/Support/PluginLoader.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-//===-- PluginLoader.cpp - Implement -load command line option ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the -load <plugin> command line option handler.
-//
-//===----------------------------------------------------------------------===//
-
-#define DONT_GET_PLUGIN_LOADER_OPTION
-#include "llvm/Support/PluginLoader.h"
-#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/raw_ostream.h"
-#include <vector>
-using namespace llvm;
-
-static ManagedStatic<std::vector<std::string> > Plugins;
-static ManagedStatic<sys::SmartMutex<true> > PluginsLock;
-
-void PluginLoader::operator=(const std::string &Filename) {
- sys::SmartScopedLock<true> Lock(*PluginsLock);
- std::string Error;
- if (sys::DynamicLibrary::LoadLibraryPermanently(Filename.c_str(), &Error)) {
- errs() << "Error opening '" << Filename << "': " << Error
- << "\n -load request ignored.\n";
- } else {
- Plugins->push_back(Filename);
- }
-}
-
-unsigned PluginLoader::getNumPlugins() {
- sys::SmartScopedLock<true> Lock(*PluginsLock);
- return Plugins.isConstructed() ? Plugins->size() : 0;
-}
-
-std::string &PluginLoader::getPlugin(unsigned num) {
- sys::SmartScopedLock<true> Lock(*PluginsLock);
- assert(Plugins.isConstructed() && num < Plugins->size() &&
- "Asking for an out of bounds plugin");
- return (*Plugins)[num];
-}
diff --git a/gnu/llvm/lib/Support/PrettyStackTrace.cpp b/gnu/llvm/lib/Support/PrettyStackTrace.cpp
deleted file mode 100644
index 206de91ae23..00000000000
--- a/gnu/llvm/lib/Support/PrettyStackTrace.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-//===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines some helpful functions for dealing with the possibility of
-// Unix signals occurring while your program is running.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm-c/ErrorHandling.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Config/config.h" // Get autoconf configuration settings
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/Watchdog.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <cstdarg>
-#include <cstdio>
-#include <tuple>
-
-#ifdef HAVE_CRASHREPORTERCLIENT_H
-#include <CrashReporterClient.h>
-#endif
-
-using namespace llvm;
-
-// If backtrace support is not enabled, compile out support for pretty stack
-// traces. This has the secondary effect of not requiring thread local storage
-// when backtrace support is disabled.
-#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
-
-// We need a thread local pointer to manage the stack of our stack trace
-// objects, but we *really* cannot tolerate destructors running and do not want
-// to pay any overhead of synchronizing. As a consequence, we use a raw
-// thread-local variable.
-static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr;
-
-namespace llvm {
-PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) {
- PrettyStackTraceEntry *Prev = nullptr;
- while (Head)
- std::tie(Prev, Head, Head->NextEntry) =
- std::make_tuple(Head, Head->NextEntry, Prev);
- return Prev;
-}
-}
-
-static void PrintStack(raw_ostream &OS) {
- // Print out the stack in reverse order. To avoid recursion (which is likely
- // to fail if we crashed due to stack overflow), we do an up-front pass to
- // reverse the stack, then print it, then reverse it again.
- unsigned ID = 0;
- PrettyStackTraceEntry *ReversedStack =
- llvm::ReverseStackTrace(PrettyStackTraceHead);
- for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry;
- Entry = Entry->getNextEntry()) {
- OS << ID++ << ".\t";
- sys::Watchdog W(5);
- Entry->print(OS);
- }
- llvm::ReverseStackTrace(ReversedStack);
-}
-
-/// PrintCurStackTrace - Print the current stack trace to the specified stream.
-static void PrintCurStackTrace(raw_ostream &OS) {
- // Don't print an empty trace.
- if (!PrettyStackTraceHead) return;
-
- // If there are pretty stack frames registered, walk and emit them.
- OS << "Stack dump:\n";
-
- PrintStack(OS);
- OS.flush();
-}
-
-// Integrate with crash reporter libraries.
-#if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H)
-// If any clients of llvm try to link to libCrashReporterClient.a themselves,
-// only one crash info struct will be used.
-extern "C" {
-CRASH_REPORTER_CLIENT_HIDDEN
-struct crashreporter_annotations_t gCRAnnotations
- __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION)))
-#if CRASHREPORTER_ANNOTATIONS_VERSION < 5
- = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
-#else
- = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0, 0 };
-#endif
-}
-#elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO
-extern "C" const char *__crashreporter_info__
- __attribute__((visibility("hidden"))) = 0;
-asm(".desc ___crashreporter_info__, 0x10");
-#endif
-
-/// CrashHandler - This callback is run if a fatal signal is delivered to the
-/// process, it prints the pretty stack trace.
-static void CrashHandler(void *) {
-#ifndef __APPLE__
- // On non-apple systems, just emit the crash stack trace to stderr.
- PrintCurStackTrace(errs());
-#else
- // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
- // put it into __crashreporter_info__.
- SmallString<2048> TmpStr;
- {
- raw_svector_ostream Stream(TmpStr);
- PrintCurStackTrace(Stream);
- }
-
- if (!TmpStr.empty()) {
-#ifdef HAVE_CRASHREPORTERCLIENT_H
- // Cast to void to avoid warning.
- (void)CRSetCrashLogMessage(TmpStr.c_str());
-#elif HAVE_CRASHREPORTER_INFO
- __crashreporter_info__ = strdup(TmpStr.c_str());
-#endif
- errs() << TmpStr.str();
- }
-
-#endif
-}
-
-// defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
-#endif
-
-PrettyStackTraceEntry::PrettyStackTraceEntry() {
-#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
- // Link ourselves.
- NextEntry = PrettyStackTraceHead;
- PrettyStackTraceHead = this;
-#endif
-}
-
-PrettyStackTraceEntry::~PrettyStackTraceEntry() {
-#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
- assert(PrettyStackTraceHead == this &&
- "Pretty stack trace entry destruction is out of order");
- PrettyStackTraceHead = NextEntry;
-#endif
-}
-
-void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; }
-
-PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) {
- va_list AP;
- va_start(AP, Format);
- const int SizeOrError = vsnprintf(nullptr, 0, Format, AP);
- va_end(AP);
- if (SizeOrError < 0) {
- return;
- }
-
- const int Size = SizeOrError + 1; // '\0'
- Str.resize(Size);
- va_start(AP, Format);
- vsnprintf(Str.data(), Size, Format, AP);
- va_end(AP);
-}
-
-void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; }
-
-void PrettyStackTraceProgram::print(raw_ostream &OS) const {
- OS << "Program arguments: ";
- // Print the argument list.
- for (unsigned i = 0, e = ArgC; i != e; ++i)
- OS << ArgV[i] << ' ';
- OS << '\n';
-}
-
-#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
-static bool RegisterCrashPrinter() {
- sys::AddSignalHandler(CrashHandler, nullptr);
- return false;
-}
-#endif
-
-void llvm::EnablePrettyStackTrace() {
-#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
- // The first time this is called, we register the crash printer.
- static bool HandlerRegistered = RegisterCrashPrinter();
- (void)HandlerRegistered;
-#endif
-}
-
-const void *llvm::SavePrettyStackState() {
-#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
- return PrettyStackTraceHead;
-#else
- return nullptr;
-#endif
-}
-
-void llvm::RestorePrettyStackState(const void *Top) {
-#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
- PrettyStackTraceHead =
- static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top));
-#endif
-}
-
-void LLVMEnablePrettyStackTrace() {
- EnablePrettyStackTrace();
-}
diff --git a/gnu/llvm/lib/Support/Process.cpp b/gnu/llvm/lib/Support/Process.cpp
deleted file mode 100644
index f32355aefbb..00000000000
--- a/gnu/llvm/lib/Support/Process.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-//===-- Process.cpp - Implement OS Process Concept --------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the operating system Process concept.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Process.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Program.h"
-
-using namespace llvm;
-using namespace sys;
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
-
-Optional<std::string> Process::FindInEnvPath(StringRef EnvName,
- StringRef FileName) {
- return FindInEnvPath(EnvName, FileName, {});
-}
-
-Optional<std::string> Process::FindInEnvPath(StringRef EnvName,
- StringRef FileName,
- ArrayRef<std::string> IgnoreList) {
- assert(!path::is_absolute(FileName));
- Optional<std::string> FoundPath;
- Optional<std::string> OptPath = Process::GetEnv(EnvName);
- if (!OptPath.hasValue())
- return FoundPath;
-
- const char EnvPathSeparatorStr[] = {EnvPathSeparator, '\0'};
- SmallVector<StringRef, 8> Dirs;
- SplitString(OptPath.getValue(), Dirs, EnvPathSeparatorStr);
-
- for (StringRef Dir : Dirs) {
- if (Dir.empty())
- continue;
-
- if (any_of(IgnoreList, [&](StringRef S) { return fs::equivalent(S, Dir); }))
- continue;
-
- SmallString<128> FilePath(Dir);
- path::append(FilePath, FileName);
- if (fs::exists(Twine(FilePath))) {
- FoundPath = FilePath.str();
- break;
- }
- }
-
- return FoundPath;
-}
-
-
-#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
-
-#define ALLCOLORS(FGBG,BOLD) {\
- COLOR(FGBG, "0", BOLD),\
- COLOR(FGBG, "1", BOLD),\
- COLOR(FGBG, "2", BOLD),\
- COLOR(FGBG, "3", BOLD),\
- COLOR(FGBG, "4", BOLD),\
- COLOR(FGBG, "5", BOLD),\
- COLOR(FGBG, "6", BOLD),\
- COLOR(FGBG, "7", BOLD)\
- }
-
-static const char colorcodes[2][2][8][10] = {
- { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
- { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
-};
-
-// A CMake option controls wheter we emit core dumps by default. An application
-// may disable core dumps by calling Process::PreventCoreFiles().
-static bool coreFilesPrevented = !LLVM_ENABLE_CRASH_DUMPS;
-
-bool Process::AreCoreFilesPrevented() { return coreFilesPrevented; }
-
-// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
-#include "Unix/Process.inc"
-#endif
-#ifdef _WIN32
-#include "Windows/Process.inc"
-#endif
diff --git a/gnu/llvm/lib/Support/Program.cpp b/gnu/llvm/lib/Support/Program.cpp
deleted file mode 100644
index 63cdcdaabee..00000000000
--- a/gnu/llvm/lib/Support/Program.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-//===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the operating system Program concept.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Program.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Config/llvm-config.h"
-#include <system_error>
-using namespace llvm;
-using namespace sys;
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
-
-static bool Execute(ProcessInfo &PI, StringRef Program,
- ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
- ArrayRef<Optional<StringRef>> Redirects,
- unsigned MemoryLimit, std::string *ErrMsg);
-
-int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args,
- Optional<ArrayRef<StringRef>> Env,
- ArrayRef<Optional<StringRef>> Redirects,
- unsigned SecondsToWait, unsigned MemoryLimit,
- std::string *ErrMsg, bool *ExecutionFailed) {
- assert(Redirects.empty() || Redirects.size() == 3);
- ProcessInfo PI;
- if (Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg)) {
- if (ExecutionFailed)
- *ExecutionFailed = false;
- ProcessInfo Result = Wait(
- PI, SecondsToWait, /*WaitUntilTerminates=*/SecondsToWait == 0, ErrMsg);
- return Result.ReturnCode;
- }
-
- if (ExecutionFailed)
- *ExecutionFailed = true;
-
- return -1;
-}
-
-ProcessInfo sys::ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args,
- Optional<ArrayRef<StringRef>> Env,
- ArrayRef<Optional<StringRef>> Redirects,
- unsigned MemoryLimit, std::string *ErrMsg,
- bool *ExecutionFailed) {
- assert(Redirects.empty() || Redirects.size() == 3);
- ProcessInfo PI;
- if (ExecutionFailed)
- *ExecutionFailed = false;
- if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg))
- if (ExecutionFailed)
- *ExecutionFailed = true;
-
- return PI;
-}
-
-bool sys::commandLineFitsWithinSystemLimits(StringRef Program,
- ArrayRef<const char *> Args) {
- SmallVector<StringRef, 8> StringRefArgs;
- StringRefArgs.reserve(Args.size());
- for (const char *A : Args)
- StringRefArgs.emplace_back(A);
- return commandLineFitsWithinSystemLimits(Program, StringRefArgs);
-}
-
-// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
-#include "Unix/Program.inc"
-#endif
-#ifdef _WIN32
-#include "Windows/Program.inc"
-#endif
diff --git a/gnu/llvm/lib/Support/README.txt.system b/gnu/llvm/lib/Support/README.txt.system
deleted file mode 100644
index 7a906b8dba4..00000000000
--- a/gnu/llvm/lib/Support/README.txt.system
+++ /dev/null
@@ -1,43 +0,0 @@
-Design Of lib/System
-====================
-
-The software in this directory is designed to completely shield LLVM from any
-and all operating system specific functionality. It is not intended to be a
-complete operating system wrapper (such as ACE), but only to provide the
-functionality necessary to support LLVM.
-
-The software located here, of necessity, has very specific and stringent design
-rules. Violation of these rules means that cracks in the shield could form and
-the primary goal of the library is defeated. By consistently using this library,
-LLVM becomes more easily ported to new platforms since the only thing requiring
-porting is this library.
-
-Complete documentation for the library can be found in the file:
- llvm/docs/SystemLibrary.html
-or at this URL:
- http://llvm.org/docs/SystemLibrary.html
-
-While we recommend that you read the more detailed documentation, for the
-impatient, here's a high level summary of the library's requirements.
-
- 1. No system header files are to be exposed through the interface.
- 2. Std C++ and Std C header files are okay to be exposed through the interface.
- 3. No exposed system-specific functions.
- 4. No exposed system-specific data.
- 5. Data in lib/System classes must use only simple C++ intrinsic types.
- 6. Errors are handled by returning "true" and setting an optional std::string
- 7. Library must not throw any exceptions, period.
- 8. Interface functions must not have throw() specifications.
- 9. No duplicate function impementations are permitted within an operating
- system class.
-
-To accomplish these requirements, the library has numerous design criteria that
-must be satisfied. Here's a high level summary of the library's design criteria:
-
- 1. No unused functionality (only what LLVM needs)
- 2. High-Level Interfaces
- 3. Use Opaque Classes
- 4. Common Implementations
- 5. Multiple Implementations
- 6. Minimize Memory Allocation
- 7. No Virtual Methods
diff --git a/gnu/llvm/lib/Support/RWMutex.cpp b/gnu/llvm/lib/Support/RWMutex.cpp
deleted file mode 100644
index 8b6d74e49f3..00000000000
--- a/gnu/llvm/lib/Support/RWMutex.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-//===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the llvm::sys::RWMutex class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/RWMutex.h"
-#include "llvm/Config/config.h"
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
-
-#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
-// Define all methods as no-ops if threading is explicitly disabled
-
-using namespace llvm;
-using namespace sys;
-
-RWMutexImpl::RWMutexImpl() = default;
-RWMutexImpl::~RWMutexImpl() = default;
-
-bool RWMutexImpl::reader_acquire() { return true; }
-bool RWMutexImpl::reader_release() { return true; }
-bool RWMutexImpl::writer_acquire() { return true; }
-bool RWMutexImpl::writer_release() { return true; }
-
-#else
-
-#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
-
-#include <cassert>
-#include <cstdlib>
-#include <pthread.h>
-
-using namespace llvm;
-using namespace sys;
-
-// Construct a RWMutex using pthread calls
-RWMutexImpl::RWMutexImpl()
-{
- // Declare the pthread_rwlock data structures
- pthread_rwlock_t* rwlock =
- static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t)));
-
-#ifdef __APPLE__
- // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
- bzero(rwlock, sizeof(pthread_rwlock_t));
-#endif
-
- // Initialize the rwlock
- int errorcode = pthread_rwlock_init(rwlock, nullptr);
- (void)errorcode;
- assert(errorcode == 0);
-
- // Assign the data member
- data_ = rwlock;
-}
-
-// Destruct a RWMutex
-RWMutexImpl::~RWMutexImpl()
-{
- pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
- assert(rwlock != nullptr);
- pthread_rwlock_destroy(rwlock);
- free(rwlock);
-}
-
-bool
-RWMutexImpl::reader_acquire()
-{
- pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
- assert(rwlock != nullptr);
-
- int errorcode = pthread_rwlock_rdlock(rwlock);
- return errorcode == 0;
-}
-
-bool
-RWMutexImpl::reader_release()
-{
- pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
- assert(rwlock != nullptr);
-
- int errorcode = pthread_rwlock_unlock(rwlock);
- return errorcode == 0;
-}
-
-bool
-RWMutexImpl::writer_acquire()
-{
- pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
- assert(rwlock != nullptr);
-
- int errorcode = pthread_rwlock_wrlock(rwlock);
- return errorcode == 0;
-}
-
-bool
-RWMutexImpl::writer_release()
-{
- pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
- assert(rwlock != nullptr);
-
- int errorcode = pthread_rwlock_unlock(rwlock);
- return errorcode == 0;
-}
-
-#elif defined(LLVM_ON_UNIX)
-#include "Unix/RWMutex.inc"
-#elif defined( _WIN32)
-#include "Windows/RWMutex.inc"
-#else
-#warning Neither LLVM_ON_UNIX nor _WIN32 was set in Support/Mutex.cpp
-#endif
-#endif
diff --git a/gnu/llvm/lib/Support/RandomNumberGenerator.cpp b/gnu/llvm/lib/Support/RandomNumberGenerator.cpp
deleted file mode 100644
index df0d87fab02..00000000000
--- a/gnu/llvm/lib/Support/RandomNumberGenerator.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-//===-- RandomNumberGenerator.cpp - Implement RNG class -------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements deterministic random number generation (RNG).
-// The current implementation is NOT cryptographically secure as it uses
-// the C++11 <random> facilities.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/RandomNumberGenerator.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-#ifdef _WIN32
-#include "Windows/WindowsSupport.h"
-#else
-#include "Unix/Unix.h"
-#endif
-
-using namespace llvm;
-
-#define DEBUG_TYPE "rng"
-
-// Tracking BUG: 19665
-// http://llvm.org/bugs/show_bug.cgi?id=19665
-//
-// Do not change to cl::opt<uint64_t> since this silently breaks argument parsing.
-static cl::opt<unsigned long long>
- Seed("rng-seed", cl::value_desc("seed"), cl::Hidden,
- cl::desc("Seed for the random number generator"), cl::init(0));
-
-RandomNumberGenerator::RandomNumberGenerator(StringRef Salt) {
- LLVM_DEBUG(if (Seed == 0) dbgs()
- << "Warning! Using unseeded random number generator.\n");
-
- // Combine seed and salts using std::seed_seq.
- // Data: Seed-low, Seed-high, Salt
- // Note: std::seed_seq can only store 32-bit values, even though we
- // are using a 64-bit RNG. This isn't a problem since the Mersenne
- // twister constructor copies these correctly into its initial state.
- std::vector<uint32_t> Data;
- Data.resize(2 + Salt.size());
- Data[0] = Seed;
- Data[1] = Seed >> 32;
-
- llvm::copy(Salt, Data.begin() + 2);
-
- std::seed_seq SeedSeq(Data.begin(), Data.end());
- Generator.seed(SeedSeq);
-}
-
-RandomNumberGenerator::result_type RandomNumberGenerator::operator()() {
- return Generator();
-}
-
-// Get random vector of specified size
-std::error_code llvm::getRandomBytes(void *Buffer, size_t Size) {
-#ifdef _WIN32
- HCRYPTPROV hProvider;
- if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
- ScopedCryptContext ScopedHandle(hProvider);
- if (CryptGenRandom(hProvider, Size, static_cast<BYTE *>(Buffer)))
- return std::error_code();
- }
- return std::error_code(GetLastError(), std::system_category());
-#else
- int Fd = open("/dev/urandom", O_RDONLY);
- if (Fd != -1) {
- std::error_code Ret;
- ssize_t BytesRead = read(Fd, Buffer, Size);
- if (BytesRead == -1)
- Ret = std::error_code(errno, std::system_category());
- else if (BytesRead != static_cast<ssize_t>(Size))
- Ret = std::error_code(EIO, std::system_category());
- if (close(Fd) == -1)
- Ret = std::error_code(errno, std::system_category());
-
- return Ret;
- }
- return std::error_code(errno, std::system_category());
-#endif
-}
diff --git a/gnu/llvm/lib/Support/Regex.cpp b/gnu/llvm/lib/Support/Regex.cpp
deleted file mode 100644
index 48caab13152..00000000000
--- a/gnu/llvm/lib/Support/Regex.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-//===-- Regex.cpp - Regular Expression matcher implementation -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a POSIX regular expression matcher.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Regex.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include <string>
-
-// Important this comes last because it defines "_REGEX_H_". At least on
-// Darwin, if included before any header that (transitively) includes
-// xlocale.h, this will cause trouble, because of missing regex-related types.
-#include "regex_impl.h"
-
-using namespace llvm;
-
-Regex::Regex() : preg(nullptr), error(REG_BADPAT) {}
-
-Regex::Regex(StringRef regex, unsigned Flags) {
- unsigned flags = 0;
- preg = new llvm_regex();
- preg->re_endp = regex.end();
- if (Flags & IgnoreCase)
- flags |= REG_ICASE;
- if (Flags & Newline)
- flags |= REG_NEWLINE;
- if (!(Flags & BasicRegex))
- flags |= REG_EXTENDED;
- error = llvm_regcomp(preg, regex.data(), flags|REG_PEND);
-}
-
-Regex::Regex(Regex &&regex) {
- preg = regex.preg;
- error = regex.error;
- regex.preg = nullptr;
- regex.error = REG_BADPAT;
-}
-
-Regex::~Regex() {
- if (preg) {
- llvm_regfree(preg);
- delete preg;
- }
-}
-
-bool Regex::isValid(std::string &Error) const {
- if (!error)
- return true;
-
- size_t len = llvm_regerror(error, preg, nullptr, 0);
-
- Error.resize(len - 1);
- llvm_regerror(error, preg, &Error[0], len);
- return false;
-}
-
-/// getNumMatches - In a valid regex, return the number of parenthesized
-/// matches it contains.
-unsigned Regex::getNumMatches() const {
- return preg->re_nsub;
-}
-
-bool Regex::match(StringRef String, SmallVectorImpl<StringRef> *Matches){
- if (error)
- return false;
-
- unsigned nmatch = Matches ? preg->re_nsub+1 : 0;
-
- // pmatch needs to have at least one element.
- SmallVector<llvm_regmatch_t, 8> pm;
- pm.resize(nmatch > 0 ? nmatch : 1);
- pm[0].rm_so = 0;
- pm[0].rm_eo = String.size();
-
- int rc = llvm_regexec(preg, String.data(), nmatch, pm.data(), REG_STARTEND);
-
- if (rc == REG_NOMATCH)
- return false;
- if (rc != 0) {
- // regexec can fail due to invalid pattern or running out of memory.
- error = rc;
- return false;
- }
-
- // There was a match.
-
- if (Matches) { // match position requested
- Matches->clear();
-
- for (unsigned i = 0; i != nmatch; ++i) {
- if (pm[i].rm_so == -1) {
- // this group didn't match
- Matches->push_back(StringRef());
- continue;
- }
- assert(pm[i].rm_eo >= pm[i].rm_so);
- Matches->push_back(StringRef(String.data()+pm[i].rm_so,
- pm[i].rm_eo-pm[i].rm_so));
- }
- }
-
- return true;
-}
-
-std::string Regex::sub(StringRef Repl, StringRef String,
- std::string *Error) {
- SmallVector<StringRef, 8> Matches;
-
- // Reset error, if given.
- if (Error && !Error->empty()) *Error = "";
-
- // Return the input if there was no match.
- if (!match(String, &Matches))
- return String;
-
- // Otherwise splice in the replacement string, starting with the prefix before
- // the match.
- std::string Res(String.begin(), Matches[0].begin());
-
- // Then the replacement string, honoring possible substitutions.
- while (!Repl.empty()) {
- // Skip to the next escape.
- std::pair<StringRef, StringRef> Split = Repl.split('\\');
-
- // Add the skipped substring.
- Res += Split.first;
-
- // Check for terminimation and trailing backslash.
- if (Split.second.empty()) {
- if (Repl.size() != Split.first.size() &&
- Error && Error->empty())
- *Error = "replacement string contained trailing backslash";
- break;
- }
-
- // Otherwise update the replacement string and interpret escapes.
- Repl = Split.second;
-
- // FIXME: We should have a StringExtras function for mapping C99 escapes.
- switch (Repl[0]) {
- // Treat all unrecognized characters as self-quoting.
- default:
- Res += Repl[0];
- Repl = Repl.substr(1);
- break;
-
- // Single character escapes.
- case 't':
- Res += '\t';
- Repl = Repl.substr(1);
- break;
- case 'n':
- Res += '\n';
- Repl = Repl.substr(1);
- break;
-
- // Decimal escapes are backreferences.
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9': {
- // Extract the backreference number.
- StringRef Ref = Repl.slice(0, Repl.find_first_not_of("0123456789"));
- Repl = Repl.substr(Ref.size());
-
- unsigned RefValue;
- if (!Ref.getAsInteger(10, RefValue) &&
- RefValue < Matches.size())
- Res += Matches[RefValue];
- else if (Error && Error->empty())
- *Error = ("invalid backreference string '" + Twine(Ref) + "'").str();
- break;
- }
- }
- }
-
- // And finally the suffix.
- Res += StringRef(Matches[0].end(), String.end() - Matches[0].end());
-
- return Res;
-}
-
-// These are the special characters matched in functions like "p_ere_exp".
-static const char RegexMetachars[] = "()^$|*+?.[]\\{}";
-
-bool Regex::isLiteralERE(StringRef Str) {
- // Check for regex metacharacters. This list was derived from our regex
- // implementation in regcomp.c and double checked against the POSIX extended
- // regular expression specification.
- return Str.find_first_of(RegexMetachars) == StringRef::npos;
-}
-
-std::string Regex::escape(StringRef String) {
- std::string RegexStr;
- for (unsigned i = 0, e = String.size(); i != e; ++i) {
- if (strchr(RegexMetachars, String[i]))
- RegexStr += '\\';
- RegexStr += String[i];
- }
-
- return RegexStr;
-}
diff --git a/gnu/llvm/lib/Support/SHA1.cpp b/gnu/llvm/lib/Support/SHA1.cpp
deleted file mode 100644
index 3007a78d5e2..00000000000
--- a/gnu/llvm/lib/Support/SHA1.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-//====- SHA1.cpp - Private copy of the SHA1 implementation ---*- C++ -* ======//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This code is taken from public domain
-// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c and
-// http://cvsweb.netbsd.org/bsdweb.cgi/src/common/lib/libc/hash/sha1/sha1.c?rev=1.6)
-// and modified by wrapping it in a C++ interface for LLVM,
-// and removing unnecessary code.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/SHA1.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/Host.h"
-using namespace llvm;
-
-#include <stdint.h>
-#include <string.h>
-
-#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
-#define SHA_BIG_ENDIAN
-#endif
-
-static uint32_t rol(uint32_t Number, int Bits) {
- return (Number << Bits) | (Number >> (32 - Bits));
-}
-
-static uint32_t blk0(uint32_t *Buf, int I) { return Buf[I]; }
-
-static uint32_t blk(uint32_t *Buf, int I) {
- Buf[I & 15] = rol(Buf[(I + 13) & 15] ^ Buf[(I + 8) & 15] ^ Buf[(I + 2) & 15] ^
- Buf[I & 15],
- 1);
- return Buf[I & 15];
-}
-
-static void r0(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E,
- int I, uint32_t *Buf) {
- E += ((B & (C ^ D)) ^ D) + blk0(Buf, I) + 0x5A827999 + rol(A, 5);
- B = rol(B, 30);
-}
-
-static void r1(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E,
- int I, uint32_t *Buf) {
- E += ((B & (C ^ D)) ^ D) + blk(Buf, I) + 0x5A827999 + rol(A, 5);
- B = rol(B, 30);
-}
-
-static void r2(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E,
- int I, uint32_t *Buf) {
- E += (B ^ C ^ D) + blk(Buf, I) + 0x6ED9EBA1 + rol(A, 5);
- B = rol(B, 30);
-}
-
-static void r3(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E,
- int I, uint32_t *Buf) {
- E += (((B | C) & D) | (B & C)) + blk(Buf, I) + 0x8F1BBCDC + rol(A, 5);
- B = rol(B, 30);
-}
-
-static void r4(uint32_t &A, uint32_t &B, uint32_t &C, uint32_t &D, uint32_t &E,
- int I, uint32_t *Buf) {
- E += (B ^ C ^ D) + blk(Buf, I) + 0xCA62C1D6 + rol(A, 5);
- B = rol(B, 30);
-}
-
-/* code */
-#define SHA1_K0 0x5a827999
-#define SHA1_K20 0x6ed9eba1
-#define SHA1_K40 0x8f1bbcdc
-#define SHA1_K60 0xca62c1d6
-
-#define SEED_0 0x67452301
-#define SEED_1 0xefcdab89
-#define SEED_2 0x98badcfe
-#define SEED_3 0x10325476
-#define SEED_4 0xc3d2e1f0
-
-void SHA1::init() {
- InternalState.State[0] = SEED_0;
- InternalState.State[1] = SEED_1;
- InternalState.State[2] = SEED_2;
- InternalState.State[3] = SEED_3;
- InternalState.State[4] = SEED_4;
- InternalState.ByteCount = 0;
- InternalState.BufferOffset = 0;
-}
-
-void SHA1::hashBlock() {
- uint32_t A = InternalState.State[0];
- uint32_t B = InternalState.State[1];
- uint32_t C = InternalState.State[2];
- uint32_t D = InternalState.State[3];
- uint32_t E = InternalState.State[4];
-
- // 4 rounds of 20 operations each. Loop unrolled.
- r0(A, B, C, D, E, 0, InternalState.Buffer.L);
- r0(E, A, B, C, D, 1, InternalState.Buffer.L);
- r0(D, E, A, B, C, 2, InternalState.Buffer.L);
- r0(C, D, E, A, B, 3, InternalState.Buffer.L);
- r0(B, C, D, E, A, 4, InternalState.Buffer.L);
- r0(A, B, C, D, E, 5, InternalState.Buffer.L);
- r0(E, A, B, C, D, 6, InternalState.Buffer.L);
- r0(D, E, A, B, C, 7, InternalState.Buffer.L);
- r0(C, D, E, A, B, 8, InternalState.Buffer.L);
- r0(B, C, D, E, A, 9, InternalState.Buffer.L);
- r0(A, B, C, D, E, 10, InternalState.Buffer.L);
- r0(E, A, B, C, D, 11, InternalState.Buffer.L);
- r0(D, E, A, B, C, 12, InternalState.Buffer.L);
- r0(C, D, E, A, B, 13, InternalState.Buffer.L);
- r0(B, C, D, E, A, 14, InternalState.Buffer.L);
- r0(A, B, C, D, E, 15, InternalState.Buffer.L);
- r1(E, A, B, C, D, 16, InternalState.Buffer.L);
- r1(D, E, A, B, C, 17, InternalState.Buffer.L);
- r1(C, D, E, A, B, 18, InternalState.Buffer.L);
- r1(B, C, D, E, A, 19, InternalState.Buffer.L);
-
- r2(A, B, C, D, E, 20, InternalState.Buffer.L);
- r2(E, A, B, C, D, 21, InternalState.Buffer.L);
- r2(D, E, A, B, C, 22, InternalState.Buffer.L);
- r2(C, D, E, A, B, 23, InternalState.Buffer.L);
- r2(B, C, D, E, A, 24, InternalState.Buffer.L);
- r2(A, B, C, D, E, 25, InternalState.Buffer.L);
- r2(E, A, B, C, D, 26, InternalState.Buffer.L);
- r2(D, E, A, B, C, 27, InternalState.Buffer.L);
- r2(C, D, E, A, B, 28, InternalState.Buffer.L);
- r2(B, C, D, E, A, 29, InternalState.Buffer.L);
- r2(A, B, C, D, E, 30, InternalState.Buffer.L);
- r2(E, A, B, C, D, 31, InternalState.Buffer.L);
- r2(D, E, A, B, C, 32, InternalState.Buffer.L);
- r2(C, D, E, A, B, 33, InternalState.Buffer.L);
- r2(B, C, D, E, A, 34, InternalState.Buffer.L);
- r2(A, B, C, D, E, 35, InternalState.Buffer.L);
- r2(E, A, B, C, D, 36, InternalState.Buffer.L);
- r2(D, E, A, B, C, 37, InternalState.Buffer.L);
- r2(C, D, E, A, B, 38, InternalState.Buffer.L);
- r2(B, C, D, E, A, 39, InternalState.Buffer.L);
-
- r3(A, B, C, D, E, 40, InternalState.Buffer.L);
- r3(E, A, B, C, D, 41, InternalState.Buffer.L);
- r3(D, E, A, B, C, 42, InternalState.Buffer.L);
- r3(C, D, E, A, B, 43, InternalState.Buffer.L);
- r3(B, C, D, E, A, 44, InternalState.Buffer.L);
- r3(A, B, C, D, E, 45, InternalState.Buffer.L);
- r3(E, A, B, C, D, 46, InternalState.Buffer.L);
- r3(D, E, A, B, C, 47, InternalState.Buffer.L);
- r3(C, D, E, A, B, 48, InternalState.Buffer.L);
- r3(B, C, D, E, A, 49, InternalState.Buffer.L);
- r3(A, B, C, D, E, 50, InternalState.Buffer.L);
- r3(E, A, B, C, D, 51, InternalState.Buffer.L);
- r3(D, E, A, B, C, 52, InternalState.Buffer.L);
- r3(C, D, E, A, B, 53, InternalState.Buffer.L);
- r3(B, C, D, E, A, 54, InternalState.Buffer.L);
- r3(A, B, C, D, E, 55, InternalState.Buffer.L);
- r3(E, A, B, C, D, 56, InternalState.Buffer.L);
- r3(D, E, A, B, C, 57, InternalState.Buffer.L);
- r3(C, D, E, A, B, 58, InternalState.Buffer.L);
- r3(B, C, D, E, A, 59, InternalState.Buffer.L);
-
- r4(A, B, C, D, E, 60, InternalState.Buffer.L);
- r4(E, A, B, C, D, 61, InternalState.Buffer.L);
- r4(D, E, A, B, C, 62, InternalState.Buffer.L);
- r4(C, D, E, A, B, 63, InternalState.Buffer.L);
- r4(B, C, D, E, A, 64, InternalState.Buffer.L);
- r4(A, B, C, D, E, 65, InternalState.Buffer.L);
- r4(E, A, B, C, D, 66, InternalState.Buffer.L);
- r4(D, E, A, B, C, 67, InternalState.Buffer.L);
- r4(C, D, E, A, B, 68, InternalState.Buffer.L);
- r4(B, C, D, E, A, 69, InternalState.Buffer.L);
- r4(A, B, C, D, E, 70, InternalState.Buffer.L);
- r4(E, A, B, C, D, 71, InternalState.Buffer.L);
- r4(D, E, A, B, C, 72, InternalState.Buffer.L);
- r4(C, D, E, A, B, 73, InternalState.Buffer.L);
- r4(B, C, D, E, A, 74, InternalState.Buffer.L);
- r4(A, B, C, D, E, 75, InternalState.Buffer.L);
- r4(E, A, B, C, D, 76, InternalState.Buffer.L);
- r4(D, E, A, B, C, 77, InternalState.Buffer.L);
- r4(C, D, E, A, B, 78, InternalState.Buffer.L);
- r4(B, C, D, E, A, 79, InternalState.Buffer.L);
-
- InternalState.State[0] += A;
- InternalState.State[1] += B;
- InternalState.State[2] += C;
- InternalState.State[3] += D;
- InternalState.State[4] += E;
-}
-
-void SHA1::addUncounted(uint8_t Data) {
-#ifdef SHA_BIG_ENDIAN
- InternalState.Buffer.C[InternalState.BufferOffset] = Data;
-#else
- InternalState.Buffer.C[InternalState.BufferOffset ^ 3] = Data;
-#endif
-
- InternalState.BufferOffset++;
- if (InternalState.BufferOffset == BLOCK_LENGTH) {
- hashBlock();
- InternalState.BufferOffset = 0;
- }
-}
-
-void SHA1::writebyte(uint8_t Data) {
- ++InternalState.ByteCount;
- addUncounted(Data);
-}
-
-void SHA1::update(ArrayRef<uint8_t> Data) {
- for (auto &C : Data)
- writebyte(C);
-}
-
-void SHA1::pad() {
- // Implement SHA-1 padding (fips180-2 5.1.1)
-
- // Pad with 0x80 followed by 0x00 until the end of the block
- addUncounted(0x80);
- while (InternalState.BufferOffset != 56)
- addUncounted(0x00);
-
- // Append length in the last 8 bytes
- addUncounted(0); // We're only using 32 bit lengths
- addUncounted(0); // But SHA-1 supports 64 bit lengths
- addUncounted(0); // So zero pad the top bits
- addUncounted(InternalState.ByteCount >> 29); // Shifting to multiply by 8
- addUncounted(InternalState.ByteCount >>
- 21); // as SHA-1 supports bitstreams as well as
- addUncounted(InternalState.ByteCount >> 13); // byte.
- addUncounted(InternalState.ByteCount >> 5);
- addUncounted(InternalState.ByteCount << 3);
-}
-
-StringRef SHA1::final() {
- // Pad to complete the last block
- pad();
-
-#ifdef SHA_BIG_ENDIAN
- // Just copy the current state
- for (int i = 0; i < 5; i++) {
- HashResult[i] = InternalState.State[i];
- }
-#else
- // Swap byte order back
- for (int i = 0; i < 5; i++) {
- HashResult[i] = (((InternalState.State[i]) << 24) & 0xff000000) |
- (((InternalState.State[i]) << 8) & 0x00ff0000) |
- (((InternalState.State[i]) >> 8) & 0x0000ff00) |
- (((InternalState.State[i]) >> 24) & 0x000000ff);
- }
-#endif
-
- // Return pointer to hash (20 characters)
- return StringRef((char *)HashResult, HASH_LENGTH);
-}
-
-StringRef SHA1::result() {
- auto StateToRestore = InternalState;
-
- auto Hash = final();
-
- // Restore the state
- InternalState = StateToRestore;
-
- // Return pointer to hash (20 characters)
- return Hash;
-}
-
-std::array<uint8_t, 20> SHA1::hash(ArrayRef<uint8_t> Data) {
- SHA1 Hash;
- Hash.update(Data);
- StringRef S = Hash.final();
-
- std::array<uint8_t, 20> Arr;
- memcpy(Arr.data(), S.data(), S.size());
- return Arr;
-}
diff --git a/gnu/llvm/lib/Support/ScaledNumber.cpp b/gnu/llvm/lib/Support/ScaledNumber.cpp
deleted file mode 100644
index 807c9fa521d..00000000000
--- a/gnu/llvm/lib/Support/ScaledNumber.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-//==- lib/Support/ScaledNumber.cpp - Support for scaled numbers -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implementation of some scaled number algorithms.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ScaledNumber.h"
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-using namespace llvm::ScaledNumbers;
-
-std::pair<uint64_t, int16_t> ScaledNumbers::multiply64(uint64_t LHS,
- uint64_t RHS) {
- // Separate into two 32-bit digits (U.L).
- auto getU = [](uint64_t N) { return N >> 32; };
- auto getL = [](uint64_t N) { return N & UINT32_MAX; };
- uint64_t UL = getU(LHS), LL = getL(LHS), UR = getU(RHS), LR = getL(RHS);
-
- // Compute cross products.
- uint64_t P1 = UL * UR, P2 = UL * LR, P3 = LL * UR, P4 = LL * LR;
-
- // Sum into two 64-bit digits.
- uint64_t Upper = P1, Lower = P4;
- auto addWithCarry = [&](uint64_t N) {
- uint64_t NewLower = Lower + (getL(N) << 32);
- Upper += getU(N) + (NewLower < Lower);
- Lower = NewLower;
- };
- addWithCarry(P2);
- addWithCarry(P3);
-
- // Check whether the upper digit is empty.
- if (!Upper)
- return std::make_pair(Lower, 0);
-
- // Shift as little as possible to maximize precision.
- unsigned LeadingZeros = countLeadingZeros(Upper);
- int Shift = 64 - LeadingZeros;
- if (LeadingZeros)
- Upper = Upper << LeadingZeros | Lower >> Shift;
- return getRounded(Upper, Shift,
- Shift && (Lower & UINT64_C(1) << (Shift - 1)));
-}
-
-static uint64_t getHalf(uint64_t N) { return (N >> 1) + (N & 1); }
-
-std::pair<uint32_t, int16_t> ScaledNumbers::divide32(uint32_t Dividend,
- uint32_t Divisor) {
- assert(Dividend && "expected non-zero dividend");
- assert(Divisor && "expected non-zero divisor");
-
- // Use 64-bit math and canonicalize the dividend to gain precision.
- uint64_t Dividend64 = Dividend;
- int Shift = 0;
- if (int Zeros = countLeadingZeros(Dividend64)) {
- Shift -= Zeros;
- Dividend64 <<= Zeros;
- }
- uint64_t Quotient = Dividend64 / Divisor;
- uint64_t Remainder = Dividend64 % Divisor;
-
- // If Quotient needs to be shifted, leave the rounding to getAdjusted().
- if (Quotient > UINT32_MAX)
- return getAdjusted<uint32_t>(Quotient, Shift);
-
- // Round based on the value of the next bit.
- return getRounded<uint32_t>(Quotient, Shift, Remainder >= getHalf(Divisor));
-}
-
-std::pair<uint64_t, int16_t> ScaledNumbers::divide64(uint64_t Dividend,
- uint64_t Divisor) {
- assert(Dividend && "expected non-zero dividend");
- assert(Divisor && "expected non-zero divisor");
-
- // Minimize size of divisor.
- int Shift = 0;
- if (int Zeros = countTrailingZeros(Divisor)) {
- Shift -= Zeros;
- Divisor >>= Zeros;
- }
-
- // Check for powers of two.
- if (Divisor == 1)
- return std::make_pair(Dividend, Shift);
-
- // Maximize size of dividend.
- if (int Zeros = countLeadingZeros(Dividend)) {
- Shift -= Zeros;
- Dividend <<= Zeros;
- }
-
- // Start with the result of a divide.
- uint64_t Quotient = Dividend / Divisor;
- Dividend %= Divisor;
-
- // Continue building the quotient with long division.
- while (!(Quotient >> 63) && Dividend) {
- // Shift Dividend and check for overflow.
- bool IsOverflow = Dividend >> 63;
- Dividend <<= 1;
- --Shift;
-
- // Get the next bit of Quotient.
- Quotient <<= 1;
- if (IsOverflow || Divisor <= Dividend) {
- Quotient |= 1;
- Dividend -= Divisor;
- }
- }
-
- return getRounded(Quotient, Shift, Dividend >= getHalf(Divisor));
-}
-
-int ScaledNumbers::compareImpl(uint64_t L, uint64_t R, int ScaleDiff) {
- assert(ScaleDiff >= 0 && "wrong argument order");
- assert(ScaleDiff < 64 && "numbers too far apart");
-
- uint64_t L_adjusted = L >> ScaleDiff;
- if (L_adjusted < R)
- return -1;
- if (L_adjusted > R)
- return 1;
-
- return L > L_adjusted << ScaleDiff ? 1 : 0;
-}
-
-static void appendDigit(std::string &Str, unsigned D) {
- assert(D < 10);
- Str += '0' + D % 10;
-}
-
-static void appendNumber(std::string &Str, uint64_t N) {
- while (N) {
- appendDigit(Str, N % 10);
- N /= 10;
- }
-}
-
-static bool doesRoundUp(char Digit) {
- switch (Digit) {
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- return true;
- default:
- return false;
- }
-}
-
-static std::string toStringAPFloat(uint64_t D, int E, unsigned Precision) {
- assert(E >= ScaledNumbers::MinScale);
- assert(E <= ScaledNumbers::MaxScale);
-
- // Find a new E, but don't let it increase past MaxScale.
- int LeadingZeros = ScaledNumberBase::countLeadingZeros64(D);
- int NewE = std::min(ScaledNumbers::MaxScale, E + 63 - LeadingZeros);
- int Shift = 63 - (NewE - E);
- assert(Shift <= LeadingZeros);
- assert(Shift == LeadingZeros || NewE == ScaledNumbers::MaxScale);
- assert(Shift >= 0 && Shift < 64 && "undefined behavior");
- D <<= Shift;
- E = NewE;
-
- // Check for a denormal.
- unsigned AdjustedE = E + 16383;
- if (!(D >> 63)) {
- assert(E == ScaledNumbers::MaxScale);
- AdjustedE = 0;
- }
-
- // Build the float and print it.
- uint64_t RawBits[2] = {D, AdjustedE};
- APFloat Float(APFloat::x87DoubleExtended(), APInt(80, RawBits));
- SmallVector<char, 24> Chars;
- Float.toString(Chars, Precision, 0);
- return std::string(Chars.begin(), Chars.end());
-}
-
-static std::string stripTrailingZeros(const std::string &Float) {
- size_t NonZero = Float.find_last_not_of('0');
- assert(NonZero != std::string::npos && "no . in floating point string");
-
- if (Float[NonZero] == '.')
- ++NonZero;
-
- return Float.substr(0, NonZero + 1);
-}
-
-std::string ScaledNumberBase::toString(uint64_t D, int16_t E, int Width,
- unsigned Precision) {
- if (!D)
- return "0.0";
-
- // Canonicalize exponent and digits.
- uint64_t Above0 = 0;
- uint64_t Below0 = 0;
- uint64_t Extra = 0;
- int ExtraShift = 0;
- if (E == 0) {
- Above0 = D;
- } else if (E > 0) {
- if (int Shift = std::min(int16_t(countLeadingZeros64(D)), E)) {
- D <<= Shift;
- E -= Shift;
-
- if (!E)
- Above0 = D;
- }
- } else if (E > -64) {
- Above0 = D >> -E;
- Below0 = D << (64 + E);
- } else if (E == -64) {
- // Special case: shift by 64 bits is undefined behavior.
- Below0 = D;
- } else if (E > -120) {
- Below0 = D >> (-E - 64);
- Extra = D << (128 + E);
- ExtraShift = -64 - E;
- }
-
- // Fall back on APFloat for very small and very large numbers.
- if (!Above0 && !Below0)
- return toStringAPFloat(D, E, Precision);
-
- // Append the digits before the decimal.
- std::string Str;
- size_t DigitsOut = 0;
- if (Above0) {
- appendNumber(Str, Above0);
- DigitsOut = Str.size();
- } else
- appendDigit(Str, 0);
- std::reverse(Str.begin(), Str.end());
-
- // Return early if there's nothing after the decimal.
- if (!Below0)
- return Str + ".0";
-
- // Append the decimal and beyond.
- Str += '.';
- uint64_t Error = UINT64_C(1) << (64 - Width);
-
- // We need to shift Below0 to the right to make space for calculating
- // digits. Save the precision we're losing in Extra.
- Extra = (Below0 & 0xf) << 56 | (Extra >> 8);
- Below0 >>= 4;
- size_t SinceDot = 0;
- size_t AfterDot = Str.size();
- do {
- if (ExtraShift) {
- --ExtraShift;
- Error *= 5;
- } else
- Error *= 10;
-
- Below0 *= 10;
- Extra *= 10;
- Below0 += (Extra >> 60);
- Extra = Extra & (UINT64_MAX >> 4);
- appendDigit(Str, Below0 >> 60);
- Below0 = Below0 & (UINT64_MAX >> 4);
- if (DigitsOut || Str.back() != '0')
- ++DigitsOut;
- ++SinceDot;
- } while (Error && (Below0 << 4 | Extra >> 60) >= Error / 2 &&
- (!Precision || DigitsOut <= Precision || SinceDot < 2));
-
- // Return early for maximum precision.
- if (!Precision || DigitsOut <= Precision)
- return stripTrailingZeros(Str);
-
- // Find where to truncate.
- size_t Truncate =
- std::max(Str.size() - (DigitsOut - Precision), AfterDot + 1);
-
- // Check if there's anything to truncate.
- if (Truncate >= Str.size())
- return stripTrailingZeros(Str);
-
- bool Carry = doesRoundUp(Str[Truncate]);
- if (!Carry)
- return stripTrailingZeros(Str.substr(0, Truncate));
-
- // Round with the first truncated digit.
- for (std::string::reverse_iterator I(Str.begin() + Truncate), E = Str.rend();
- I != E; ++I) {
- if (*I == '.')
- continue;
- if (*I == '9') {
- *I = '0';
- continue;
- }
-
- ++*I;
- Carry = false;
- break;
- }
-
- // Add "1" in front if we still need to carry.
- return stripTrailingZeros(std::string(Carry, '1') + Str.substr(0, Truncate));
-}
-
-raw_ostream &ScaledNumberBase::print(raw_ostream &OS, uint64_t D, int16_t E,
- int Width, unsigned Precision) {
- return OS << toString(D, E, Width, Precision);
-}
-
-void ScaledNumberBase::dump(uint64_t D, int16_t E, int Width) {
- print(dbgs(), D, E, Width, 0) << "[" << Width << ":" << D << "*2^" << E
- << "]";
-}
diff --git a/gnu/llvm/lib/Support/ScopedPrinter.cpp b/gnu/llvm/lib/Support/ScopedPrinter.cpp
deleted file mode 100644
index 981dfbff520..00000000000
--- a/gnu/llvm/lib/Support/ScopedPrinter.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#include "llvm/Support/ScopedPrinter.h"
-
-#include "llvm/Support/Format.h"
-#include <cctype>
-
-using namespace llvm::support;
-
-namespace llvm {
-
-raw_ostream &operator<<(raw_ostream &OS, const HexNumber &Value) {
- OS << "0x" << to_hexString(Value.Value);
- return OS;
-}
-
-const std::string to_hexString(uint64_t Value, bool UpperCase) {
- std::string number;
- llvm::raw_string_ostream stream(number);
- stream << format_hex_no_prefix(Value, 1, UpperCase);
- return stream.str();
-}
-
-void ScopedPrinter::printBinaryImpl(StringRef Label, StringRef Str,
- ArrayRef<uint8_t> Data, bool Block,
- uint32_t StartOffset) {
- if (Data.size() > 16)
- Block = true;
-
- if (Block) {
- startLine() << Label;
- if (!Str.empty())
- OS << ": " << Str;
- OS << " (\n";
- if (!Data.empty())
- OS << format_bytes_with_ascii(Data, StartOffset, 16, 4,
- (IndentLevel + 1) * 2, true)
- << "\n";
- startLine() << ")\n";
- } else {
- startLine() << Label << ":";
- if (!Str.empty())
- OS << " " << Str;
- OS << " (" << format_bytes(Data, None, Data.size(), 1, 0, true) << ")\n";
- }
-}
-
-} // namespace llvm
diff --git a/gnu/llvm/lib/Support/Signals.cpp b/gnu/llvm/lib/Support/Signals.cpp
deleted file mode 100644
index 333f492d458..00000000000
--- a/gnu/llvm/lib/Support/Signals.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-//===- Signals.cpp - Signal Handling support --------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines some helpful functions for dealing with the possibility of
-// Unix signals occurring while your program is running.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Signals.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/FormatAdapters.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/StringSaver.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Options.h"
-#include <vector>
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
-
-using namespace llvm;
-
-// Use explicit storage to avoid accessing cl::opt in a signal handler.
-static bool DisableSymbolicationFlag = false;
-static cl::opt<bool, true>
- DisableSymbolication("disable-symbolication",
- cl::desc("Disable symbolizing crash backtraces."),
- cl::location(DisableSymbolicationFlag), cl::Hidden);
-
-// Callbacks to run in signal handler must be lock-free because a signal handler
-// could be running as we add new callbacks. We don't add unbounded numbers of
-// callbacks, an array is therefore sufficient.
-struct CallbackAndCookie {
- sys::SignalHandlerCallback Callback;
- void *Cookie;
- enum class Status { Empty, Initializing, Initialized, Executing };
- std::atomic<Status> Flag;
-};
-static constexpr size_t MaxSignalHandlerCallbacks = 8;
-static CallbackAndCookie CallBacksToRun[MaxSignalHandlerCallbacks];
-
-// Signal-safe.
-void sys::RunSignalHandlers() {
- for (size_t I = 0; I < MaxSignalHandlerCallbacks; ++I) {
- auto &RunMe = CallBacksToRun[I];
- auto Expected = CallbackAndCookie::Status::Initialized;
- auto Desired = CallbackAndCookie::Status::Executing;
- if (!RunMe.Flag.compare_exchange_strong(Expected, Desired))
- continue;
- (*RunMe.Callback)(RunMe.Cookie);
- RunMe.Callback = nullptr;
- RunMe.Cookie = nullptr;
- RunMe.Flag.store(CallbackAndCookie::Status::Empty);
- }
-}
-
-// Signal-safe.
-static void insertSignalHandler(sys::SignalHandlerCallback FnPtr,
- void *Cookie) {
- for (size_t I = 0; I < MaxSignalHandlerCallbacks; ++I) {
- auto &SetMe = CallBacksToRun[I];
- auto Expected = CallbackAndCookie::Status::Empty;
- auto Desired = CallbackAndCookie::Status::Initializing;
- if (!SetMe.Flag.compare_exchange_strong(Expected, Desired))
- continue;
- SetMe.Callback = FnPtr;
- SetMe.Cookie = Cookie;
- SetMe.Flag.store(CallbackAndCookie::Status::Initialized);
- return;
- }
- report_fatal_error("too many signal callbacks already registered");
-}
-
-static bool findModulesAndOffsets(void **StackTrace, int Depth,
- const char **Modules, intptr_t *Offsets,
- const char *MainExecutableName,
- StringSaver &StrPool);
-
-/// Format a pointer value as hexadecimal. Zero pad it out so its always the
-/// same width.
-static FormattedNumber format_ptr(void *PC) {
- // Each byte is two hex digits plus 2 for the 0x prefix.
- unsigned PtrWidth = 2 + 2 * sizeof(void *);
- return format_hex((uint64_t)PC, PtrWidth);
-}
-
-/// Helper that launches llvm-symbolizer and symbolizes a backtrace.
-LLVM_ATTRIBUTE_USED
-static bool printSymbolizedStackTrace(StringRef Argv0, void **StackTrace,
- int Depth, llvm::raw_ostream &OS) {
- if (DisableSymbolicationFlag)
- return false;
-
- // Don't recursively invoke the llvm-symbolizer binary.
- if (Argv0.find("llvm-symbolizer") != std::string::npos)
- return false;
-
- // FIXME: Subtract necessary number from StackTrace entries to turn return addresses
- // into actual instruction addresses.
- // Use llvm-symbolizer tool to symbolize the stack traces. First look for it
- // alongside our binary, then in $PATH.
- ErrorOr<std::string> LLVMSymbolizerPathOrErr = std::error_code();
- if (!Argv0.empty()) {
- StringRef Parent = llvm::sys::path::parent_path(Argv0);
- if (!Parent.empty())
- LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer", Parent);
- }
- if (!LLVMSymbolizerPathOrErr)
- LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer");
- if (!LLVMSymbolizerPathOrErr)
- return false;
- const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr;
-
- // If we don't know argv0 or the address of main() at this point, try
- // to guess it anyway (it's possible on some platforms).
- std::string MainExecutableName =
- Argv0.empty() ? sys::fs::getMainExecutable(nullptr, nullptr)
- : (std::string)Argv0;
- BumpPtrAllocator Allocator;
- StringSaver StrPool(Allocator);
- std::vector<const char *> Modules(Depth, nullptr);
- std::vector<intptr_t> Offsets(Depth, 0);
- if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(), Offsets.data(),
- MainExecutableName.c_str(), StrPool))
- return false;
- int InputFD;
- SmallString<32> InputFile, OutputFile;
- sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile);
- sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile);
- FileRemover InputRemover(InputFile.c_str());
- FileRemover OutputRemover(OutputFile.c_str());
-
- {
- raw_fd_ostream Input(InputFD, true);
- for (int i = 0; i < Depth; i++) {
- if (Modules[i])
- Input << Modules[i] << " " << (void*)Offsets[i] << "\n";
- }
- }
-
- Optional<StringRef> Redirects[] = {StringRef(InputFile),
- StringRef(OutputFile), StringRef("")};
- StringRef Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining",
-#ifdef _WIN32
- // Pass --relative-address on Windows so that we don't
- // have to add ImageBase from PE file.
- // FIXME: Make this the default for llvm-symbolizer.
- "--relative-address",
-#endif
- "--demangle"};
- int RunResult =
- sys::ExecuteAndWait(LLVMSymbolizerPath, Args, None, Redirects);
- if (RunResult != 0)
- return false;
-
- // This report format is based on the sanitizer stack trace printer. See
- // sanitizer_stacktrace_printer.cc in compiler-rt.
- auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str());
- if (!OutputBuf)
- return false;
- StringRef Output = OutputBuf.get()->getBuffer();
- SmallVector<StringRef, 32> Lines;
- Output.split(Lines, "\n");
- auto CurLine = Lines.begin();
- int frame_no = 0;
- for (int i = 0; i < Depth; i++) {
- auto PrintLineHeader = [&]() {
- OS << right_justify(formatv("#{0}", frame_no++).str(),
- std::log10(Depth) + 2)
- << ' ' << format_ptr(StackTrace[i]) << ' ';
- };
- if (!Modules[i]) {
- PrintLineHeader();
- OS << '\n';
- continue;
- }
- // Read pairs of lines (function name and file/line info) until we
- // encounter empty line.
- for (;;) {
- if (CurLine == Lines.end())
- return false;
- StringRef FunctionName = *CurLine++;
- if (FunctionName.empty())
- break;
- PrintLineHeader();
- if (!FunctionName.startswith("??"))
- OS << FunctionName << ' ';
- if (CurLine == Lines.end())
- return false;
- StringRef FileLineInfo = *CurLine++;
- if (!FileLineInfo.startswith("??"))
- OS << FileLineInfo;
- else
- OS << "(" << Modules[i] << '+' << format_hex(Offsets[i], 0) << ")";
- OS << "\n";
- }
- }
- return true;
-}
-
-// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
-#include "Unix/Signals.inc"
-#endif
-#ifdef _WIN32
-#include "Windows/Signals.inc"
-#endif
diff --git a/gnu/llvm/lib/Support/SmallPtrSet.cpp b/gnu/llvm/lib/Support/SmallPtrSet.cpp
deleted file mode 100644
index fed4a17d663..00000000000
--- a/gnu/llvm/lib/Support/SmallPtrSet.cpp
+++ /dev/null
@@ -1,271 +0,0 @@
-//===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the SmallPtrSet class. See SmallPtrSet.h for an
-// overview of the algorithm.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdlib>
-
-using namespace llvm;
-
-void SmallPtrSetImplBase::shrink_and_clear() {
- assert(!isSmall() && "Can't shrink a small set!");
- free(CurArray);
-
- // Reduce the number of buckets.
- unsigned Size = size();
- CurArraySize = Size > 16 ? 1 << (Log2_32_Ceil(Size) + 1) : 32;
- NumNonEmpty = NumTombstones = 0;
-
- // Install the new array. Clear all the buckets to empty.
- CurArray = (const void**)safe_malloc(sizeof(void*) * CurArraySize);
-
- memset(CurArray, -1, CurArraySize*sizeof(void*));
-}
-
-std::pair<const void *const *, bool>
-SmallPtrSetImplBase::insert_imp_big(const void *Ptr) {
- if (LLVM_UNLIKELY(size() * 4 >= CurArraySize * 3)) {
- // If more than 3/4 of the array is full, grow.
- Grow(CurArraySize < 64 ? 128 : CurArraySize * 2);
- } else if (LLVM_UNLIKELY(CurArraySize - NumNonEmpty < CurArraySize / 8)) {
- // If fewer of 1/8 of the array is empty (meaning that many are filled with
- // tombstones), rehash.
- Grow(CurArraySize);
- }
-
- // Okay, we know we have space. Find a hash bucket.
- const void **Bucket = const_cast<const void**>(FindBucketFor(Ptr));
- if (*Bucket == Ptr)
- return std::make_pair(Bucket, false); // Already inserted, good.
-
- // Otherwise, insert it!
- if (*Bucket == getTombstoneMarker())
- --NumTombstones;
- else
- ++NumNonEmpty; // Track density.
- *Bucket = Ptr;
- incrementEpoch();
- return std::make_pair(Bucket, true);
-}
-
-const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const {
- unsigned Bucket = DenseMapInfo<void *>::getHashValue(Ptr) & (CurArraySize-1);
- unsigned ArraySize = CurArraySize;
- unsigned ProbeAmt = 1;
- const void *const *Array = CurArray;
- const void *const *Tombstone = nullptr;
- while (true) {
- // If we found an empty bucket, the pointer doesn't exist in the set.
- // Return a tombstone if we've seen one so far, or the empty bucket if
- // not.
- if (LLVM_LIKELY(Array[Bucket] == getEmptyMarker()))
- return Tombstone ? Tombstone : Array+Bucket;
-
- // Found Ptr's bucket?
- if (LLVM_LIKELY(Array[Bucket] == Ptr))
- return Array+Bucket;
-
- // If this is a tombstone, remember it. If Ptr ends up not in the set, we
- // prefer to return it than something that would require more probing.
- if (Array[Bucket] == getTombstoneMarker() && !Tombstone)
- Tombstone = Array+Bucket; // Remember the first tombstone found.
-
- // It's a hash collision or a tombstone. Reprobe.
- Bucket = (Bucket + ProbeAmt++) & (ArraySize-1);
- }
-}
-
-/// Grow - Allocate a larger backing store for the buckets and move it over.
-///
-void SmallPtrSetImplBase::Grow(unsigned NewSize) {
- const void **OldBuckets = CurArray;
- const void **OldEnd = EndPointer();
- bool WasSmall = isSmall();
-
- // Install the new array. Clear all the buckets to empty.
- const void **NewBuckets = (const void**) safe_malloc(sizeof(void*) * NewSize);
-
- // Reset member only if memory was allocated successfully
- CurArray = NewBuckets;
- CurArraySize = NewSize;
- memset(CurArray, -1, NewSize*sizeof(void*));
-
- // Copy over all valid entries.
- for (const void **BucketPtr = OldBuckets; BucketPtr != OldEnd; ++BucketPtr) {
- // Copy over the element if it is valid.
- const void *Elt = *BucketPtr;
- if (Elt != getTombstoneMarker() && Elt != getEmptyMarker())
- *const_cast<void**>(FindBucketFor(Elt)) = const_cast<void*>(Elt);
- }
-
- if (!WasSmall)
- free(OldBuckets);
- NumNonEmpty -= NumTombstones;
- NumTombstones = 0;
-}
-
-SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
- const SmallPtrSetImplBase &that) {
- SmallArray = SmallStorage;
-
- // If we're becoming small, prepare to insert into our stack space
- if (that.isSmall()) {
- CurArray = SmallArray;
- // Otherwise, allocate new heap space (unless we were the same size)
- } else {
- CurArray = (const void**)safe_malloc(sizeof(void*) * that.CurArraySize);
- }
-
- // Copy over the that array.
- CopyHelper(that);
-}
-
-SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
- unsigned SmallSize,
- SmallPtrSetImplBase &&that) {
- SmallArray = SmallStorage;
- MoveHelper(SmallSize, std::move(that));
-}
-
-void SmallPtrSetImplBase::CopyFrom(const SmallPtrSetImplBase &RHS) {
- assert(&RHS != this && "Self-copy should be handled by the caller.");
-
- if (isSmall() && RHS.isSmall())
- assert(CurArraySize == RHS.CurArraySize &&
- "Cannot assign sets with different small sizes");
-
- // If we're becoming small, prepare to insert into our stack space
- if (RHS.isSmall()) {
- if (!isSmall())
- free(CurArray);
- CurArray = SmallArray;
- // Otherwise, allocate new heap space (unless we were the same size)
- } else if (CurArraySize != RHS.CurArraySize) {
- if (isSmall())
- CurArray = (const void**)safe_malloc(sizeof(void*) * RHS.CurArraySize);
- else {
- const void **T = (const void**)safe_realloc(CurArray,
- sizeof(void*) * RHS.CurArraySize);
- CurArray = T;
- }
- }
-
- CopyHelper(RHS);
-}
-
-void SmallPtrSetImplBase::CopyHelper(const SmallPtrSetImplBase &RHS) {
- // Copy over the new array size
- CurArraySize = RHS.CurArraySize;
-
- // Copy over the contents from the other set
- std::copy(RHS.CurArray, RHS.EndPointer(), CurArray);
-
- NumNonEmpty = RHS.NumNonEmpty;
- NumTombstones = RHS.NumTombstones;
-}
-
-void SmallPtrSetImplBase::MoveFrom(unsigned SmallSize,
- SmallPtrSetImplBase &&RHS) {
- if (!isSmall())
- free(CurArray);
- MoveHelper(SmallSize, std::move(RHS));
-}
-
-void SmallPtrSetImplBase::MoveHelper(unsigned SmallSize,
- SmallPtrSetImplBase &&RHS) {
- assert(&RHS != this && "Self-move should be handled by the caller.");
-
- if (RHS.isSmall()) {
- // Copy a small RHS rather than moving.
- CurArray = SmallArray;
- std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, CurArray);
- } else {
- CurArray = RHS.CurArray;
- RHS.CurArray = RHS.SmallArray;
- }
-
- // Copy the rest of the trivial members.
- CurArraySize = RHS.CurArraySize;
- NumNonEmpty = RHS.NumNonEmpty;
- NumTombstones = RHS.NumTombstones;
-
- // Make the RHS small and empty.
- RHS.CurArraySize = SmallSize;
- assert(RHS.CurArray == RHS.SmallArray);
- RHS.NumNonEmpty = 0;
- RHS.NumTombstones = 0;
-}
-
-void SmallPtrSetImplBase::swap(SmallPtrSetImplBase &RHS) {
- if (this == &RHS) return;
-
- // We can only avoid copying elements if neither set is small.
- if (!this->isSmall() && !RHS.isSmall()) {
- std::swap(this->CurArray, RHS.CurArray);
- std::swap(this->CurArraySize, RHS.CurArraySize);
- std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
- std::swap(this->NumTombstones, RHS.NumTombstones);
- return;
- }
-
- // FIXME: From here on we assume that both sets have the same small size.
-
- // If only RHS is small, copy the small elements into LHS and move the pointer
- // from LHS to RHS.
- if (!this->isSmall() && RHS.isSmall()) {
- assert(RHS.CurArray == RHS.SmallArray);
- std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, this->SmallArray);
- std::swap(RHS.CurArraySize, this->CurArraySize);
- std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
- std::swap(this->NumTombstones, RHS.NumTombstones);
- RHS.CurArray = this->CurArray;
- this->CurArray = this->SmallArray;
- return;
- }
-
- // If only LHS is small, copy the small elements into RHS and move the pointer
- // from RHS to LHS.
- if (this->isSmall() && !RHS.isSmall()) {
- assert(this->CurArray == this->SmallArray);
- std::copy(this->CurArray, this->CurArray + this->NumNonEmpty,
- RHS.SmallArray);
- std::swap(RHS.CurArraySize, this->CurArraySize);
- std::swap(RHS.NumNonEmpty, this->NumNonEmpty);
- std::swap(RHS.NumTombstones, this->NumTombstones);
- this->CurArray = RHS.CurArray;
- RHS.CurArray = RHS.SmallArray;
- return;
- }
-
- // Both a small, just swap the small elements.
- assert(this->isSmall() && RHS.isSmall());
- unsigned MinNonEmpty = std::min(this->NumNonEmpty, RHS.NumNonEmpty);
- std::swap_ranges(this->SmallArray, this->SmallArray + MinNonEmpty,
- RHS.SmallArray);
- if (this->NumNonEmpty > MinNonEmpty) {
- std::copy(this->SmallArray + MinNonEmpty,
- this->SmallArray + this->NumNonEmpty,
- RHS.SmallArray + MinNonEmpty);
- } else {
- std::copy(RHS.SmallArray + MinNonEmpty, RHS.SmallArray + RHS.NumNonEmpty,
- this->SmallArray + MinNonEmpty);
- }
- assert(this->CurArraySize == RHS.CurArraySize);
- std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
- std::swap(this->NumTombstones, RHS.NumTombstones);
-}
diff --git a/gnu/llvm/lib/Support/SmallVector.cpp b/gnu/llvm/lib/Support/SmallVector.cpp
deleted file mode 100644
index 1070c6672ed..00000000000
--- a/gnu/llvm/lib/Support/SmallVector.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-//===- llvm/ADT/SmallVector.cpp - 'Normally small' vectors ----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the SmallVector class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/SmallVector.h"
-using namespace llvm;
-
-// Check that no bytes are wasted and everything is well-aligned.
-namespace {
-struct Struct16B {
- alignas(16) void *X;
-};
-struct Struct32B {
- alignas(32) void *X;
-};
-}
-static_assert(sizeof(SmallVector<void *, 0>) ==
- sizeof(unsigned) * 2 + sizeof(void *),
- "wasted space in SmallVector size 0");
-static_assert(alignof(SmallVector<Struct16B, 0>) >= alignof(Struct16B),
- "wrong alignment for 16-byte aligned T");
-static_assert(alignof(SmallVector<Struct32B, 0>) >= alignof(Struct32B),
- "wrong alignment for 32-byte aligned T");
-static_assert(sizeof(SmallVector<Struct16B, 0>) >= alignof(Struct16B),
- "missing padding for 16-byte aligned T");
-static_assert(sizeof(SmallVector<Struct32B, 0>) >= alignof(Struct32B),
- "missing padding for 32-byte aligned T");
-static_assert(sizeof(SmallVector<void *, 1>) ==
- sizeof(unsigned) * 2 + sizeof(void *) * 2,
- "wasted space in SmallVector size 1");
-
-/// grow_pod - This is an implementation of the grow() method which only works
-/// on POD-like datatypes and is out of line to reduce code duplication.
-void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity,
- size_t TSize) {
- // Ensure we can fit the new capacity in 32 bits.
- if (MinCapacity > UINT32_MAX)
- report_bad_alloc_error("SmallVector capacity overflow during allocation");
-
- size_t NewCapacity = 2 * capacity() + 1; // Always grow.
- NewCapacity =
- std::min(std::max(NewCapacity, MinCapacity), size_t(UINT32_MAX));
-
- void *NewElts;
- if (BeginX == FirstEl) {
- NewElts = safe_malloc(NewCapacity * TSize);
-
- // Copy the elements over. No need to run dtors on PODs.
- memcpy(NewElts, this->BeginX, size() * TSize);
- } else {
- // If this wasn't grown from the inline copy, grow the allocated space.
- NewElts = safe_realloc(this->BeginX, NewCapacity * TSize);
- }
-
- this->BeginX = NewElts;
- this->Capacity = NewCapacity;
-}
diff --git a/gnu/llvm/lib/Support/SourceMgr.cpp b/gnu/llvm/lib/Support/SourceMgr.cpp
deleted file mode 100644
index a55ad881d01..00000000000
--- a/gnu/llvm/lib/Support/SourceMgr.cpp
+++ /dev/null
@@ -1,507 +0,0 @@
-//===- SourceMgr.cpp - Manager for Simple Source Buffers & Diagnostics ----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the SourceMgr class. This class is used as a simple
-// substrate for diagnostics, #include handling, and other low level things for
-// simple parsers.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/Locale.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <limits>
-#include <memory>
-#include <string>
-#include <utility>
-
-using namespace llvm;
-
-static const size_t TabStop = 8;
-
-unsigned SourceMgr::AddIncludeFile(const std::string &Filename,
- SMLoc IncludeLoc,
- std::string &IncludedFile) {
- IncludedFile = Filename;
- ErrorOr<std::unique_ptr<MemoryBuffer>> NewBufOrErr =
- MemoryBuffer::getFile(IncludedFile);
-
- // If the file didn't exist directly, see if it's in an include path.
- for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBufOrErr;
- ++i) {
- IncludedFile =
- IncludeDirectories[i] + sys::path::get_separator().data() + Filename;
- NewBufOrErr = MemoryBuffer::getFile(IncludedFile);
- }
-
- if (!NewBufOrErr)
- return 0;
-
- return AddNewSourceBuffer(std::move(*NewBufOrErr), IncludeLoc);
-}
-
-unsigned SourceMgr::FindBufferContainingLoc(SMLoc Loc) const {
- for (unsigned i = 0, e = Buffers.size(); i != e; ++i)
- if (Loc.getPointer() >= Buffers[i].Buffer->getBufferStart() &&
- // Use <= here so that a pointer to the null at the end of the buffer
- // is included as part of the buffer.
- Loc.getPointer() <= Buffers[i].Buffer->getBufferEnd())
- return i + 1;
- return 0;
-}
-
-template <typename T>
-unsigned SourceMgr::SrcBuffer::getLineNumber(const char *Ptr) const {
-
- // Ensure OffsetCache is allocated and populated with offsets of all the
- // '\n' bytes.
- std::vector<T> *Offsets = nullptr;
- if (OffsetCache.isNull()) {
- Offsets = new std::vector<T>();
- OffsetCache = Offsets;
- size_t Sz = Buffer->getBufferSize();
- assert(Sz <= std::numeric_limits<T>::max());
- StringRef S = Buffer->getBuffer();
- for (size_t N = 0; N < Sz; ++N) {
- if (S[N] == '\n') {
- Offsets->push_back(static_cast<T>(N));
- }
- }
- } else {
- Offsets = OffsetCache.get<std::vector<T> *>();
- }
-
- const char *BufStart = Buffer->getBufferStart();
- assert(Ptr >= BufStart && Ptr <= Buffer->getBufferEnd());
- ptrdiff_t PtrDiff = Ptr - BufStart;
- assert(PtrDiff >= 0 && static_cast<size_t>(PtrDiff) <= std::numeric_limits<T>::max());
- T PtrOffset = static_cast<T>(PtrDiff);
-
- // std::lower_bound returns the first EOL offset that's not-less-than
- // PtrOffset, meaning the EOL that _ends the line_ that PtrOffset is on
- // (including if PtrOffset refers to the EOL itself). If there's no such
- // EOL, returns end().
- auto EOL = std::lower_bound(Offsets->begin(), Offsets->end(), PtrOffset);
-
- // Lines count from 1, so add 1 to the distance from the 0th line.
- return (1 + (EOL - Offsets->begin()));
-}
-
-SourceMgr::SrcBuffer::SrcBuffer(SourceMgr::SrcBuffer &&Other)
- : Buffer(std::move(Other.Buffer)),
- OffsetCache(Other.OffsetCache),
- IncludeLoc(Other.IncludeLoc) {
- Other.OffsetCache = nullptr;
-}
-
-SourceMgr::SrcBuffer::~SrcBuffer() {
- if (!OffsetCache.isNull()) {
- if (OffsetCache.is<std::vector<uint8_t>*>())
- delete OffsetCache.get<std::vector<uint8_t>*>();
- else if (OffsetCache.is<std::vector<uint16_t>*>())
- delete OffsetCache.get<std::vector<uint16_t>*>();
- else if (OffsetCache.is<std::vector<uint32_t>*>())
- delete OffsetCache.get<std::vector<uint32_t>*>();
- else
- delete OffsetCache.get<std::vector<uint64_t>*>();
- OffsetCache = nullptr;
- }
-}
-
-std::pair<unsigned, unsigned>
-SourceMgr::getLineAndColumn(SMLoc Loc, unsigned BufferID) const {
- if (!BufferID)
- BufferID = FindBufferContainingLoc(Loc);
- assert(BufferID && "Invalid Location!");
-
- auto &SB = getBufferInfo(BufferID);
- const char *Ptr = Loc.getPointer();
-
- size_t Sz = SB.Buffer->getBufferSize();
- unsigned LineNo;
- if (Sz <= std::numeric_limits<uint8_t>::max())
- LineNo = SB.getLineNumber<uint8_t>(Ptr);
- else if (Sz <= std::numeric_limits<uint16_t>::max())
- LineNo = SB.getLineNumber<uint16_t>(Ptr);
- else if (Sz <= std::numeric_limits<uint32_t>::max())
- LineNo = SB.getLineNumber<uint32_t>(Ptr);
- else
- LineNo = SB.getLineNumber<uint64_t>(Ptr);
-
- const char *BufStart = SB.Buffer->getBufferStart();
- size_t NewlineOffs = StringRef(BufStart, Ptr-BufStart).find_last_of("\n\r");
- if (NewlineOffs == StringRef::npos) NewlineOffs = ~(size_t)0;
- return std::make_pair(LineNo, Ptr-BufStart-NewlineOffs);
-}
-
-void SourceMgr::PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const {
- if (IncludeLoc == SMLoc()) return; // Top of stack.
-
- unsigned CurBuf = FindBufferContainingLoc(IncludeLoc);
- assert(CurBuf && "Invalid or unspecified location!");
-
- PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS);
-
- OS << "Included from "
- << getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
- << ":" << FindLineNumber(IncludeLoc, CurBuf) << ":\n";
-}
-
-SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
- const Twine &Msg,
- ArrayRef<SMRange> Ranges,
- ArrayRef<SMFixIt> FixIts) const {
- // First thing to do: find the current buffer containing the specified
- // location to pull out the source line.
- SmallVector<std::pair<unsigned, unsigned>, 4> ColRanges;
- std::pair<unsigned, unsigned> LineAndCol;
- StringRef BufferID = "<unknown>";
- std::string LineStr;
-
- if (Loc.isValid()) {
- unsigned CurBuf = FindBufferContainingLoc(Loc);
- assert(CurBuf && "Invalid or unspecified location!");
-
- const MemoryBuffer *CurMB = getMemoryBuffer(CurBuf);
- BufferID = CurMB->getBufferIdentifier();
-
- // Scan backward to find the start of the line.
- const char *LineStart = Loc.getPointer();
- const char *BufStart = CurMB->getBufferStart();
- while (LineStart != BufStart && LineStart[-1] != '\n' &&
- LineStart[-1] != '\r')
- --LineStart;
-
- // Get the end of the line.
- const char *LineEnd = Loc.getPointer();
- const char *BufEnd = CurMB->getBufferEnd();
- while (LineEnd != BufEnd && LineEnd[0] != '\n' && LineEnd[0] != '\r')
- ++LineEnd;
- LineStr = std::string(LineStart, LineEnd);
-
- // Convert any ranges to column ranges that only intersect the line of the
- // location.
- for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
- SMRange R = Ranges[i];
- if (!R.isValid()) continue;
-
- // If the line doesn't contain any part of the range, then ignore it.
- if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
- continue;
-
- // Ignore pieces of the range that go onto other lines.
- if (R.Start.getPointer() < LineStart)
- R.Start = SMLoc::getFromPointer(LineStart);
- if (R.End.getPointer() > LineEnd)
- R.End = SMLoc::getFromPointer(LineEnd);
-
- // Translate from SMLoc ranges to column ranges.
- // FIXME: Handle multibyte characters.
- ColRanges.push_back(std::make_pair(R.Start.getPointer()-LineStart,
- R.End.getPointer()-LineStart));
- }
-
- LineAndCol = getLineAndColumn(Loc, CurBuf);
- }
-
- return SMDiagnostic(*this, Loc, BufferID, LineAndCol.first,
- LineAndCol.second-1, Kind, Msg.str(),
- LineStr, ColRanges, FixIts);
-}
-
-void SourceMgr::PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic,
- bool ShowColors) const {
- // Report the message with the diagnostic handler if present.
- if (DiagHandler) {
- DiagHandler(Diagnostic, DiagContext);
- return;
- }
-
- if (Diagnostic.getLoc().isValid()) {
- unsigned CurBuf = FindBufferContainingLoc(Diagnostic.getLoc());
- assert(CurBuf && "Invalid or unspecified location!");
- PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS);
- }
-
- Diagnostic.print(nullptr, OS, ShowColors);
-}
-
-void SourceMgr::PrintMessage(raw_ostream &OS, SMLoc Loc,
- SourceMgr::DiagKind Kind,
- const Twine &Msg, ArrayRef<SMRange> Ranges,
- ArrayRef<SMFixIt> FixIts, bool ShowColors) const {
- PrintMessage(OS, GetMessage(Loc, Kind, Msg, Ranges, FixIts), ShowColors);
-}
-
-void SourceMgr::PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
- const Twine &Msg, ArrayRef<SMRange> Ranges,
- ArrayRef<SMFixIt> FixIts, bool ShowColors) const {
- PrintMessage(errs(), Loc, Kind, Msg, Ranges, FixIts, ShowColors);
-}
-
-//===----------------------------------------------------------------------===//
-// SMDiagnostic Implementation
-//===----------------------------------------------------------------------===//
-
-SMDiagnostic::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> Hints)
- : SM(&sm), Loc(L), Filename(FN), LineNo(Line), ColumnNo(Col), Kind(Kind),
- Message(Msg), LineContents(LineStr), Ranges(Ranges.vec()),
- FixIts(Hints.begin(), Hints.end()) {
- llvm::sort(FixIts);
-}
-
-static void buildFixItLine(std::string &CaretLine, std::string &FixItLine,
- ArrayRef<SMFixIt> FixIts, ArrayRef<char> SourceLine){
- if (FixIts.empty())
- return;
-
- const char *LineStart = SourceLine.begin();
- const char *LineEnd = SourceLine.end();
-
- size_t PrevHintEndCol = 0;
-
- for (ArrayRef<SMFixIt>::iterator I = FixIts.begin(), E = FixIts.end();
- I != E; ++I) {
- // If the fixit contains a newline or tab, ignore it.
- if (I->getText().find_first_of("\n\r\t") != StringRef::npos)
- continue;
-
- SMRange R = I->getRange();
-
- // If the line doesn't contain any part of the range, then ignore it.
- if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
- continue;
-
- // Translate from SMLoc to column.
- // Ignore pieces of the range that go onto other lines.
- // FIXME: Handle multibyte characters in the source line.
- unsigned FirstCol;
- if (R.Start.getPointer() < LineStart)
- FirstCol = 0;
- else
- FirstCol = R.Start.getPointer() - LineStart;
-
- // If we inserted a long previous hint, push this one forwards, and add
- // an extra space to show that this is not part of the previous
- // completion. This is sort of the best we can do when two hints appear
- // to overlap.
- //
- // Note that if this hint is located immediately after the previous
- // hint, no space will be added, since the location is more important.
- unsigned HintCol = FirstCol;
- if (HintCol < PrevHintEndCol)
- HintCol = PrevHintEndCol + 1;
-
- // FIXME: This assertion is intended to catch unintended use of multibyte
- // characters in fixits. If we decide to do this, we'll have to track
- // separate byte widths for the source and fixit lines.
- assert((size_t)sys::locale::columnWidth(I->getText()) ==
- I->getText().size());
-
- // This relies on one byte per column in our fixit hints.
- unsigned LastColumnModified = HintCol + I->getText().size();
- if (LastColumnModified > FixItLine.size())
- FixItLine.resize(LastColumnModified, ' ');
-
- std::copy(I->getText().begin(), I->getText().end(),
- FixItLine.begin() + HintCol);
-
- PrevHintEndCol = LastColumnModified;
-
- // For replacements, mark the removal range with '~'.
- // FIXME: Handle multibyte characters in the source line.
- unsigned LastCol;
- if (R.End.getPointer() >= LineEnd)
- LastCol = LineEnd - LineStart;
- else
- LastCol = R.End.getPointer() - LineStart;
-
- std::fill(&CaretLine[FirstCol], &CaretLine[LastCol], '~');
- }
-}
-
-static void printSourceLine(raw_ostream &S, StringRef LineContents) {
- // Print out the source line one character at a time, so we can expand tabs.
- for (unsigned i = 0, e = LineContents.size(), OutCol = 0; i != e; ++i) {
- size_t NextTab = LineContents.find('\t', i);
- // If there were no tabs left, print the rest, we are done.
- if (NextTab == StringRef::npos) {
- S << LineContents.drop_front(i);
- break;
- }
-
- // Otherwise, print from i to NextTab.
- S << LineContents.slice(i, NextTab);
- OutCol += NextTab - i;
- i = NextTab;
-
- // If we have a tab, emit at least one space, then round up to 8 columns.
- do {
- S << ' ';
- ++OutCol;
- } while ((OutCol % TabStop) != 0);
- }
- S << '\n';
-}
-
-static bool isNonASCII(char c) {
- return c & 0x80;
-}
-
-void SMDiagnostic::print(const char *ProgName, raw_ostream &OS,
- bool ShowColors, bool ShowKindLabel) const {
- {
- WithColor S(OS, raw_ostream::SAVEDCOLOR, true, false, !ShowColors);
-
- if (ProgName && ProgName[0])
- S << ProgName << ": ";
-
- if (!Filename.empty()) {
- if (Filename == "-")
- S << "<stdin>";
- else
- S << Filename;
-
- if (LineNo != -1) {
- S << ':' << LineNo;
- if (ColumnNo != -1)
- S << ':' << (ColumnNo + 1);
- }
- S << ": ";
- }
- }
-
- if (ShowKindLabel) {
- switch (Kind) {
- case SourceMgr::DK_Error:
- WithColor::error(OS, "", !ShowColors);
- break;
- case SourceMgr::DK_Warning:
- WithColor::warning(OS, "", !ShowColors);
- break;
- case SourceMgr::DK_Note:
- WithColor::note(OS, "", !ShowColors);
- break;
- case SourceMgr::DK_Remark:
- WithColor::remark(OS, "", !ShowColors);
- break;
- }
- }
-
- WithColor(OS, raw_ostream::SAVEDCOLOR, true, false, !ShowColors)
- << Message << '\n';
-
- if (LineNo == -1 || ColumnNo == -1)
- return;
-
- // FIXME: If there are multibyte or multi-column characters in the source, all
- // our ranges will be wrong. To do this properly, we'll need a byte-to-column
- // map like Clang's TextDiagnostic. For now, we'll just handle tabs by
- // expanding them later, and bail out rather than show incorrect ranges and
- // misaligned fixits for any other odd characters.
- if (find_if(LineContents, isNonASCII) != LineContents.end()) {
- printSourceLine(OS, LineContents);
- return;
- }
- size_t NumColumns = LineContents.size();
-
- // Build the line with the caret and ranges.
- std::string CaretLine(NumColumns+1, ' ');
-
- // Expand any ranges.
- for (unsigned r = 0, e = Ranges.size(); r != e; ++r) {
- std::pair<unsigned, unsigned> R = Ranges[r];
- std::fill(&CaretLine[R.first],
- &CaretLine[std::min((size_t)R.second, CaretLine.size())],
- '~');
- }
-
- // Add any fix-its.
- // FIXME: Find the beginning of the line properly for multibyte characters.
- std::string FixItInsertionLine;
- buildFixItLine(CaretLine, FixItInsertionLine, FixIts,
- makeArrayRef(Loc.getPointer() - ColumnNo,
- LineContents.size()));
-
- // Finally, plop on the caret.
- if (unsigned(ColumnNo) <= NumColumns)
- CaretLine[ColumnNo] = '^';
- else
- CaretLine[NumColumns] = '^';
-
- // ... and remove trailing whitespace so the output doesn't wrap for it. We
- // know that the line isn't completely empty because it has the caret in it at
- // least.
- CaretLine.erase(CaretLine.find_last_not_of(' ')+1);
-
- printSourceLine(OS, LineContents);
-
- {
- WithColor S(OS, raw_ostream::GREEN, true, false, !ShowColors);
-
- // Print out the caret line, matching tabs in the source line.
- for (unsigned i = 0, e = CaretLine.size(), OutCol = 0; i != e; ++i) {
- if (i >= LineContents.size() || LineContents[i] != '\t') {
- S << CaretLine[i];
- ++OutCol;
- continue;
- }
-
- // Okay, we have a tab. Insert the appropriate number of characters.
- do {
- S << CaretLine[i];
- ++OutCol;
- } while ((OutCol % TabStop) != 0);
- }
- S << '\n';
- }
-
- // Print out the replacement line, matching tabs in the source line.
- if (FixItInsertionLine.empty())
- return;
-
- for (size_t i = 0, e = FixItInsertionLine.size(), OutCol = 0; i < e; ++i) {
- if (i >= LineContents.size() || LineContents[i] != '\t') {
- OS << FixItInsertionLine[i];
- ++OutCol;
- continue;
- }
-
- // Okay, we have a tab. Insert the appropriate number of characters.
- do {
- OS << FixItInsertionLine[i];
- // FIXME: This is trying not to break up replacements, but then to re-sync
- // with the tabs between replacements. This will fail, though, if two
- // fix-it replacements are exactly adjacent, or if a fix-it contains a
- // space. Really we should be precomputing column widths, which we'll
- // need anyway for multibyte chars.
- if (FixItInsertionLine[i] != ' ')
- ++i;
- ++OutCol;
- } while (((OutCol % TabStop) != 0) && i != e);
- }
- OS << '\n';
-}
diff --git a/gnu/llvm/lib/Support/SpecialCaseList.cpp b/gnu/llvm/lib/Support/SpecialCaseList.cpp
deleted file mode 100644
index bf807e66e02..00000000000
--- a/gnu/llvm/lib/Support/SpecialCaseList.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-//===-- SpecialCaseList.cpp - special case list for sanitizers ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is a utility class for instrumentation passes (like AddressSanitizer
-// or ThreadSanitizer) to avoid instrumenting some functions or global
-// variables, or to instrument some functions or global variables in a specific
-// way, based on a user-supplied list.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/SpecialCaseList.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Regex.h"
-#include <string>
-#include <system_error>
-#include <utility>
-
-#include <stdio.h>
-namespace llvm {
-
-bool SpecialCaseList::Matcher::insert(std::string Regexp,
- unsigned LineNumber,
- std::string &REError) {
- if (Regexp.empty()) {
- REError = "Supplied regexp was blank";
- return false;
- }
-
- if (Regex::isLiteralERE(Regexp)) {
- Strings[Regexp] = LineNumber;
- return true;
- }
- Trigrams.insert(Regexp);
-
- // Replace * with .*
- for (size_t pos = 0; (pos = Regexp.find('*', pos)) != std::string::npos;
- pos += strlen(".*")) {
- Regexp.replace(pos, strlen("*"), ".*");
- }
-
- Regexp = (Twine("^(") + StringRef(Regexp) + ")$").str();
-
- // Check that the regexp is valid.
- Regex CheckRE(Regexp);
- if (!CheckRE.isValid(REError))
- return false;
-
- RegExes.emplace_back(
- std::make_pair(make_unique<Regex>(std::move(CheckRE)), LineNumber));
- return true;
-}
-
-unsigned SpecialCaseList::Matcher::match(StringRef Query) const {
- auto It = Strings.find(Query);
- if (It != Strings.end())
- return It->second;
- if (Trigrams.isDefinitelyOut(Query))
- return false;
- for (auto& RegExKV : RegExes)
- if (RegExKV.first->match(Query))
- return RegExKV.second;
- return 0;
-}
-
-std::unique_ptr<SpecialCaseList>
-SpecialCaseList::create(const std::vector<std::string> &Paths,
- std::string &Error) {
- std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
- if (SCL->createInternal(Paths, Error))
- return SCL;
- return nullptr;
-}
-
-std::unique_ptr<SpecialCaseList> SpecialCaseList::create(const MemoryBuffer *MB,
- std::string &Error) {
- std::unique_ptr<SpecialCaseList> SCL(new SpecialCaseList());
- if (SCL->createInternal(MB, Error))
- return SCL;
- return nullptr;
-}
-
-std::unique_ptr<SpecialCaseList>
-SpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
- std::string Error;
- if (auto SCL = create(Paths, Error))
- return SCL;
- report_fatal_error(Error);
-}
-
-bool SpecialCaseList::createInternal(const std::vector<std::string> &Paths,
- std::string &Error) {
- StringMap<size_t> Sections;
- for (const auto &Path : Paths) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
- MemoryBuffer::getFile(Path);
- if (std::error_code EC = FileOrErr.getError()) {
- Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
- return false;
- }
- std::string ParseError;
- if (!parse(FileOrErr.get().get(), Sections, ParseError)) {
- Error = (Twine("error parsing file '") + Path + "': " + ParseError).str();
- return false;
- }
- }
- return true;
-}
-
-bool SpecialCaseList::createInternal(const MemoryBuffer *MB,
- std::string &Error) {
- StringMap<size_t> Sections;
- if (!parse(MB, Sections, Error))
- return false;
- return true;
-}
-
-bool SpecialCaseList::parse(const MemoryBuffer *MB,
- StringMap<size_t> &SectionsMap,
- std::string &Error) {
- // Iterate through each line in the blacklist file.
- SmallVector<StringRef, 16> Lines;
- MB->getBuffer().split(Lines, '\n');
-
- unsigned LineNo = 1;
- StringRef Section = "*";
-
- for (auto I = Lines.begin(), E = Lines.end(); I != E; ++I, ++LineNo) {
- *I = I->trim();
- // Ignore empty lines and lines starting with "#"
- if (I->empty() || I->startswith("#"))
- continue;
-
- // Save section names
- if (I->startswith("[")) {
- if (!I->endswith("]")) {
- Error = (Twine("malformed section header on line ") + Twine(LineNo) +
- ": " + *I).str();
- return false;
- }
-
- Section = I->slice(1, I->size() - 1);
-
- std::string REError;
- Regex CheckRE(Section);
- if (!CheckRE.isValid(REError)) {
- Error =
- (Twine("malformed regex for section ") + Section + ": '" + REError)
- .str();
- return false;
- }
-
- continue;
- }
-
- // Get our prefix and unparsed regexp.
- std::pair<StringRef, StringRef> SplitLine = I->split(":");
- StringRef Prefix = SplitLine.first;
- if (SplitLine.second.empty()) {
- // Missing ':' in the line.
- Error = (Twine("malformed line ") + Twine(LineNo) + ": '" +
- SplitLine.first + "'").str();
- return false;
- }
-
- std::pair<StringRef, StringRef> SplitRegexp = SplitLine.second.split("=");
- std::string Regexp = SplitRegexp.first;
- StringRef Category = SplitRegexp.second;
-
- // Create this section if it has not been seen before.
- if (SectionsMap.find(Section) == SectionsMap.end()) {
- std::unique_ptr<Matcher> M = make_unique<Matcher>();
- std::string REError;
- if (!M->insert(Section, LineNo, REError)) {
- Error = (Twine("malformed section ") + Section + ": '" + REError).str();
- return false;
- }
-
- SectionsMap[Section] = Sections.size();
- Sections.emplace_back(std::move(M));
- }
-
- auto &Entry = Sections[SectionsMap[Section]].Entries[Prefix][Category];
- std::string REError;
- if (!Entry.insert(std::move(Regexp), LineNo, REError)) {
- Error = (Twine("malformed regex in line ") + Twine(LineNo) + ": '" +
- SplitLine.second + "': " + REError).str();
- return false;
- }
- }
- return true;
-}
-
-SpecialCaseList::~SpecialCaseList() {}
-
-bool SpecialCaseList::inSection(StringRef Section, StringRef Prefix,
- StringRef Query, StringRef Category) const {
- return inSectionBlame(Section, Prefix, Query, Category);
-}
-
-unsigned SpecialCaseList::inSectionBlame(StringRef Section, StringRef Prefix,
- StringRef Query,
- StringRef Category) const {
- for (auto &SectionIter : Sections)
- if (SectionIter.SectionMatcher->match(Section)) {
- unsigned Blame =
- inSectionBlame(SectionIter.Entries, Prefix, Query, Category);
- if (Blame)
- return Blame;
- }
- return 0;
-}
-
-unsigned SpecialCaseList::inSectionBlame(const SectionEntries &Entries,
- StringRef Prefix, StringRef Query,
- StringRef Category) const {
- SectionEntries::const_iterator I = Entries.find(Prefix);
- if (I == Entries.end()) return 0;
- StringMap<Matcher>::const_iterator II = I->second.find(Category);
- if (II == I->second.end()) return 0;
-
- return II->getValue().match(Query);
-}
-
-} // namespace llvm
diff --git a/gnu/llvm/lib/Support/Statistic.cpp b/gnu/llvm/lib/Support/Statistic.cpp
deleted file mode 100644
index d57300a75d1..00000000000
--- a/gnu/llvm/lib/Support/Statistic.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-//===-- Statistic.cpp - Easy way to expose stats information --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the 'Statistic' class, which is designed to be an easy
-// way to expose various success metrics from passes. These statistics are
-// printed at the end of a run, when the -stats command line option is enabled
-// on the command line.
-//
-// This is useful for reporting information like the number of instructions
-// simplified, optimized or removed by various transformations, like this:
-//
-// static Statistic NumInstEliminated("GCSE", "Number of instructions killed");
-//
-// Later, in the code: ++NumInstEliminated;
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/Timer.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cstring>
-using namespace llvm;
-
-/// -stats - Command line option to cause transformations to emit stats about
-/// what they did.
-///
-static cl::opt<bool> Stats(
- "stats",
- cl::desc("Enable statistics output from program (available with Asserts)"),
- cl::Hidden);
-
-static cl::opt<bool> StatsAsJSON("stats-json",
- cl::desc("Display statistics as json data"),
- cl::Hidden);
-
-static bool Enabled;
-static bool PrintOnExit;
-
-namespace {
-/// This class is used in a ManagedStatic so that it is created on demand (when
-/// the first statistic is bumped) and destroyed only when llvm_shutdown is
-/// called. We print statistics from the destructor.
-/// This class is also used to look up statistic values from applications that
-/// use LLVM.
-class StatisticInfo {
- std::vector<Statistic*> Stats;
-
- friend void llvm::PrintStatistics();
- friend void llvm::PrintStatistics(raw_ostream &OS);
- friend void llvm::PrintStatisticsJSON(raw_ostream &OS);
-
- /// Sort statistics by debugtype,name,description.
- void sort();
-public:
- using const_iterator = std::vector<Statistic *>::const_iterator;
-
- StatisticInfo();
- ~StatisticInfo();
-
- void addStatistic(Statistic *S) {
- Stats.push_back(S);
- }
-
- const_iterator begin() const { return Stats.begin(); }
- const_iterator end() const { return Stats.end(); }
- iterator_range<const_iterator> statistics() const {
- return {begin(), end()};
- }
-
- void reset();
-};
-} // end anonymous namespace
-
-static ManagedStatic<StatisticInfo> StatInfo;
-static ManagedStatic<sys::SmartMutex<true> > StatLock;
-
-/// RegisterStatistic - The first time a statistic is bumped, this method is
-/// called.
-void Statistic::RegisterStatistic() {
- // If stats are enabled, inform StatInfo that this statistic should be
- // printed.
- // llvm_shutdown calls destructors while holding the ManagedStatic mutex.
- // These destructors end up calling PrintStatistics, which takes StatLock.
- // Since dereferencing StatInfo and StatLock can require taking the
- // ManagedStatic mutex, doing so with StatLock held would lead to a lock
- // order inversion. To avoid that, we dereference the ManagedStatics first,
- // and only take StatLock afterwards.
- if (!Initialized.load(std::memory_order_relaxed)) {
- sys::SmartMutex<true> &Lock = *StatLock;
- StatisticInfo &SI = *StatInfo;
- sys::SmartScopedLock<true> Writer(Lock);
- // Check Initialized again after acquiring the lock.
- if (Initialized.load(std::memory_order_relaxed))
- return;
- if (Stats || Enabled)
- SI.addStatistic(this);
-
- // Remember we have been registered.
- Initialized.store(true, std::memory_order_release);
- }
-}
-
-StatisticInfo::StatisticInfo() {
- // Ensure timergroup lists are created first so they are destructed after us.
- TimerGroup::ConstructTimerLists();
-}
-
-// Print information when destroyed, iff command line option is specified.
-StatisticInfo::~StatisticInfo() {
- if (::Stats || PrintOnExit)
- llvm::PrintStatistics();
-}
-
-void llvm::EnableStatistics(bool PrintOnExit) {
- Enabled = true;
- ::PrintOnExit = PrintOnExit;
-}
-
-bool llvm::AreStatisticsEnabled() {
- return Enabled || Stats;
-}
-
-void StatisticInfo::sort() {
- std::stable_sort(Stats.begin(), Stats.end(),
- [](const Statistic *LHS, const Statistic *RHS) {
- if (int Cmp = std::strcmp(LHS->getDebugType(), RHS->getDebugType()))
- return Cmp < 0;
-
- if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
- return Cmp < 0;
-
- return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
- });
-}
-
-void StatisticInfo::reset() {
- sys::SmartScopedLock<true> Writer(*StatLock);
-
- // Tell each statistic that it isn't registered so it has to register
- // again. We're holding the lock so it won't be able to do so until we're
- // finished. Once we've forced it to re-register (after we return), then zero
- // the value.
- for (auto *Stat : Stats) {
- // Value updates to a statistic that complete before this statement in the
- // iteration for that statistic will be lost as intended.
- Stat->Initialized = false;
- Stat->Value = 0;
- }
-
- // Clear the registration list and release the lock once we're done. Any
- // pending updates from other threads will safely take effect after we return.
- // That might not be what the user wants if they're measuring a compilation
- // but it's their responsibility to prevent concurrent compilations to make
- // a single compilation measurable.
- Stats.clear();
-}
-
-void llvm::PrintStatistics(raw_ostream &OS) {
- StatisticInfo &Stats = *StatInfo;
-
- // Figure out how long the biggest Value and Name fields are.
- unsigned MaxDebugTypeLen = 0, MaxValLen = 0;
- for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) {
- MaxValLen = std::max(MaxValLen,
- (unsigned)utostr(Stats.Stats[i]->getValue()).size());
- MaxDebugTypeLen = std::max(MaxDebugTypeLen,
- (unsigned)std::strlen(Stats.Stats[i]->getDebugType()));
- }
-
- Stats.sort();
-
- // Print out the statistics header...
- OS << "===" << std::string(73, '-') << "===\n"
- << " ... Statistics Collected ...\n"
- << "===" << std::string(73, '-') << "===\n\n";
-
- // Print all of the statistics.
- for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i)
- OS << format("%*u %-*s - %s\n",
- MaxValLen, Stats.Stats[i]->getValue(),
- MaxDebugTypeLen, Stats.Stats[i]->getDebugType(),
- Stats.Stats[i]->getDesc());
-
- OS << '\n'; // Flush the output stream.
- OS.flush();
-}
-
-void llvm::PrintStatisticsJSON(raw_ostream &OS) {
- sys::SmartScopedLock<true> Reader(*StatLock);
- StatisticInfo &Stats = *StatInfo;
-
- Stats.sort();
-
- // Print all of the statistics.
- OS << "{\n";
- const char *delim = "";
- for (const Statistic *Stat : Stats.Stats) {
- OS << delim;
- assert(yaml::needsQuotes(Stat->getDebugType()) == yaml::QuotingType::None &&
- "Statistic group/type name is simple.");
- assert(yaml::needsQuotes(Stat->getName()) == yaml::QuotingType::None &&
- "Statistic name is simple");
- OS << "\t\"" << Stat->getDebugType() << '.' << Stat->getName() << "\": "
- << Stat->getValue();
- delim = ",\n";
- }
- // Print timers.
- TimerGroup::printAllJSONValues(OS, delim);
-
- OS << "\n}\n";
- OS.flush();
-}
-
-void llvm::PrintStatistics() {
-#if LLVM_ENABLE_STATS
- sys::SmartScopedLock<true> Reader(*StatLock);
- StatisticInfo &Stats = *StatInfo;
-
- // Statistics not enabled?
- if (Stats.Stats.empty()) return;
-
- // Get the stream to write to.
- std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
- if (StatsAsJSON)
- PrintStatisticsJSON(*OutStream);
- else
- PrintStatistics(*OutStream);
-
-#else
- // Check if the -stats option is set instead of checking
- // !Stats.Stats.empty(). In release builds, Statistics operators
- // do nothing, so stats are never Registered.
- if (Stats) {
- // Get the stream to write to.
- std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
- (*OutStream) << "Statistics are disabled. "
- << "Build with asserts or with -DLLVM_ENABLE_STATS\n";
- }
-#endif
-}
-
-const std::vector<std::pair<StringRef, unsigned>> llvm::GetStatistics() {
- sys::SmartScopedLock<true> Reader(*StatLock);
- std::vector<std::pair<StringRef, unsigned>> ReturnStats;
-
- for (const auto &Stat : StatInfo->statistics())
- ReturnStats.emplace_back(Stat->getName(), Stat->getValue());
- return ReturnStats;
-}
-
-void llvm::ResetStatistics() {
- StatInfo->reset();
-}
diff --git a/gnu/llvm/lib/Support/StringExtras.cpp b/gnu/llvm/lib/Support/StringExtras.cpp
deleted file mode 100644
index 386d74a4798..00000000000
--- a/gnu/llvm/lib/Support/StringExtras.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-//===-- StringExtras.cpp - Implement the StringExtras header --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the StringExtras.h header
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-/// StrInStrNoCase - Portable version of strcasestr. Locates the first
-/// occurrence of string 's1' in string 's2', ignoring case. Returns
-/// the offset of s2 in s1 or npos if s2 cannot be found.
-StringRef::size_type llvm::StrInStrNoCase(StringRef s1, StringRef s2) {
- size_t N = s2.size(), M = s1.size();
- if (N > M)
- return StringRef::npos;
- for (size_t i = 0, e = M - N + 1; i != e; ++i)
- if (s1.substr(i, N).equals_lower(s2))
- return i;
- return StringRef::npos;
-}
-
-/// getToken - This function extracts one token from source, ignoring any
-/// leading characters that appear in the Delimiters string, and ending the
-/// token at any of the characters that appear in the Delimiters string. If
-/// there are no tokens in the source string, an empty string is returned.
-/// The function returns a pair containing the extracted token and the
-/// remaining tail string.
-std::pair<StringRef, StringRef> llvm::getToken(StringRef Source,
- StringRef Delimiters) {
- // Figure out where the token starts.
- StringRef::size_type Start = Source.find_first_not_of(Delimiters);
-
- // Find the next occurrence of the delimiter.
- StringRef::size_type End = Source.find_first_of(Delimiters, Start);
-
- return std::make_pair(Source.slice(Start, End), Source.substr(End));
-}
-
-/// SplitString - Split up the specified string according to the specified
-/// delimiters, appending the result fragments to the output list.
-void llvm::SplitString(StringRef Source,
- SmallVectorImpl<StringRef> &OutFragments,
- StringRef Delimiters) {
- std::pair<StringRef, StringRef> S = getToken(Source, Delimiters);
- while (!S.first.empty()) {
- OutFragments.push_back(S.first);
- S = getToken(S.second, Delimiters);
- }
-}
-
-void llvm::printEscapedString(StringRef Name, raw_ostream &Out) {
- for (unsigned i = 0, e = Name.size(); i != e; ++i) {
- unsigned char C = Name[i];
- if (isPrint(C) && C != '\\' && C != '"')
- Out << C;
- else
- Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
- }
-}
-
-void llvm::printHTMLEscaped(StringRef String, raw_ostream &Out) {
- for (char C : String) {
- if (C == '&')
- Out << "&amp;";
- else if (C == '<')
- Out << "&lt;";
- else if (C == '>')
- Out << "&gt;";
- else if (C == '\"')
- Out << "&quot;";
- else if (C == '\'')
- Out << "&apos;";
- else
- Out << C;
- }
-}
-
-void llvm::printLowerCase(StringRef String, raw_ostream &Out) {
- for (const char C : String)
- Out << toLower(C);
-}
diff --git a/gnu/llvm/lib/Support/StringMap.cpp b/gnu/llvm/lib/Support/StringMap.cpp
deleted file mode 100644
index c1f707ce50a..00000000000
--- a/gnu/llvm/lib/Support/StringMap.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-//===--- StringMap.cpp - String Hash table map implementation -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the StringMap class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DJB.h"
-#include "llvm/Support/MathExtras.h"
-#include <cassert>
-
-using namespace llvm;
-
-/// Returns the number of buckets to allocate to ensure that the DenseMap can
-/// accommodate \p NumEntries without need to grow().
-static unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
- // Ensure that "NumEntries * 4 < NumBuckets * 3"
- if (NumEntries == 0)
- return 0;
- // +1 is required because of the strict equality.
- // For example if NumEntries is 48, we need to return 401.
- return NextPowerOf2(NumEntries * 4 / 3 + 1);
-}
-
-StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) {
- ItemSize = itemSize;
-
- // If a size is specified, initialize the table with that many buckets.
- if (InitSize) {
- // The table will grow when the number of entries reach 3/4 of the number of
- // buckets. To guarantee that "InitSize" number of entries can be inserted
- // in the table without growing, we allocate just what is needed here.
- init(getMinBucketToReserveForEntries(InitSize));
- return;
- }
-
- // Otherwise, initialize it with zero buckets to avoid the allocation.
- TheTable = nullptr;
- NumBuckets = 0;
- NumItems = 0;
- NumTombstones = 0;
-}
-
-void StringMapImpl::init(unsigned InitSize) {
- assert((InitSize & (InitSize-1)) == 0 &&
- "Init Size must be a power of 2 or zero!");
-
- unsigned NewNumBuckets = InitSize ? InitSize : 16;
- NumItems = 0;
- NumTombstones = 0;
-
- TheTable = static_cast<StringMapEntryBase **>(
- safe_calloc(NewNumBuckets+1,
- sizeof(StringMapEntryBase **) + sizeof(unsigned)));
-
- // Set the member only if TheTable was successfully allocated
- NumBuckets = NewNumBuckets;
-
- // Allocate one extra bucket, set it to look filled so the iterators stop at
- // end.
- TheTable[NumBuckets] = (StringMapEntryBase*)2;
-}
-
-/// LookupBucketFor - Look up the bucket that the specified string should end
-/// up in. If it already exists as a key in the map, the Item pointer for the
-/// specified bucket will be non-null. Otherwise, it will be null. In either
-/// case, the FullHashValue field of the bucket will be set to the hash value
-/// of the string.
-unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
- unsigned HTSize = NumBuckets;
- if (HTSize == 0) { // Hash table unallocated so far?
- init(16);
- HTSize = NumBuckets;
- }
- unsigned FullHashValue = djbHash(Name, 0);
- unsigned BucketNo = FullHashValue & (HTSize-1);
- unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
-
- unsigned ProbeAmt = 1;
- int FirstTombstone = -1;
- while (true) {
- StringMapEntryBase *BucketItem = TheTable[BucketNo];
- // If we found an empty bucket, this key isn't in the table yet, return it.
- if (LLVM_LIKELY(!BucketItem)) {
- // If we found a tombstone, we want to reuse the tombstone instead of an
- // empty bucket. This reduces probing.
- if (FirstTombstone != -1) {
- HashTable[FirstTombstone] = FullHashValue;
- return FirstTombstone;
- }
-
- HashTable[BucketNo] = FullHashValue;
- return BucketNo;
- }
-
- if (BucketItem == getTombstoneVal()) {
- // Skip over tombstones. However, remember the first one we see.
- if (FirstTombstone == -1) FirstTombstone = BucketNo;
- } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) {
- // If the full hash value matches, check deeply for a match. The common
- // case here is that we are only looking at the buckets (for item info
- // being non-null and for the full hash value) not at the items. This
- // is important for cache locality.
-
- // Do the comparison like this because Name isn't necessarily
- // null-terminated!
- char *ItemStr = (char*)BucketItem+ItemSize;
- if (Name == StringRef(ItemStr, BucketItem->getKeyLength())) {
- // We found a match!
- return BucketNo;
- }
- }
-
- // Okay, we didn't find the item. Probe to the next bucket.
- BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
-
- // Use quadratic probing, it has fewer clumping artifacts than linear
- // probing and has good cache behavior in the common case.
- ++ProbeAmt;
- }
-}
-
-/// FindKey - Look up the bucket that contains the specified key. If it exists
-/// in the map, return the bucket number of the key. Otherwise return -1.
-/// This does not modify the map.
-int StringMapImpl::FindKey(StringRef Key) const {
- unsigned HTSize = NumBuckets;
- if (HTSize == 0) return -1; // Really empty table?
- unsigned FullHashValue = djbHash(Key, 0);
- unsigned BucketNo = FullHashValue & (HTSize-1);
- unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
-
- unsigned ProbeAmt = 1;
- while (true) {
- StringMapEntryBase *BucketItem = TheTable[BucketNo];
- // If we found an empty bucket, this key isn't in the table yet, return.
- if (LLVM_LIKELY(!BucketItem))
- return -1;
-
- if (BucketItem == getTombstoneVal()) {
- // Ignore tombstones.
- } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) {
- // If the full hash value matches, check deeply for a match. The common
- // case here is that we are only looking at the buckets (for item info
- // being non-null and for the full hash value) not at the items. This
- // is important for cache locality.
-
- // Do the comparison like this because NameStart isn't necessarily
- // null-terminated!
- char *ItemStr = (char*)BucketItem+ItemSize;
- if (Key == StringRef(ItemStr, BucketItem->getKeyLength())) {
- // We found a match!
- return BucketNo;
- }
- }
-
- // Okay, we didn't find the item. Probe to the next bucket.
- BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
-
- // Use quadratic probing, it has fewer clumping artifacts than linear
- // probing and has good cache behavior in the common case.
- ++ProbeAmt;
- }
-}
-
-/// RemoveKey - Remove the specified StringMapEntry from the table, but do not
-/// delete it. This aborts if the value isn't in the table.
-void StringMapImpl::RemoveKey(StringMapEntryBase *V) {
- const char *VStr = (char*)V + ItemSize;
- StringMapEntryBase *V2 = RemoveKey(StringRef(VStr, V->getKeyLength()));
- (void)V2;
- assert(V == V2 && "Didn't find key?");
-}
-
-/// RemoveKey - Remove the StringMapEntry for the specified key from the
-/// table, returning it. If the key is not in the table, this returns null.
-StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) {
- int Bucket = FindKey(Key);
- if (Bucket == -1) return nullptr;
-
- StringMapEntryBase *Result = TheTable[Bucket];
- TheTable[Bucket] = getTombstoneVal();
- --NumItems;
- ++NumTombstones;
- assert(NumItems + NumTombstones <= NumBuckets);
-
- return Result;
-}
-
-/// RehashTable - Grow the table, redistributing values into the buckets with
-/// the appropriate mod-of-hashtable-size.
-unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
- unsigned NewSize;
- unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
-
- // If the hash table is now more than 3/4 full, or if fewer than 1/8 of
- // the buckets are empty (meaning that many are filled with tombstones),
- // grow/rehash the table.
- if (LLVM_UNLIKELY(NumItems * 4 > NumBuckets * 3)) {
- NewSize = NumBuckets*2;
- } else if (LLVM_UNLIKELY(NumBuckets - (NumItems + NumTombstones) <=
- NumBuckets / 8)) {
- NewSize = NumBuckets;
- } else {
- return BucketNo;
- }
-
- unsigned NewBucketNo = BucketNo;
- // Allocate one extra bucket which will always be non-empty. This allows the
- // iterators to stop at end.
- auto NewTableArray = static_cast<StringMapEntryBase **>(
- safe_calloc(NewSize+1, sizeof(StringMapEntryBase *) + sizeof(unsigned)));
-
- unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1);
- NewTableArray[NewSize] = (StringMapEntryBase*)2;
-
- // Rehash all the items into their new buckets. Luckily :) we already have
- // the hash values available, so we don't have to rehash any strings.
- for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
- StringMapEntryBase *Bucket = TheTable[I];
- if (Bucket && Bucket != getTombstoneVal()) {
- // Fast case, bucket available.
- unsigned FullHash = HashTable[I];
- unsigned NewBucket = FullHash & (NewSize-1);
- if (!NewTableArray[NewBucket]) {
- NewTableArray[FullHash & (NewSize-1)] = Bucket;
- NewHashArray[FullHash & (NewSize-1)] = FullHash;
- if (I == BucketNo)
- NewBucketNo = NewBucket;
- continue;
- }
-
- // Otherwise probe for a spot.
- unsigned ProbeSize = 1;
- do {
- NewBucket = (NewBucket + ProbeSize++) & (NewSize-1);
- } while (NewTableArray[NewBucket]);
-
- // Finally found a slot. Fill it in.
- NewTableArray[NewBucket] = Bucket;
- NewHashArray[NewBucket] = FullHash;
- if (I == BucketNo)
- NewBucketNo = NewBucket;
- }
- }
-
- free(TheTable);
-
- TheTable = NewTableArray;
- NumBuckets = NewSize;
- NumTombstones = 0;
- return NewBucketNo;
-}
diff --git a/gnu/llvm/lib/Support/StringPool.cpp b/gnu/llvm/lib/Support/StringPool.cpp
deleted file mode 100644
index c591857c415..00000000000
--- a/gnu/llvm/lib/Support/StringPool.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//===-- StringPool.cpp - Interned string pool -----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the StringPool class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/StringPool.h"
-#include "llvm/ADT/StringRef.h"
-
-using namespace llvm;
-
-StringPool::StringPool() {}
-
-StringPool::~StringPool() {
- assert(InternTable.empty() && "PooledStringPtr leaked!");
-}
-
-PooledStringPtr StringPool::intern(StringRef Key) {
- table_t::iterator I = InternTable.find(Key);
- if (I != InternTable.end())
- return PooledStringPtr(&*I);
-
- entry_t *S = entry_t::Create(Key);
- S->getValue().Pool = this;
- InternTable.insert(S);
-
- return PooledStringPtr(S);
-}
diff --git a/gnu/llvm/lib/Support/StringRef.cpp b/gnu/llvm/lib/Support/StringRef.cpp
deleted file mode 100644
index f0349260e22..00000000000
--- a/gnu/llvm/lib/Support/StringRef.cpp
+++ /dev/null
@@ -1,600 +0,0 @@
-//===-- StringRef.cpp - Lightweight String References ---------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/edit_distance.h"
-#include <bitset>
-
-using namespace llvm;
-
-// MSVC emits references to this into the translation units which reference it.
-#ifndef _MSC_VER
-const size_t StringRef::npos;
-#endif
-
-// strncasecmp() is not available on non-POSIX systems, so define an
-// alternative function here.
-static int ascii_strncasecmp(const char *LHS, const char *RHS, size_t Length) {
- for (size_t I = 0; I < Length; ++I) {
- unsigned char LHC = toLower(LHS[I]);
- unsigned char RHC = toLower(RHS[I]);
- if (LHC != RHC)
- return LHC < RHC ? -1 : 1;
- }
- return 0;
-}
-
-/// compare_lower - Compare strings, ignoring case.
-int StringRef::compare_lower(StringRef RHS) const {
- if (int Res = ascii_strncasecmp(Data, RHS.Data, std::min(Length, RHS.Length)))
- return Res;
- if (Length == RHS.Length)
- return 0;
- return Length < RHS.Length ? -1 : 1;
-}
-
-/// Check if this string starts with the given \p Prefix, ignoring case.
-bool StringRef::startswith_lower(StringRef Prefix) const {
- return Length >= Prefix.Length &&
- ascii_strncasecmp(Data, Prefix.Data, Prefix.Length) == 0;
-}
-
-/// Check if this string ends with the given \p Suffix, ignoring case.
-bool StringRef::endswith_lower(StringRef Suffix) const {
- return Length >= Suffix.Length &&
- ascii_strncasecmp(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0;
-}
-
-size_t StringRef::find_lower(char C, size_t From) const {
- char L = toLower(C);
- return find_if([L](char D) { return toLower(D) == L; }, From);
-}
-
-/// compare_numeric - Compare strings, handle embedded numbers.
-int StringRef::compare_numeric(StringRef RHS) const {
- for (size_t I = 0, E = std::min(Length, RHS.Length); I != E; ++I) {
- // Check for sequences of digits.
- if (isDigit(Data[I]) && isDigit(RHS.Data[I])) {
- // The longer sequence of numbers is considered larger.
- // This doesn't really handle prefixed zeros well.
- size_t J;
- for (J = I + 1; J != E + 1; ++J) {
- bool ld = J < Length && isDigit(Data[J]);
- bool rd = J < RHS.Length && isDigit(RHS.Data[J]);
- if (ld != rd)
- return rd ? -1 : 1;
- if (!rd)
- break;
- }
- // The two number sequences have the same length (J-I), just memcmp them.
- if (int Res = compareMemory(Data + I, RHS.Data + I, J - I))
- return Res < 0 ? -1 : 1;
- // Identical number sequences, continue search after the numbers.
- I = J - 1;
- continue;
- }
- if (Data[I] != RHS.Data[I])
- return (unsigned char)Data[I] < (unsigned char)RHS.Data[I] ? -1 : 1;
- }
- if (Length == RHS.Length)
- return 0;
- return Length < RHS.Length ? -1 : 1;
-}
-
-// Compute the edit distance between the two given strings.
-unsigned StringRef::edit_distance(llvm::StringRef Other,
- bool AllowReplacements,
- unsigned MaxEditDistance) const {
- return llvm::ComputeEditDistance(
- makeArrayRef(data(), size()),
- makeArrayRef(Other.data(), Other.size()),
- AllowReplacements, MaxEditDistance);
-}
-
-//===----------------------------------------------------------------------===//
-// String Operations
-//===----------------------------------------------------------------------===//
-
-std::string StringRef::lower() const {
- std::string Result(size(), char());
- for (size_type i = 0, e = size(); i != e; ++i) {
- Result[i] = toLower(Data[i]);
- }
- return Result;
-}
-
-std::string StringRef::upper() const {
- std::string Result(size(), char());
- for (size_type i = 0, e = size(); i != e; ++i) {
- Result[i] = toUpper(Data[i]);
- }
- return Result;
-}
-
-//===----------------------------------------------------------------------===//
-// String Searching
-//===----------------------------------------------------------------------===//
-
-
-/// find - Search for the first string \arg Str in the string.
-///
-/// \return - The index of the first occurrence of \arg Str, or npos if not
-/// found.
-size_t StringRef::find(StringRef Str, size_t From) const {
- if (From > Length)
- return npos;
-
- const char *Start = Data + From;
- size_t Size = Length - From;
-
- const char *Needle = Str.data();
- size_t N = Str.size();
- if (N == 0)
- return From;
- if (Size < N)
- return npos;
- if (N == 1) {
- const char *Ptr = (const char *)::memchr(Start, Needle[0], Size);
- return Ptr == nullptr ? npos : Ptr - Data;
- }
-
- const char *Stop = Start + (Size - N + 1);
-
- // For short haystacks or unsupported needles fall back to the naive algorithm
- if (Size < 16 || N > 255) {
- do {
- if (std::memcmp(Start, Needle, N) == 0)
- return Start - Data;
- ++Start;
- } while (Start < Stop);
- return npos;
- }
-
- // Build the bad char heuristic table, with uint8_t to reduce cache thrashing.
- uint8_t BadCharSkip[256];
- std::memset(BadCharSkip, N, 256);
- for (unsigned i = 0; i != N-1; ++i)
- BadCharSkip[(uint8_t)Str[i]] = N-1-i;
-
- do {
- uint8_t Last = Start[N - 1];
- if (LLVM_UNLIKELY(Last == (uint8_t)Needle[N - 1]))
- if (std::memcmp(Start, Needle, N - 1) == 0)
- return Start - Data;
-
- // Otherwise skip the appropriate number of bytes.
- Start += BadCharSkip[Last];
- } while (Start < Stop);
-
- return npos;
-}
-
-size_t StringRef::find_lower(StringRef Str, size_t From) const {
- StringRef This = substr(From);
- while (This.size() >= Str.size()) {
- if (This.startswith_lower(Str))
- return From;
- This = This.drop_front();
- ++From;
- }
- return npos;
-}
-
-size_t StringRef::rfind_lower(char C, size_t From) const {
- From = std::min(From, Length);
- size_t i = From;
- while (i != 0) {
- --i;
- if (toLower(Data[i]) == toLower(C))
- return i;
- }
- return npos;
-}
-
-/// rfind - Search for the last string \arg Str in the string.
-///
-/// \return - The index of the last occurrence of \arg Str, or npos if not
-/// found.
-size_t StringRef::rfind(StringRef Str) const {
- size_t N = Str.size();
- if (N > Length)
- return npos;
- for (size_t i = Length - N + 1, e = 0; i != e;) {
- --i;
- if (substr(i, N).equals(Str))
- return i;
- }
- return npos;
-}
-
-size_t StringRef::rfind_lower(StringRef Str) const {
- size_t N = Str.size();
- if (N > Length)
- return npos;
- for (size_t i = Length - N + 1, e = 0; i != e;) {
- --i;
- if (substr(i, N).equals_lower(Str))
- return i;
- }
- return npos;
-}
-
-/// find_first_of - Find the first character in the string that is in \arg
-/// Chars, or npos if not found.
-///
-/// Note: O(size() + Chars.size())
-StringRef::size_type StringRef::find_first_of(StringRef Chars,
- size_t From) const {
- std::bitset<1 << CHAR_BIT> CharBits;
- for (size_type i = 0; i != Chars.size(); ++i)
- CharBits.set((unsigned char)Chars[i]);
-
- for (size_type i = std::min(From, Length), e = Length; i != e; ++i)
- if (CharBits.test((unsigned char)Data[i]))
- return i;
- return npos;
-}
-
-/// find_first_not_of - Find the first character in the string that is not
-/// \arg C or npos if not found.
-StringRef::size_type StringRef::find_first_not_of(char C, size_t From) const {
- for (size_type i = std::min(From, Length), e = Length; i != e; ++i)
- if (Data[i] != C)
- return i;
- return npos;
-}
-
-/// find_first_not_of - Find the first character in the string that is not
-/// in the string \arg Chars, or npos if not found.
-///
-/// Note: O(size() + Chars.size())
-StringRef::size_type StringRef::find_first_not_of(StringRef Chars,
- size_t From) const {
- std::bitset<1 << CHAR_BIT> CharBits;
- for (size_type i = 0; i != Chars.size(); ++i)
- CharBits.set((unsigned char)Chars[i]);
-
- for (size_type i = std::min(From, Length), e = Length; i != e; ++i)
- if (!CharBits.test((unsigned char)Data[i]))
- return i;
- return npos;
-}
-
-/// find_last_of - Find the last character in the string that is in \arg C,
-/// or npos if not found.
-///
-/// Note: O(size() + Chars.size())
-StringRef::size_type StringRef::find_last_of(StringRef Chars,
- size_t From) const {
- std::bitset<1 << CHAR_BIT> CharBits;
- for (size_type i = 0; i != Chars.size(); ++i)
- CharBits.set((unsigned char)Chars[i]);
-
- for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i)
- if (CharBits.test((unsigned char)Data[i]))
- return i;
- return npos;
-}
-
-/// find_last_not_of - Find the last character in the string that is not
-/// \arg C, or npos if not found.
-StringRef::size_type StringRef::find_last_not_of(char C, size_t From) const {
- for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i)
- if (Data[i] != C)
- return i;
- return npos;
-}
-
-/// find_last_not_of - Find the last character in the string that is not in
-/// \arg Chars, or npos if not found.
-///
-/// Note: O(size() + Chars.size())
-StringRef::size_type StringRef::find_last_not_of(StringRef Chars,
- size_t From) const {
- std::bitset<1 << CHAR_BIT> CharBits;
- for (size_type i = 0, e = Chars.size(); i != e; ++i)
- CharBits.set((unsigned char)Chars[i]);
-
- for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i)
- if (!CharBits.test((unsigned char)Data[i]))
- return i;
- return npos;
-}
-
-void StringRef::split(SmallVectorImpl<StringRef> &A,
- StringRef Separator, int MaxSplit,
- bool KeepEmpty) const {
- StringRef S = *this;
-
- // Count down from MaxSplit. When MaxSplit is -1, this will just split
- // "forever". This doesn't support splitting more than 2^31 times
- // intentionally; if we ever want that we can make MaxSplit a 64-bit integer
- // but that seems unlikely to be useful.
- while (MaxSplit-- != 0) {
- size_t Idx = S.find(Separator);
- if (Idx == npos)
- break;
-
- // Push this split.
- if (KeepEmpty || Idx > 0)
- A.push_back(S.slice(0, Idx));
-
- // Jump forward.
- S = S.slice(Idx + Separator.size(), npos);
- }
-
- // Push the tail.
- if (KeepEmpty || !S.empty())
- A.push_back(S);
-}
-
-void StringRef::split(SmallVectorImpl<StringRef> &A, char Separator,
- int MaxSplit, bool KeepEmpty) const {
- StringRef S = *this;
-
- // Count down from MaxSplit. When MaxSplit is -1, this will just split
- // "forever". This doesn't support splitting more than 2^31 times
- // intentionally; if we ever want that we can make MaxSplit a 64-bit integer
- // but that seems unlikely to be useful.
- while (MaxSplit-- != 0) {
- size_t Idx = S.find(Separator);
- if (Idx == npos)
- break;
-
- // Push this split.
- if (KeepEmpty || Idx > 0)
- A.push_back(S.slice(0, Idx));
-
- // Jump forward.
- S = S.slice(Idx + 1, npos);
- }
-
- // Push the tail.
- if (KeepEmpty || !S.empty())
- A.push_back(S);
-}
-
-//===----------------------------------------------------------------------===//
-// Helpful Algorithms
-//===----------------------------------------------------------------------===//
-
-/// count - Return the number of non-overlapped occurrences of \arg Str in
-/// the string.
-size_t StringRef::count(StringRef Str) const {
- size_t Count = 0;
- size_t N = Str.size();
- if (N > Length)
- return 0;
- for (size_t i = 0, e = Length - N + 1; i != e; ++i)
- if (substr(i, N).equals(Str))
- ++Count;
- return Count;
-}
-
-static unsigned GetAutoSenseRadix(StringRef &Str) {
- if (Str.empty())
- return 10;
-
- if (Str.startswith("0x") || Str.startswith("0X")) {
- Str = Str.substr(2);
- return 16;
- }
-
- if (Str.startswith("0b") || Str.startswith("0B")) {
- Str = Str.substr(2);
- return 2;
- }
-
- if (Str.startswith("0o")) {
- Str = Str.substr(2);
- return 8;
- }
-
- if (Str[0] == '0' && Str.size() > 1 && isDigit(Str[1])) {
- Str = Str.substr(1);
- return 8;
- }
-
- return 10;
-}
-
-bool llvm::consumeUnsignedInteger(StringRef &Str, unsigned Radix,
- unsigned long long &Result) {
- // Autosense radix if not specified.
- if (Radix == 0)
- Radix = GetAutoSenseRadix(Str);
-
- // Empty strings (after the radix autosense) are invalid.
- if (Str.empty()) return true;
-
- // Parse all the bytes of the string given this radix. Watch for overflow.
- StringRef Str2 = Str;
- Result = 0;
- while (!Str2.empty()) {
- unsigned CharVal;
- if (Str2[0] >= '0' && Str2[0] <= '9')
- CharVal = Str2[0] - '0';
- else if (Str2[0] >= 'a' && Str2[0] <= 'z')
- CharVal = Str2[0] - 'a' + 10;
- else if (Str2[0] >= 'A' && Str2[0] <= 'Z')
- CharVal = Str2[0] - 'A' + 10;
- else
- break;
-
- // If the parsed value is larger than the integer radix, we cannot
- // consume any more characters.
- if (CharVal >= Radix)
- break;
-
- // Add in this character.
- unsigned long long PrevResult = Result;
- Result = Result * Radix + CharVal;
-
- // Check for overflow by shifting back and seeing if bits were lost.
- if (Result / Radix < PrevResult)
- return true;
-
- Str2 = Str2.substr(1);
- }
-
- // We consider the operation a failure if no characters were consumed
- // successfully.
- if (Str.size() == Str2.size())
- return true;
-
- Str = Str2;
- return false;
-}
-
-bool llvm::consumeSignedInteger(StringRef &Str, unsigned Radix,
- long long &Result) {
- unsigned long long ULLVal;
-
- // Handle positive strings first.
- if (Str.empty() || Str.front() != '-') {
- if (consumeUnsignedInteger(Str, Radix, ULLVal) ||
- // Check for value so large it overflows a signed value.
- (long long)ULLVal < 0)
- return true;
- Result = ULLVal;
- return false;
- }
-
- // Get the positive part of the value.
- StringRef Str2 = Str.drop_front(1);
- if (consumeUnsignedInteger(Str2, Radix, ULLVal) ||
- // Reject values so large they'd overflow as negative signed, but allow
- // "-0". This negates the unsigned so that the negative isn't undefined
- // on signed overflow.
- (long long)-ULLVal > 0)
- return true;
-
- Str = Str2;
- Result = -ULLVal;
- return false;
-}
-
-/// GetAsUnsignedInteger - Workhorse method that converts a integer character
-/// sequence of radix up to 36 to an unsigned long long value.
-bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix,
- unsigned long long &Result) {
- if (consumeUnsignedInteger(Str, Radix, Result))
- return true;
-
- // For getAsUnsignedInteger, we require the whole string to be consumed or
- // else we consider it a failure.
- return !Str.empty();
-}
-
-bool llvm::getAsSignedInteger(StringRef Str, unsigned Radix,
- long long &Result) {
- if (consumeSignedInteger(Str, Radix, Result))
- return true;
-
- // For getAsSignedInteger, we require the whole string to be consumed or else
- // we consider it a failure.
- return !Str.empty();
-}
-
-bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const {
- StringRef Str = *this;
-
- // Autosense radix if not specified.
- if (Radix == 0)
- Radix = GetAutoSenseRadix(Str);
-
- assert(Radix > 1 && Radix <= 36);
-
- // Empty strings (after the radix autosense) are invalid.
- if (Str.empty()) return true;
-
- // Skip leading zeroes. This can be a significant improvement if
- // it means we don't need > 64 bits.
- while (!Str.empty() && Str.front() == '0')
- Str = Str.substr(1);
-
- // If it was nothing but zeroes....
- if (Str.empty()) {
- Result = APInt(64, 0);
- return false;
- }
-
- // (Over-)estimate the required number of bits.
- unsigned Log2Radix = 0;
- while ((1U << Log2Radix) < Radix) Log2Radix++;
- bool IsPowerOf2Radix = ((1U << Log2Radix) == Radix);
-
- unsigned BitWidth = Log2Radix * Str.size();
- if (BitWidth < Result.getBitWidth())
- BitWidth = Result.getBitWidth(); // don't shrink the result
- else if (BitWidth > Result.getBitWidth())
- Result = Result.zext(BitWidth);
-
- APInt RadixAP, CharAP; // unused unless !IsPowerOf2Radix
- if (!IsPowerOf2Radix) {
- // These must have the same bit-width as Result.
- RadixAP = APInt(BitWidth, Radix);
- CharAP = APInt(BitWidth, 0);
- }
-
- // Parse all the bytes of the string given this radix.
- Result = 0;
- while (!Str.empty()) {
- unsigned CharVal;
- if (Str[0] >= '0' && Str[0] <= '9')
- CharVal = Str[0]-'0';
- else if (Str[0] >= 'a' && Str[0] <= 'z')
- CharVal = Str[0]-'a'+10;
- else if (Str[0] >= 'A' && Str[0] <= 'Z')
- CharVal = Str[0]-'A'+10;
- else
- return true;
-
- // If the parsed value is larger than the integer radix, the string is
- // invalid.
- if (CharVal >= Radix)
- return true;
-
- // Add in this character.
- if (IsPowerOf2Radix) {
- Result <<= Log2Radix;
- Result |= CharVal;
- } else {
- Result *= RadixAP;
- CharAP = CharVal;
- Result += CharAP;
- }
-
- Str = Str.substr(1);
- }
-
- return false;
-}
-
-bool StringRef::getAsDouble(double &Result, bool AllowInexact) const {
- APFloat F(0.0);
- APFloat::opStatus Status =
- F.convertFromString(*this, APFloat::rmNearestTiesToEven);
- if (Status != APFloat::opOK) {
- if (!AllowInexact || !(Status & APFloat::opInexact))
- return true;
- }
-
- Result = F.convertToDouble();
- return false;
-}
-
-// Implementation of StringRef hashing.
-hash_code llvm::hash_value(StringRef S) {
- return hash_combine_range(S.begin(), S.end());
-}
diff --git a/gnu/llvm/lib/Support/StringSaver.cpp b/gnu/llvm/lib/Support/StringSaver.cpp
deleted file mode 100644
index bf0ac8de982..00000000000
--- a/gnu/llvm/lib/Support/StringSaver.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//===-- StringSaver.cpp ---------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/StringSaver.h"
-
-using namespace llvm;
-
-StringRef StringSaver::save(StringRef S) {
- char *P = Alloc.Allocate<char>(S.size() + 1);
- if (!S.empty())
- memcpy(P, S.data(), S.size());
- P[S.size()] = '\0';
- return StringRef(P, S.size());
-}
-
-StringRef UniqueStringSaver::save(StringRef S) {
- auto R = Unique.insert(S);
- if (R.second) // cache miss, need to actually save the string
- *R.first = Strings.save(S); // safe replacement with equal value
- return *R.first;
-}
diff --git a/gnu/llvm/lib/Support/SymbolRemappingReader.cpp b/gnu/llvm/lib/Support/SymbolRemappingReader.cpp
deleted file mode 100644
index 264c890ce8f..00000000000
--- a/gnu/llvm/lib/Support/SymbolRemappingReader.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-//===- SymbolRemappingReader.cpp - Read symbol remapping file -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains definitions needed for reading and applying symbol
-// remapping files.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/SymbolRemappingReader.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/LineIterator.h"
-
-using namespace llvm;
-
-char SymbolRemappingParseError::ID;
-
-/// Load a set of name remappings from a text file.
-///
-/// See the documentation at the top of the file for an explanation of
-/// the expected format.
-Error SymbolRemappingReader::read(MemoryBuffer &B) {
- line_iterator LineIt(B, /*SkipBlanks=*/true, '#');
-
- auto ReportError = [&](Twine Msg) {
- return llvm::make_error<SymbolRemappingParseError>(
- B.getBufferIdentifier(), LineIt.line_number(), Msg);
- };
-
- for (; !LineIt.is_at_eof(); ++LineIt) {
- StringRef Line = *LineIt;
- Line = Line.ltrim(' ');
- // line_iterator only detects comments starting in column 1.
- if (Line.startswith("#") || Line.empty())
- continue;
-
- SmallVector<StringRef, 4> Parts;
- Line.split(Parts, ' ', /*MaxSplits*/-1, /*KeepEmpty*/false);
-
- if (Parts.size() != 3)
- return ReportError("Expected 'kind mangled_name mangled_name', "
- "found '" + Line + "'");
-
- using FK = ItaniumManglingCanonicalizer::FragmentKind;
- Optional<FK> FragmentKind = StringSwitch<Optional<FK>>(Parts[0])
- .Case("name", FK::Name)
- .Case("type", FK::Type)
- .Case("encoding", FK::Encoding)
- .Default(None);
- if (!FragmentKind)
- return ReportError("Invalid kind, expected 'name', 'type', or 'encoding',"
- " found '" + Parts[0] + "'");
-
- using EE = ItaniumManglingCanonicalizer::EquivalenceError;
- switch (Canonicalizer.addEquivalence(*FragmentKind, Parts[1], Parts[2])) {
- case EE::Success:
- break;
-
- case EE::ManglingAlreadyUsed:
- return ReportError("Manglings '" + Parts[1] + "' and '" + Parts[2] + "' "
- "have both been used in prior remappings. Move this "
- "remapping earlier in the file.");
-
- case EE::InvalidFirstMangling:
- return ReportError("Could not demangle '" + Parts[1] + "' "
- "as a <" + Parts[0] + ">; invalid mangling?");
-
- case EE::InvalidSecondMangling:
- return ReportError("Could not demangle '" + Parts[2] + "' "
- "as a <" + Parts[0] + ">; invalid mangling?");
- }
- }
-
- return Error::success();
-}
diff --git a/gnu/llvm/lib/Support/SystemUtils.cpp b/gnu/llvm/lib/Support/SystemUtils.cpp
deleted file mode 100644
index 7fa6ae3f619..00000000000
--- a/gnu/llvm/lib/Support/SystemUtils.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- SystemUtils.cpp - Utilities for low-level system tasks -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains functions used to do a variety of low-level, often
-// system-specific, tasks.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/SystemUtils.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-bool llvm::CheckBitcodeOutputToConsole(raw_ostream &stream_to_check,
- bool print_warning) {
- if (stream_to_check.is_displayed()) {
- if (print_warning) {
- errs() << "WARNING: You're attempting to print out a bitcode file.\n"
- "This is inadvisable as it may cause display problems. If\n"
- "you REALLY want to taste LLVM bitcode first-hand, you\n"
- "can force output with the `-f' option.\n\n";
- }
- return true;
- }
- return false;
-}
diff --git a/gnu/llvm/lib/Support/TarWriter.cpp b/gnu/llvm/lib/Support/TarWriter.cpp
deleted file mode 100644
index 5b4d554befe..00000000000
--- a/gnu/llvm/lib/Support/TarWriter.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-//===-- TarWriter.cpp - Tar archive file creator --------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// TarWriter class provides a feature to create a tar archive file.
-//
-// I put emphasis on simplicity over comprehensiveness when implementing this
-// class because we don't need a full-fledged archive file generator in LLVM
-// at the moment.
-//
-// The filename field in the Unix V7 tar header is 100 bytes. Longer filenames
-// are stored using the PAX extension. The PAX header is standardized in
-// POSIX.1-2001.
-//
-// The struct definition of UstarHeader is copied from
-// https://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/TarWriter.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/Path.h"
-
-using namespace llvm;
-
-// Each file in an archive must be aligned to this block size.
-static const int BlockSize = 512;
-
-struct UstarHeader {
- char Name[100];
- char Mode[8];
- char Uid[8];
- char Gid[8];
- char Size[12];
- char Mtime[12];
- char Checksum[8];
- char TypeFlag;
- char Linkname[100];
- char Magic[6];
- char Version[2];
- char Uname[32];
- char Gname[32];
- char DevMajor[8];
- char DevMinor[8];
- char Prefix[155];
- char Pad[12];
-};
-static_assert(sizeof(UstarHeader) == BlockSize, "invalid Ustar header");
-
-static UstarHeader makeUstarHeader() {
- UstarHeader Hdr = {};
- memcpy(Hdr.Magic, "ustar", 5); // Ustar magic
- memcpy(Hdr.Version, "00", 2); // Ustar version
- return Hdr;
-}
-
-// A PAX attribute is in the form of "<length> <key>=<value>\n"
-// where <length> is the length of the entire string including
-// the length field itself. An example string is this.
-//
-// 25 ctime=1084839148.1212\n
-//
-// This function create such string.
-static std::string formatPax(StringRef Key, StringRef Val) {
- int Len = Key.size() + Val.size() + 3; // +3 for " ", "=" and "\n"
-
- // We need to compute total size twice because appending
- // a length field could change total size by one.
- int Total = Len + Twine(Len).str().size();
- Total = Len + Twine(Total).str().size();
- return (Twine(Total) + " " + Key + "=" + Val + "\n").str();
-}
-
-// Headers in tar files must be aligned to 512 byte boundaries.
-// This function forwards the current file position to the next boundary.
-static void pad(raw_fd_ostream &OS) {
- uint64_t Pos = OS.tell();
- OS.seek(alignTo(Pos, BlockSize));
-}
-
-// Computes a checksum for a tar header.
-static void computeChecksum(UstarHeader &Hdr) {
- // Before computing a checksum, checksum field must be
- // filled with space characters.
- memset(Hdr.Checksum, ' ', sizeof(Hdr.Checksum));
-
- // Compute a checksum and set it to the checksum field.
- unsigned Chksum = 0;
- for (size_t I = 0; I < sizeof(Hdr); ++I)
- Chksum += reinterpret_cast<uint8_t *>(&Hdr)[I];
- snprintf(Hdr.Checksum, sizeof(Hdr.Checksum), "%06o", Chksum);
-}
-
-// Create a tar header and write it to a given output stream.
-static void writePaxHeader(raw_fd_ostream &OS, StringRef Path) {
- // A PAX header consists of a 512-byte header followed
- // by key-value strings. First, create key-value strings.
- std::string PaxAttr = formatPax("path", Path);
-
- // Create a 512-byte header.
- UstarHeader Hdr = makeUstarHeader();
- snprintf(Hdr.Size, sizeof(Hdr.Size), "%011zo", PaxAttr.size());
- Hdr.TypeFlag = 'x'; // PAX magic
- computeChecksum(Hdr);
-
- // Write them down.
- OS << StringRef(reinterpret_cast<char *>(&Hdr), sizeof(Hdr));
- OS << PaxAttr;
- pad(OS);
-}
-
-// Path fits in a Ustar header if
-//
-// - Path is less than 100 characters long, or
-// - Path is in the form of "<prefix>/<name>" where <prefix> is less
-// than or equal to 155 characters long and <name> is less than 100
-// characters long. Both <prefix> and <name> can contain extra '/'.
-//
-// If Path fits in a Ustar header, updates Prefix and Name and returns true.
-// Otherwise, returns false.
-static bool splitUstar(StringRef Path, StringRef &Prefix, StringRef &Name) {
- if (Path.size() < sizeof(UstarHeader::Name)) {
- Prefix = "";
- Name = Path;
- return true;
- }
-
- size_t Sep = Path.rfind('/', sizeof(UstarHeader::Prefix) + 1);
- if (Sep == StringRef::npos)
- return false;
- if (Path.size() - Sep - 1 >= sizeof(UstarHeader::Name))
- return false;
-
- Prefix = Path.substr(0, Sep);
- Name = Path.substr(Sep + 1);
- return true;
-}
-
-// The PAX header is an extended format, so a PAX header needs
-// to be followed by a "real" header.
-static void writeUstarHeader(raw_fd_ostream &OS, StringRef Prefix,
- StringRef Name, size_t Size) {
- UstarHeader Hdr = makeUstarHeader();
- memcpy(Hdr.Name, Name.data(), Name.size());
- memcpy(Hdr.Mode, "0000664", 8);
- snprintf(Hdr.Size, sizeof(Hdr.Size), "%011zo", Size);
- memcpy(Hdr.Prefix, Prefix.data(), Prefix.size());
- computeChecksum(Hdr);
- OS << StringRef(reinterpret_cast<char *>(&Hdr), sizeof(Hdr));
-}
-
-// Creates a TarWriter instance and returns it.
-Expected<std::unique_ptr<TarWriter>> TarWriter::create(StringRef OutputPath,
- StringRef BaseDir) {
- using namespace sys::fs;
- int FD;
- if (std::error_code EC =
- openFileForWrite(OutputPath, FD, CD_CreateAlways, OF_None))
- return make_error<StringError>("cannot open " + OutputPath, EC);
- return std::unique_ptr<TarWriter>(new TarWriter(FD, BaseDir));
-}
-
-TarWriter::TarWriter(int FD, StringRef BaseDir)
- : OS(FD, /*shouldClose=*/true, /*unbuffered=*/false), BaseDir(BaseDir) {}
-
-// Append a given file to an archive.
-void TarWriter::append(StringRef Path, StringRef Data) {
- // Write Path and Data.
- std::string Fullpath = BaseDir + "/" + sys::path::convert_to_slash(Path);
-
- // We do not want to include the same file more than once.
- if (!Files.insert(Fullpath).second)
- return;
-
- StringRef Prefix;
- StringRef Name;
- if (splitUstar(Fullpath, Prefix, Name)) {
- writeUstarHeader(OS, Prefix, Name, Data.size());
- } else {
- writePaxHeader(OS, Fullpath);
- writeUstarHeader(OS, "", "", Data.size());
- }
-
- OS << Data;
- pad(OS);
-
- // POSIX requires tar archives end with two null blocks.
- // Here, we write the terminator and then seek back, so that
- // the file being output is terminated correctly at any moment.
- uint64_t Pos = OS.tell();
- OS << std::string(BlockSize * 2, '\0');
- OS.seek(Pos);
- OS.flush();
-}
diff --git a/gnu/llvm/lib/Support/TargetParser.cpp b/gnu/llvm/lib/Support/TargetParser.cpp
deleted file mode 100644
index bdc0dc52c5e..00000000000
--- a/gnu/llvm/lib/Support/TargetParser.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-//===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a target parser to recognise hardware features such as
-// FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ARMBuildAttributes.h"
-#include "llvm/Support/TargetParser.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Twine.h"
-
-using namespace llvm;
-using namespace AMDGPU;
-
-namespace {
-
-struct GPUInfo {
- StringLiteral Name;
- StringLiteral CanonicalName;
- AMDGPU::GPUKind Kind;
- unsigned Features;
-};
-
-constexpr GPUInfo R600GPUs[26] = {
- // Name Canonical Kind Features
- // Name
- {{"r600"}, {"r600"}, GK_R600, FEATURE_NONE },
- {{"rv630"}, {"r600"}, GK_R600, FEATURE_NONE },
- {{"rv635"}, {"r600"}, GK_R600, FEATURE_NONE },
- {{"r630"}, {"r630"}, GK_R630, FEATURE_NONE },
- {{"rs780"}, {"rs880"}, GK_RS880, FEATURE_NONE },
- {{"rs880"}, {"rs880"}, GK_RS880, FEATURE_NONE },
- {{"rv610"}, {"rs880"}, GK_RS880, FEATURE_NONE },
- {{"rv620"}, {"rs880"}, GK_RS880, FEATURE_NONE },
- {{"rv670"}, {"rv670"}, GK_RV670, FEATURE_NONE },
- {{"rv710"}, {"rv710"}, GK_RV710, FEATURE_NONE },
- {{"rv730"}, {"rv730"}, GK_RV730, FEATURE_NONE },
- {{"rv740"}, {"rv770"}, GK_RV770, FEATURE_NONE },
- {{"rv770"}, {"rv770"}, GK_RV770, FEATURE_NONE },
- {{"cedar"}, {"cedar"}, GK_CEDAR, FEATURE_NONE },
- {{"palm"}, {"cedar"}, GK_CEDAR, FEATURE_NONE },
- {{"cypress"}, {"cypress"}, GK_CYPRESS, FEATURE_FMA },
- {{"hemlock"}, {"cypress"}, GK_CYPRESS, FEATURE_FMA },
- {{"juniper"}, {"juniper"}, GK_JUNIPER, FEATURE_NONE },
- {{"redwood"}, {"redwood"}, GK_REDWOOD, FEATURE_NONE },
- {{"sumo"}, {"sumo"}, GK_SUMO, FEATURE_NONE },
- {{"sumo2"}, {"sumo"}, GK_SUMO, FEATURE_NONE },
- {{"barts"}, {"barts"}, GK_BARTS, FEATURE_NONE },
- {{"caicos"}, {"caicos"}, GK_CAICOS, FEATURE_NONE },
- {{"aruba"}, {"cayman"}, GK_CAYMAN, FEATURE_FMA },
- {{"cayman"}, {"cayman"}, GK_CAYMAN, FEATURE_FMA },
- {{"turks"}, {"turks"}, GK_TURKS, FEATURE_NONE }
-};
-
-// This table should be sorted by the value of GPUKind
-// Don't bother listing the implicitly true features
-constexpr GPUInfo AMDGCNGPUs[33] = {
- // Name Canonical Kind Features
- // Name
- {{"gfx600"}, {"gfx600"}, GK_GFX600, FEATURE_FAST_FMA_F32},
- {{"tahiti"}, {"gfx600"}, GK_GFX600, FEATURE_FAST_FMA_F32},
- {{"gfx601"}, {"gfx601"}, GK_GFX601, FEATURE_NONE},
- {{"hainan"}, {"gfx601"}, GK_GFX601, FEATURE_NONE},
- {{"oland"}, {"gfx601"}, GK_GFX601, FEATURE_NONE},
- {{"pitcairn"}, {"gfx601"}, GK_GFX601, FEATURE_NONE},
- {{"verde"}, {"gfx601"}, GK_GFX601, FEATURE_NONE},
- {{"gfx700"}, {"gfx700"}, GK_GFX700, FEATURE_NONE},
- {{"kaveri"}, {"gfx700"}, GK_GFX700, FEATURE_NONE},
- {{"gfx701"}, {"gfx701"}, GK_GFX701, FEATURE_FAST_FMA_F32},
- {{"hawaii"}, {"gfx701"}, GK_GFX701, FEATURE_FAST_FMA_F32},
- {{"gfx702"}, {"gfx702"}, GK_GFX702, FEATURE_FAST_FMA_F32},
- {{"gfx703"}, {"gfx703"}, GK_GFX703, FEATURE_NONE},
- {{"kabini"}, {"gfx703"}, GK_GFX703, FEATURE_NONE},
- {{"mullins"}, {"gfx703"}, GK_GFX703, FEATURE_NONE},
- {{"gfx704"}, {"gfx704"}, GK_GFX704, FEATURE_NONE},
- {{"bonaire"}, {"gfx704"}, GK_GFX704, FEATURE_NONE},
- {{"gfx801"}, {"gfx801"}, GK_GFX801, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
- {{"carrizo"}, {"gfx801"}, GK_GFX801, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
- {{"gfx802"}, {"gfx802"}, GK_GFX802, FEATURE_FAST_DENORMAL_F32},
- {{"iceland"}, {"gfx802"}, GK_GFX802, FEATURE_FAST_DENORMAL_F32},
- {{"tonga"}, {"gfx802"}, GK_GFX802, FEATURE_FAST_DENORMAL_F32},
- {{"gfx803"}, {"gfx803"}, GK_GFX803, FEATURE_FAST_DENORMAL_F32},
- {{"fiji"}, {"gfx803"}, GK_GFX803, FEATURE_FAST_DENORMAL_F32},
- {{"polaris10"}, {"gfx803"}, GK_GFX803, FEATURE_FAST_DENORMAL_F32},
- {{"polaris11"}, {"gfx803"}, GK_GFX803, FEATURE_FAST_DENORMAL_F32},
- {{"gfx810"}, {"gfx810"}, GK_GFX810, FEATURE_FAST_DENORMAL_F32},
- {{"stoney"}, {"gfx810"}, GK_GFX810, FEATURE_FAST_DENORMAL_F32},
- {{"gfx900"}, {"gfx900"}, GK_GFX900, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
- {{"gfx902"}, {"gfx902"}, GK_GFX902, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
- {{"gfx904"}, {"gfx904"}, GK_GFX904, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
- {{"gfx906"}, {"gfx906"}, GK_GFX906, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
- {{"gfx909"}, {"gfx909"}, GK_GFX909, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
-};
-
-const GPUInfo *getArchEntry(AMDGPU::GPUKind AK, ArrayRef<GPUInfo> Table) {
- GPUInfo Search = { {""}, {""}, AK, AMDGPU::FEATURE_NONE };
-
- auto I = std::lower_bound(Table.begin(), Table.end(), Search,
- [](const GPUInfo &A, const GPUInfo &B) {
- return A.Kind < B.Kind;
- });
-
- if (I == Table.end())
- return nullptr;
- return I;
-}
-
-} // namespace
-
-StringRef llvm::AMDGPU::getArchNameAMDGCN(GPUKind AK) {
- if (const auto *Entry = getArchEntry(AK, AMDGCNGPUs))
- return Entry->CanonicalName;
- return "";
-}
-
-StringRef llvm::AMDGPU::getArchNameR600(GPUKind AK) {
- if (const auto *Entry = getArchEntry(AK, R600GPUs))
- return Entry->CanonicalName;
- return "";
-}
-
-AMDGPU::GPUKind llvm::AMDGPU::parseArchAMDGCN(StringRef CPU) {
- for (const auto C : AMDGCNGPUs) {
- if (CPU == C.Name)
- return C.Kind;
- }
-
- return AMDGPU::GPUKind::GK_NONE;
-}
-
-AMDGPU::GPUKind llvm::AMDGPU::parseArchR600(StringRef CPU) {
- for (const auto C : R600GPUs) {
- if (CPU == C.Name)
- return C.Kind;
- }
-
- return AMDGPU::GPUKind::GK_NONE;
-}
-
-unsigned AMDGPU::getArchAttrAMDGCN(GPUKind AK) {
- if (const auto *Entry = getArchEntry(AK, AMDGCNGPUs))
- return Entry->Features;
- return FEATURE_NONE;
-}
-
-unsigned AMDGPU::getArchAttrR600(GPUKind AK) {
- if (const auto *Entry = getArchEntry(AK, R600GPUs))
- return Entry->Features;
- return FEATURE_NONE;
-}
-
-void AMDGPU::fillValidArchListAMDGCN(SmallVectorImpl<StringRef> &Values) {
- // XXX: Should this only report unique canonical names?
- for (const auto C : AMDGCNGPUs)
- Values.push_back(C.Name);
-}
-
-void AMDGPU::fillValidArchListR600(SmallVectorImpl<StringRef> &Values) {
- for (const auto C : R600GPUs)
- Values.push_back(C.Name);
-}
-
-AMDGPU::IsaVersion AMDGPU::getIsaVersion(StringRef GPU) {
- if (GPU == "generic")
- return {7, 0, 0};
-
- AMDGPU::GPUKind AK = parseArchAMDGCN(GPU);
- if (AK == AMDGPU::GPUKind::GK_NONE)
- return {0, 0, 0};
-
- switch (AK) {
- case GK_GFX600: return {6, 0, 0};
- case GK_GFX601: return {6, 0, 1};
- case GK_GFX700: return {7, 0, 0};
- case GK_GFX701: return {7, 0, 1};
- case GK_GFX702: return {7, 0, 2};
- case GK_GFX703: return {7, 0, 3};
- case GK_GFX704: return {7, 0, 4};
- case GK_GFX801: return {8, 0, 1};
- case GK_GFX802: return {8, 0, 2};
- case GK_GFX803: return {8, 0, 3};
- case GK_GFX810: return {8, 1, 0};
- case GK_GFX900: return {9, 0, 0};
- case GK_GFX902: return {9, 0, 2};
- case GK_GFX904: return {9, 0, 4};
- case GK_GFX906: return {9, 0, 6};
- case GK_GFX909: return {9, 0, 9};
- default: return {0, 0, 0};
- }
-}
diff --git a/gnu/llvm/lib/Support/TargetRegistry.cpp b/gnu/llvm/lib/Support/TargetRegistry.cpp
deleted file mode 100644
index bb63891cd71..00000000000
--- a/gnu/llvm/lib/Support/TargetRegistry.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-//===--- TargetRegistry.cpp - Target registration -------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <vector>
-using namespace llvm;
-
-// Clients are responsible for avoid race conditions in registration.
-static Target *FirstTarget = nullptr;
-
-iterator_range<TargetRegistry::iterator> TargetRegistry::targets() {
- return make_range(iterator(FirstTarget), iterator());
-}
-
-const Target *TargetRegistry::lookupTarget(const std::string &ArchName,
- Triple &TheTriple,
- std::string &Error) {
- // Allocate target machine. First, check whether the user has explicitly
- // specified an architecture to compile for. If so we have to look it up by
- // name, because it might be a backend that has no mapping to a target triple.
- const Target *TheTarget = nullptr;
- if (!ArchName.empty()) {
- auto I = find_if(targets(),
- [&](const Target &T) { return ArchName == T.getName(); });
-
- if (I == targets().end()) {
- Error = "error: invalid target '" + ArchName + "'.\n";
- return nullptr;
- }
-
- TheTarget = &*I;
-
- // Adjust the triple to match (if known), otherwise stick with the
- // given triple.
- Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
- if (Type != Triple::UnknownArch)
- TheTriple.setArch(Type);
- } else {
- // Get the target specific parser.
- std::string TempError;
- TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError);
- if (!TheTarget) {
- Error = ": error: unable to get target for '"
- + TheTriple.getTriple()
- + "', see --version and --triple.\n";
- return nullptr;
- }
- }
-
- return TheTarget;
-}
-
-const Target *TargetRegistry::lookupTarget(const std::string &TT,
- std::string &Error) {
- // Provide special warning when no targets are initialized.
- if (targets().begin() == targets().end()) {
- Error = "Unable to find target for this triple (no targets are registered)";
- return nullptr;
- }
- Triple::ArchType Arch = Triple(TT).getArch();
- auto ArchMatch = [&](const Target &T) { return T.ArchMatchFn(Arch); };
- auto I = find_if(targets(), ArchMatch);
-
- if (I == targets().end()) {
- Error = "No available targets are compatible with triple \"" + TT + "\"";
- return nullptr;
- }
-
- auto J = std::find_if(std::next(I), targets().end(), ArchMatch);
- if (J != targets().end()) {
- Error = std::string("Cannot choose between targets \"") + I->Name +
- "\" and \"" + J->Name + "\"";
- return nullptr;
- }
-
- return &*I;
-}
-
-void TargetRegistry::RegisterTarget(Target &T, const char *Name,
- const char *ShortDesc,
- const char *BackendName,
- Target::ArchMatchFnTy ArchMatchFn,
- bool HasJIT) {
- assert(Name && ShortDesc && ArchMatchFn &&
- "Missing required target information!");
-
- // Check if this target has already been initialized, we allow this as a
- // convenience to some clients.
- if (T.Name)
- return;
-
- // Add to the list of targets.
- T.Next = FirstTarget;
- FirstTarget = &T;
-
- T.Name = Name;
- T.ShortDesc = ShortDesc;
- T.BackendName = BackendName;
- T.ArchMatchFn = ArchMatchFn;
- T.HasJIT = HasJIT;
-}
-
-static int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS,
- const std::pair<StringRef, const Target *> *RHS) {
- return LHS->first.compare(RHS->first);
-}
-
-void TargetRegistry::printRegisteredTargetsForVersion(raw_ostream &OS) {
- std::vector<std::pair<StringRef, const Target*> > Targets;
- size_t Width = 0;
- for (const auto &T : TargetRegistry::targets()) {
- Targets.push_back(std::make_pair(T.getName(), &T));
- Width = std::max(Width, Targets.back().first.size());
- }
- array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn);
-
- OS << " Registered Targets:\n";
- for (unsigned i = 0, e = Targets.size(); i != e; ++i) {
- OS << " " << Targets[i].first;
- OS.indent(Width - Targets[i].first.size()) << " - "
- << Targets[i].second->getShortDescription() << '\n';
- }
- if (Targets.empty())
- OS << " (none)\n";
-}
diff --git a/gnu/llvm/lib/Support/ThreadLocal.cpp b/gnu/llvm/lib/Support/ThreadLocal.cpp
deleted file mode 100644
index f6e4a652302..00000000000
--- a/gnu/llvm/lib/Support/ThreadLocal.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//===- ThreadLocal.cpp - Thread Local Data ----------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the llvm::sys::ThreadLocal class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ThreadLocal.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Compiler.h"
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
-
-#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
-// Define all methods as no-ops if threading is explicitly disabled
-namespace llvm {
-using namespace sys;
-ThreadLocalImpl::ThreadLocalImpl() : data() { }
-ThreadLocalImpl::~ThreadLocalImpl() { }
-void ThreadLocalImpl::setInstance(const void* d) {
- static_assert(sizeof(d) <= sizeof(data), "size too big");
- void **pd = reinterpret_cast<void**>(&data);
- *pd = const_cast<void*>(d);
-}
-void *ThreadLocalImpl::getInstance() {
- void **pd = reinterpret_cast<void**>(&data);
- return *pd;
-}
-void ThreadLocalImpl::removeInstance() {
- setInstance(nullptr);
-}
-}
-#elif defined(LLVM_ON_UNIX)
-#include "Unix/ThreadLocal.inc"
-#elif defined( _WIN32)
-#include "Windows/ThreadLocal.inc"
-#else
-#warning Neither LLVM_ON_UNIX nor _WIN32 set in Support/ThreadLocal.cpp
-#endif
diff --git a/gnu/llvm/lib/Support/ThreadPool.cpp b/gnu/llvm/lib/Support/ThreadPool.cpp
deleted file mode 100644
index d0212ca1346..00000000000
--- a/gnu/llvm/lib/Support/ThreadPool.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-//==-- llvm/Support/ThreadPool.cpp - A ThreadPool implementation -*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a crude C++11 based thread pool.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ThreadPool.h"
-
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Threading.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-#if LLVM_ENABLE_THREADS
-
-// Default to hardware_concurrency
-ThreadPool::ThreadPool() : ThreadPool(hardware_concurrency()) {}
-
-ThreadPool::ThreadPool(unsigned ThreadCount)
- : ActiveThreads(0), EnableFlag(true) {
- // Create ThreadCount threads that will loop forever, wait on QueueCondition
- // for tasks to be queued or the Pool to be destroyed.
- Threads.reserve(ThreadCount);
- for (unsigned ThreadID = 0; ThreadID < ThreadCount; ++ThreadID) {
- Threads.emplace_back([&] {
- while (true) {
- PackagedTaskTy Task;
- {
- std::unique_lock<std::mutex> LockGuard(QueueLock);
- // Wait for tasks to be pushed in the queue
- QueueCondition.wait(LockGuard,
- [&] { return !EnableFlag || !Tasks.empty(); });
- // Exit condition
- if (!EnableFlag && Tasks.empty())
- return;
- // Yeah, we have a task, grab it and release the lock on the queue
-
- // We first need to signal that we are active before popping the queue
- // in order for wait() to properly detect that even if the queue is
- // empty, there is still a task in flight.
- {
- std::unique_lock<std::mutex> LockGuard(CompletionLock);
- ++ActiveThreads;
- }
- Task = std::move(Tasks.front());
- Tasks.pop();
- }
- // Run the task we just grabbed
- Task();
-
- {
- // Adjust `ActiveThreads`, in case someone waits on ThreadPool::wait()
- std::unique_lock<std::mutex> LockGuard(CompletionLock);
- --ActiveThreads;
- }
-
- // Notify task completion, in case someone waits on ThreadPool::wait()
- CompletionCondition.notify_all();
- }
- });
- }
-}
-
-void ThreadPool::wait() {
- // Wait for all threads to complete and the queue to be empty
- std::unique_lock<std::mutex> LockGuard(CompletionLock);
- // The order of the checks for ActiveThreads and Tasks.empty() matters because
- // any active threads might be modifying the Tasks queue, and this would be a
- // race.
- CompletionCondition.wait(LockGuard,
- [&] { return !ActiveThreads && Tasks.empty(); });
-}
-
-std::shared_future<void> ThreadPool::asyncImpl(TaskTy Task) {
- /// Wrap the Task in a packaged_task to return a future object.
- PackagedTaskTy PackagedTask(std::move(Task));
- auto Future = PackagedTask.get_future();
- {
- // Lock the queue and push the new task
- std::unique_lock<std::mutex> LockGuard(QueueLock);
-
- // Don't allow enqueueing after disabling the pool
- assert(EnableFlag && "Queuing a thread during ThreadPool destruction");
-
- Tasks.push(std::move(PackagedTask));
- }
- QueueCondition.notify_one();
- return Future.share();
-}
-
-// The destructor joins all threads, waiting for completion.
-ThreadPool::~ThreadPool() {
- {
- std::unique_lock<std::mutex> LockGuard(QueueLock);
- EnableFlag = false;
- }
- QueueCondition.notify_all();
- for (auto &Worker : Threads)
- Worker.join();
-}
-
-#else // LLVM_ENABLE_THREADS Disabled
-
-ThreadPool::ThreadPool() : ThreadPool(0) {}
-
-// No threads are launched, issue a warning if ThreadCount is not 0
-ThreadPool::ThreadPool(unsigned ThreadCount)
- : ActiveThreads(0) {
- if (ThreadCount) {
- errs() << "Warning: request a ThreadPool with " << ThreadCount
- << " threads, but LLVM_ENABLE_THREADS has been turned off\n";
- }
-}
-
-void ThreadPool::wait() {
- // Sequential implementation running the tasks
- while (!Tasks.empty()) {
- auto Task = std::move(Tasks.front());
- Tasks.pop();
- Task();
- }
-}
-
-std::shared_future<void> ThreadPool::asyncImpl(TaskTy Task) {
- // Get a Future with launch::deferred execution using std::async
- auto Future = std::async(std::launch::deferred, std::move(Task)).share();
- // Wrap the future so that both ThreadPool::wait() can operate and the
- // returned future can be sync'ed on.
- PackagedTaskTy PackagedTask([Future]() { Future.get(); });
- Tasks.push(std::move(PackagedTask));
- return Future;
-}
-
-ThreadPool::~ThreadPool() {
- wait();
-}
-
-#endif
diff --git a/gnu/llvm/lib/Support/Threading.cpp b/gnu/llvm/lib/Support/Threading.cpp
deleted file mode 100644
index fcb1030e1ab..00000000000
--- a/gnu/llvm/lib/Support/Threading.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-//===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines helper functions for running LLVM in a multi-threaded
-// environment.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Threading.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/Host.h"
-
-#include <cassert>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only TRULY operating system
-//=== independent code.
-//===----------------------------------------------------------------------===//
-
-bool llvm::llvm_is_multithreaded() {
-#if LLVM_ENABLE_THREADS != 0
- return true;
-#else
- return false;
-#endif
-}
-
-#if LLVM_ENABLE_THREADS == 0 || \
- (!defined(_WIN32) && !defined(HAVE_PTHREAD_H))
-// Support for non-Win32, non-pthread implementation.
-void llvm::llvm_execute_on_thread(void (*Fn)(void *), void *UserData,
- unsigned RequestedStackSize) {
- (void)RequestedStackSize;
- Fn(UserData);
-}
-
-unsigned llvm::heavyweight_hardware_concurrency() { return 1; }
-
-unsigned llvm::hardware_concurrency() { return 1; }
-
-uint64_t llvm::get_threadid() { return 0; }
-
-uint32_t llvm::get_max_thread_name_length() { return 0; }
-
-void llvm::set_thread_name(const Twine &Name) {}
-
-void llvm::get_thread_name(SmallVectorImpl<char> &Name) { Name.clear(); }
-
-#else
-
-#include <thread>
-unsigned llvm::heavyweight_hardware_concurrency() {
- // Since we can't get here unless LLVM_ENABLE_THREADS == 1, it is safe to use
- // `std::thread` directly instead of `llvm::thread` (and indeed, doing so
- // allows us to not define `thread` in the llvm namespace, which conflicts
- // with some platforms such as FreeBSD whose headers also define a struct
- // called `thread` in the global namespace which can cause ambiguity due to
- // ADL.
- int NumPhysical = sys::getHostNumPhysicalCores();
- if (NumPhysical == -1)
- return std::thread::hardware_concurrency();
- return NumPhysical;
-}
-
-unsigned llvm::hardware_concurrency() {
-#if defined(HAVE_SCHED_GETAFFINITY) && defined(HAVE_CPU_COUNT)
- cpu_set_t Set;
- if (sched_getaffinity(0, sizeof(Set), &Set))
- return CPU_COUNT(&Set);
-#endif
- // Guard against std::thread::hardware_concurrency() returning 0.
- if (unsigned Val = std::thread::hardware_concurrency())
- return Val;
- return 1;
-}
-
-// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
-#include "Unix/Threading.inc"
-#endif
-#ifdef _WIN32
-#include "Windows/Threading.inc"
-#endif
-
-#endif
diff --git a/gnu/llvm/lib/Support/Timer.cpp b/gnu/llvm/lib/Support/Timer.cpp
deleted file mode 100644
index 82f5810dd10..00000000000
--- a/gnu/llvm/lib/Support/Timer.cpp
+++ /dev/null
@@ -1,432 +0,0 @@
-//===-- Timer.cpp - Interval Timing Support -------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file Interval Timing implementation.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Timer.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/Support/raw_ostream.h"
-#include <limits>
-
-using namespace llvm;
-
-// This ugly hack is brought to you courtesy of constructor/destructor ordering
-// being unspecified by C++. Basically the problem is that a Statistic object
-// gets destroyed, which ends up calling 'GetLibSupportInfoOutputFile()'
-// (below), which calls this function. LibSupportInfoOutputFilename used to be
-// a global variable, but sometimes it would get destroyed before the Statistic,
-// causing havoc to ensue. We "fix" this by creating the string the first time
-// it is needed and never destroying it.
-static ManagedStatic<std::string> LibSupportInfoOutputFilename;
-static std::string &getLibSupportInfoOutputFilename() {
- return *LibSupportInfoOutputFilename;
-}
-
-static ManagedStatic<sys::SmartMutex<true> > TimerLock;
-
-namespace {
- static cl::opt<bool>
- TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
- "tracking (this may be slow)"),
- cl::Hidden);
-
- static cl::opt<std::string, true>
- InfoOutputFilename("info-output-file", cl::value_desc("filename"),
- cl::desc("File to append -stats and -timer output to"),
- cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
-}
-
-std::unique_ptr<raw_fd_ostream> llvm::CreateInfoOutputFile() {
- const std::string &OutputFilename = getLibSupportInfoOutputFilename();
- if (OutputFilename.empty())
- return llvm::make_unique<raw_fd_ostream>(2, false); // stderr.
- if (OutputFilename == "-")
- return llvm::make_unique<raw_fd_ostream>(1, false); // stdout.
-
- // Append mode is used because the info output file is opened and closed
- // each time -stats or -time-passes wants to print output to it. To
- // compensate for this, the test-suite Makefiles have code to delete the
- // info output file before running commands which write to it.
- std::error_code EC;
- auto Result = llvm::make_unique<raw_fd_ostream>(
- OutputFilename, EC, sys::fs::F_Append | sys::fs::F_Text);
- if (!EC)
- return Result;
-
- errs() << "Error opening info-output-file '"
- << OutputFilename << " for appending!\n";
- return llvm::make_unique<raw_fd_ostream>(2, false); // stderr.
-}
-
-namespace {
-struct CreateDefaultTimerGroup {
- static void *call() {
- return new TimerGroup("misc", "Miscellaneous Ungrouped Timers");
- }
-};
-} // namespace
-static ManagedStatic<TimerGroup, CreateDefaultTimerGroup> DefaultTimerGroup;
-static TimerGroup *getDefaultTimerGroup() { return &*DefaultTimerGroup; }
-
-//===----------------------------------------------------------------------===//
-// Timer Implementation
-//===----------------------------------------------------------------------===//
-
-void Timer::init(StringRef Name, StringRef Description) {
- init(Name, Description, *getDefaultTimerGroup());
-}
-
-void Timer::init(StringRef Name, StringRef Description, TimerGroup &tg) {
- assert(!TG && "Timer already initialized");
- this->Name.assign(Name.begin(), Name.end());
- this->Description.assign(Description.begin(), Description.end());
- Running = Triggered = false;
- TG = &tg;
- TG->addTimer(*this);
-}
-
-Timer::~Timer() {
- if (!TG) return; // Never initialized, or already cleared.
- TG->removeTimer(*this);
-}
-
-static inline size_t getMemUsage() {
- if (!TrackSpace) return 0;
- return sys::Process::GetMallocUsage();
-}
-
-TimeRecord TimeRecord::getCurrentTime(bool Start) {
- using Seconds = std::chrono::duration<double, std::ratio<1>>;
- TimeRecord Result;
- sys::TimePoint<> now;
- std::chrono::nanoseconds user, sys;
-
- if (Start) {
- Result.MemUsed = getMemUsage();
- sys::Process::GetTimeUsage(now, user, sys);
- } else {
- sys::Process::GetTimeUsage(now, user, sys);
- Result.MemUsed = getMemUsage();
- }
-
- Result.WallTime = Seconds(now.time_since_epoch()).count();
- Result.UserTime = Seconds(user).count();
- Result.SystemTime = Seconds(sys).count();
- return Result;
-}
-
-void Timer::startTimer() {
- assert(!Running && "Cannot start a running timer");
- Running = Triggered = true;
- StartTime = TimeRecord::getCurrentTime(true);
-}
-
-void Timer::stopTimer() {
- assert(Running && "Cannot stop a paused timer");
- Running = false;
- Time += TimeRecord::getCurrentTime(false);
- Time -= StartTime;
-}
-
-void Timer::clear() {
- Running = Triggered = false;
- Time = StartTime = TimeRecord();
-}
-
-static void printVal(double Val, double Total, raw_ostream &OS) {
- if (Total < 1e-7) // Avoid dividing by zero.
- OS << " ----- ";
- else
- OS << format(" %7.4f (%5.1f%%)", Val, Val*100/Total);
-}
-
-void TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const {
- if (Total.getUserTime())
- printVal(getUserTime(), Total.getUserTime(), OS);
- if (Total.getSystemTime())
- printVal(getSystemTime(), Total.getSystemTime(), OS);
- if (Total.getProcessTime())
- printVal(getProcessTime(), Total.getProcessTime(), OS);
- printVal(getWallTime(), Total.getWallTime(), OS);
-
- OS << " ";
-
- if (Total.getMemUsed())
- OS << format("%9" PRId64 " ", (int64_t)getMemUsed());
-}
-
-
-//===----------------------------------------------------------------------===//
-// NamedRegionTimer Implementation
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-typedef StringMap<Timer> Name2TimerMap;
-
-class Name2PairMap {
- StringMap<std::pair<TimerGroup*, Name2TimerMap> > Map;
-public:
- ~Name2PairMap() {
- for (StringMap<std::pair<TimerGroup*, Name2TimerMap> >::iterator
- I = Map.begin(), E = Map.end(); I != E; ++I)
- delete I->second.first;
- }
-
- Timer &get(StringRef Name, StringRef Description, StringRef GroupName,
- StringRef GroupDescription) {
- sys::SmartScopedLock<true> L(*TimerLock);
-
- std::pair<TimerGroup*, Name2TimerMap> &GroupEntry = Map[GroupName];
-
- if (!GroupEntry.first)
- GroupEntry.first = new TimerGroup(GroupName, GroupDescription);
-
- Timer &T = GroupEntry.second[Name];
- if (!T.isInitialized())
- T.init(Name, Description, *GroupEntry.first);
- return T;
- }
-};
-
-}
-
-static ManagedStatic<Name2PairMap> NamedGroupedTimers;
-
-NamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef Description,
- StringRef GroupName,
- StringRef GroupDescription, bool Enabled)
- : TimeRegion(!Enabled ? nullptr
- : &NamedGroupedTimers->get(Name, Description, GroupName,
- GroupDescription)) {}
-
-//===----------------------------------------------------------------------===//
-// TimerGroup Implementation
-//===----------------------------------------------------------------------===//
-
-/// This is the global list of TimerGroups, maintained by the TimerGroup
-/// ctor/dtor and is protected by the TimerLock lock.
-static TimerGroup *TimerGroupList = nullptr;
-
-TimerGroup::TimerGroup(StringRef Name, StringRef Description)
- : Name(Name.begin(), Name.end()),
- Description(Description.begin(), Description.end()) {
- // Add the group to TimerGroupList.
- sys::SmartScopedLock<true> L(*TimerLock);
- if (TimerGroupList)
- TimerGroupList->Prev = &Next;
- Next = TimerGroupList;
- Prev = &TimerGroupList;
- TimerGroupList = this;
-}
-
-TimerGroup::TimerGroup(StringRef Name, StringRef Description,
- const StringMap<TimeRecord> &Records)
- : TimerGroup(Name, Description) {
- TimersToPrint.reserve(Records.size());
- for (const auto &P : Records)
- TimersToPrint.emplace_back(P.getValue(), P.getKey(), P.getKey());
- assert(TimersToPrint.size() == Records.size() && "Size mismatch");
-}
-
-TimerGroup::~TimerGroup() {
- // If the timer group is destroyed before the timers it owns, accumulate and
- // print the timing data.
- while (FirstTimer)
- removeTimer(*FirstTimer);
-
- // Remove the group from the TimerGroupList.
- sys::SmartScopedLock<true> L(*TimerLock);
- *Prev = Next;
- if (Next)
- Next->Prev = Prev;
-}
-
-
-void TimerGroup::removeTimer(Timer &T) {
- sys::SmartScopedLock<true> L(*TimerLock);
-
- // If the timer was started, move its data to TimersToPrint.
- if (T.hasTriggered())
- TimersToPrint.emplace_back(T.Time, T.Name, T.Description);
-
- T.TG = nullptr;
-
- // Unlink the timer from our list.
- *T.Prev = T.Next;
- if (T.Next)
- T.Next->Prev = T.Prev;
-
- // Print the report when all timers in this group are destroyed if some of
- // them were started.
- if (FirstTimer || TimersToPrint.empty())
- return;
-
- std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
- PrintQueuedTimers(*OutStream);
-}
-
-void TimerGroup::addTimer(Timer &T) {
- sys::SmartScopedLock<true> L(*TimerLock);
-
- // Add the timer to our list.
- if (FirstTimer)
- FirstTimer->Prev = &T.Next;
- T.Next = FirstTimer;
- T.Prev = &FirstTimer;
- FirstTimer = &T;
-}
-
-void TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
- // Sort the timers in descending order by amount of time taken.
- llvm::sort(TimersToPrint);
-
- TimeRecord Total;
- for (const PrintRecord &Record : TimersToPrint)
- Total += Record.Time;
-
- // Print out timing header.
- OS << "===" << std::string(73, '-') << "===\n";
- // Figure out how many spaces to indent TimerGroup name.
- unsigned Padding = (80-Description.length())/2;
- if (Padding > 80) Padding = 0; // Don't allow "negative" numbers
- OS.indent(Padding) << Description << '\n';
- OS << "===" << std::string(73, '-') << "===\n";
-
- // If this is not an collection of ungrouped times, print the total time.
- // Ungrouped timers don't really make sense to add up. We still print the
- // TOTAL line to make the percentages make sense.
- if (this != getDefaultTimerGroup())
- OS << format(" Total Execution Time: %5.4f seconds (%5.4f wall clock)\n",
- Total.getProcessTime(), Total.getWallTime());
- OS << '\n';
-
- if (Total.getUserTime())
- OS << " ---User Time---";
- if (Total.getSystemTime())
- OS << " --System Time--";
- if (Total.getProcessTime())
- OS << " --User+System--";
- OS << " ---Wall Time---";
- if (Total.getMemUsed())
- OS << " ---Mem---";
- OS << " --- Name ---\n";
-
- // Loop through all of the timing data, printing it out.
- for (const PrintRecord &Record : make_range(TimersToPrint.rbegin(),
- TimersToPrint.rend())) {
- Record.Time.print(Total, OS);
- OS << Record.Description << '\n';
- }
-
- Total.print(Total, OS);
- OS << "Total\n\n";
- OS.flush();
-
- TimersToPrint.clear();
-}
-
-void TimerGroup::prepareToPrintList() {
- // See if any of our timers were started, if so add them to TimersToPrint.
- for (Timer *T = FirstTimer; T; T = T->Next) {
- if (!T->hasTriggered()) continue;
- bool WasRunning = T->isRunning();
- if (WasRunning)
- T->stopTimer();
-
- TimersToPrint.emplace_back(T->Time, T->Name, T->Description);
-
- if (WasRunning)
- T->startTimer();
- }
-}
-
-void TimerGroup::print(raw_ostream &OS) {
- sys::SmartScopedLock<true> L(*TimerLock);
-
- prepareToPrintList();
-
- // If any timers were started, print the group.
- if (!TimersToPrint.empty())
- PrintQueuedTimers(OS);
-}
-
-void TimerGroup::clear() {
- sys::SmartScopedLock<true> L(*TimerLock);
- for (Timer *T = FirstTimer; T; T = T->Next)
- T->clear();
-}
-
-void TimerGroup::printAll(raw_ostream &OS) {
- sys::SmartScopedLock<true> L(*TimerLock);
-
- for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next)
- TG->print(OS);
-}
-
-void TimerGroup::clearAll() {
- sys::SmartScopedLock<true> L(*TimerLock);
- for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next)
- TG->clear();
-}
-
-void TimerGroup::printJSONValue(raw_ostream &OS, const PrintRecord &R,
- const char *suffix, double Value) {
- assert(yaml::needsQuotes(Name) == yaml::QuotingType::None &&
- "TimerGroup name should not need quotes");
- assert(yaml::needsQuotes(R.Name) == yaml::QuotingType::None &&
- "Timer name should not need quotes");
- constexpr auto max_digits10 = std::numeric_limits<double>::max_digits10;
- OS << "\t\"time." << Name << '.' << R.Name << suffix
- << "\": " << format("%.*e", max_digits10 - 1, Value);
-}
-
-const char *TimerGroup::printJSONValues(raw_ostream &OS, const char *delim) {
- sys::SmartScopedLock<true> L(*TimerLock);
-
- prepareToPrintList();
- for (const PrintRecord &R : TimersToPrint) {
- OS << delim;
- delim = ",\n";
-
- const TimeRecord &T = R.Time;
- printJSONValue(OS, R, ".wall", T.getWallTime());
- OS << delim;
- printJSONValue(OS, R, ".user", T.getUserTime());
- OS << delim;
- printJSONValue(OS, R, ".sys", T.getSystemTime());
- if (T.getMemUsed()) {
- OS << delim;
- printJSONValue(OS, R, ".mem", T.getMemUsed());
- }
- }
- TimersToPrint.clear();
- return delim;
-}
-
-const char *TimerGroup::printAllJSONValues(raw_ostream &OS, const char *delim) {
- sys::SmartScopedLock<true> L(*TimerLock);
- for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next)
- delim = TG->printJSONValues(OS, delim);
- return delim;
-}
-
-void TimerGroup::ConstructTimerLists() {
- (void)*NamedGroupedTimers;
-}
diff --git a/gnu/llvm/lib/Support/ToolOutputFile.cpp b/gnu/llvm/lib/Support/ToolOutputFile.cpp
deleted file mode 100644
index e12d9e824f7..00000000000
--- a/gnu/llvm/lib/Support/ToolOutputFile.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//===--- ToolOutputFile.cpp - Implement the ToolOutputFile class --------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This implements the ToolOutputFile class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ToolOutputFile.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Signals.h"
-using namespace llvm;
-
-ToolOutputFile::CleanupInstaller::CleanupInstaller(StringRef Filename)
- : Filename(Filename), Keep(false) {
- // Arrange for the file to be deleted if the process is killed.
- if (Filename != "-")
- sys::RemoveFileOnSignal(Filename);
-}
-
-ToolOutputFile::CleanupInstaller::~CleanupInstaller() {
- // Delete the file if the client hasn't told us not to.
- if (!Keep && Filename != "-")
- sys::fs::remove(Filename);
-
- // Ok, the file is successfully written and closed, or deleted. There's no
- // further need to clean it up on signals.
- if (Filename != "-")
- sys::DontRemoveFileOnSignal(Filename);
-}
-
-ToolOutputFile::ToolOutputFile(StringRef Filename, std::error_code &EC,
- sys::fs::OpenFlags Flags)
- : Installer(Filename), OS(Filename, EC, Flags) {
- // If open fails, no cleanup is needed.
- if (EC)
- Installer.Keep = true;
-}
-
-ToolOutputFile::ToolOutputFile(StringRef Filename, int FD)
- : Installer(Filename), OS(FD, true) {}
diff --git a/gnu/llvm/lib/Support/TrigramIndex.cpp b/gnu/llvm/lib/Support/TrigramIndex.cpp
deleted file mode 100644
index 721763c8852..00000000000
--- a/gnu/llvm/lib/Support/TrigramIndex.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-//===-- TrigramIndex.cpp - a heuristic for SpecialCaseList ----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// TrigramIndex implements a heuristic for SpecialCaseList that allows to
-// filter out ~99% incoming queries when all regular expressions in the
-// SpecialCaseList are simple wildcards with '*' and '.'. If rules are more
-// complicated, the check is defeated and it will always pass the queries to a
-// full regex.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/TrigramIndex.h"
-#include "llvm/ADT/SmallVector.h"
-
-#include <set>
-#include <string>
-#include <unordered_map>
-
-using namespace llvm;
-
-static const char RegexAdvancedMetachars[] = "()^$|+?[]\\{}";
-
-static bool isAdvancedMetachar(unsigned Char) {
- return strchr(RegexAdvancedMetachars, Char) != nullptr;
-}
-
-void TrigramIndex::insert(std::string Regex) {
- if (Defeated) return;
- std::set<unsigned> Was;
- unsigned Cnt = 0;
- unsigned Tri = 0;
- unsigned Len = 0;
- bool Escaped = false;
- for (unsigned Char : Regex) {
- if (!Escaped) {
- // Regular expressions allow escaping symbols by preceding it with '\'.
- if (Char == '\\') {
- Escaped = true;
- continue;
- }
- if (isAdvancedMetachar(Char)) {
- // This is a more complicated regex than we can handle here.
- Defeated = true;
- return;
- }
- if (Char == '.' || Char == '*') {
- Tri = 0;
- Len = 0;
- continue;
- }
- }
- if (Escaped && Char >= '1' && Char <= '9') {
- Defeated = true;
- return;
- }
- // We have already handled escaping and can reset the flag.
- Escaped = false;
- Tri = ((Tri << 8) + Char) & 0xFFFFFF;
- Len++;
- if (Len < 3)
- continue;
- // We don't want the index to grow too much for the popular trigrams,
- // as they are weak signals. It's ok to still require them for the
- // rules we have already processed. It's just a small additional
- // computational cost.
- if (Index[Tri].size() >= 4)
- continue;
- Cnt++;
- if (!Was.count(Tri)) {
- // Adding the current rule to the index.
- Index[Tri].push_back(Counts.size());
- Was.insert(Tri);
- }
- }
- if (!Cnt) {
- // This rule does not have remarkable trigrams to rely on.
- // We have to always call the full regex chain.
- Defeated = true;
- return;
- }
- Counts.push_back(Cnt);
-}
-
-bool TrigramIndex::isDefinitelyOut(StringRef Query) const {
- if (Defeated)
- return false;
- std::vector<unsigned> CurCounts(Counts.size());
- unsigned Tri = 0;
- for (size_t I = 0; I < Query.size(); I++) {
- Tri = ((Tri << 8) + Query[I]) & 0xFFFFFF;
- if (I < 2)
- continue;
- const auto &II = Index.find(Tri);
- if (II == Index.end())
- continue;
- for (size_t J : II->second) {
- CurCounts[J]++;
- // If we have reached a desired limit, we have to look at the query
- // more closely by running a full regex.
- if (CurCounts[J] >= Counts[J])
- return false;
- }
- }
- return true;
-}
diff --git a/gnu/llvm/lib/Support/Triple.cpp b/gnu/llvm/lib/Support/Triple.cpp
deleted file mode 100644
index 26d9327f620..00000000000
--- a/gnu/llvm/lib/Support/Triple.cpp
+++ /dev/null
@@ -1,1630 +0,0 @@
-//===--- Triple.cpp - Target triple helper class --------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/TargetParser.h"
-#include <cstring>
-using namespace llvm;
-
-StringRef Triple::getArchTypeName(ArchType Kind) {
- switch (Kind) {
- case UnknownArch: return "unknown";
-
- case aarch64: return "aarch64";
- case aarch64_be: return "aarch64_be";
- case arm: return "arm";
- case armeb: return "armeb";
- case arc: return "arc";
- case avr: return "avr";
- case bpfel: return "bpfel";
- case bpfeb: return "bpfeb";
- case hexagon: return "hexagon";
- case mips: return "mips";
- case mipsel: return "mipsel";
- case mips64: return "mips64";
- case mips64el: return "mips64el";
- case msp430: return "msp430";
- case ppc64: return "powerpc64";
- case ppc64le: return "powerpc64le";
- case ppc: return "powerpc";
- case r600: return "r600";
- case amdgcn: return "amdgcn";
- case riscv32: return "riscv32";
- case riscv64: return "riscv64";
- case sparc: return "sparc";
- case sparcv9: return "sparcv9";
- case sparcel: return "sparcel";
- case systemz: return "s390x";
- case tce: return "tce";
- case tcele: return "tcele";
- case thumb: return "thumb";
- case thumbeb: return "thumbeb";
- case x86: return "i386";
- case x86_64: return "x86_64";
- case xcore: return "xcore";
- case nvptx: return "nvptx";
- case nvptx64: return "nvptx64";
- case le32: return "le32";
- case le64: return "le64";
- case amdil: return "amdil";
- case amdil64: return "amdil64";
- case hsail: return "hsail";
- case hsail64: return "hsail64";
- case spir: return "spir";
- case spir64: return "spir64";
- case kalimba: return "kalimba";
- case lanai: return "lanai";
- case shave: return "shave";
- case wasm32: return "wasm32";
- case wasm64: return "wasm64";
- case renderscript32: return "renderscript32";
- case renderscript64: return "renderscript64";
- }
-
- llvm_unreachable("Invalid ArchType!");
-}
-
-StringRef Triple::getArchTypePrefix(ArchType Kind) {
- switch (Kind) {
- default:
- return StringRef();
-
- case aarch64:
- case aarch64_be: return "aarch64";
-
- case arc: return "arc";
-
- case arm:
- case armeb:
- case thumb:
- case thumbeb: return "arm";
-
- case avr: return "avr";
-
- case ppc64:
- case ppc64le:
- case ppc: return "ppc";
-
- case mips:
- case mipsel:
- case mips64:
- case mips64el: return "mips";
-
- case hexagon: return "hexagon";
-
- case amdgcn: return "amdgcn";
- case r600: return "r600";
-
- case bpfel:
- case bpfeb: return "bpf";
-
- case sparcv9:
- case sparcel:
- case sparc: return "sparc";
-
- case systemz: return "s390";
-
- case x86:
- case x86_64: return "x86";
-
- case xcore: return "xcore";
-
- // NVPTX intrinsics are namespaced under nvvm.
- case nvptx: return "nvvm";
- case nvptx64: return "nvvm";
-
- case le32: return "le32";
- case le64: return "le64";
-
- case amdil:
- case amdil64: return "amdil";
-
- case hsail:
- case hsail64: return "hsail";
-
- case spir:
- case spir64: return "spir";
- case kalimba: return "kalimba";
- case lanai: return "lanai";
- case shave: return "shave";
- case wasm32:
- case wasm64: return "wasm";
-
- case riscv32:
- case riscv64: return "riscv";
- }
-}
-
-StringRef Triple::getVendorTypeName(VendorType Kind) {
- switch (Kind) {
- case UnknownVendor: return "unknown";
-
- case Apple: return "apple";
- case PC: return "pc";
- case SCEI: return "scei";
- case BGP: return "bgp";
- case BGQ: return "bgq";
- case Freescale: return "fsl";
- case IBM: return "ibm";
- case ImaginationTechnologies: return "img";
- case MipsTechnologies: return "mti";
- case NVIDIA: return "nvidia";
- case CSR: return "csr";
- case Myriad: return "myriad";
- case AMD: return "amd";
- case Mesa: return "mesa";
- case SUSE: return "suse";
- case OpenEmbedded: return "oe";
- }
-
- llvm_unreachable("Invalid VendorType!");
-}
-
-StringRef Triple::getOSTypeName(OSType Kind) {
- switch (Kind) {
- case UnknownOS: return "unknown";
-
- case Ananas: return "ananas";
- case CloudABI: return "cloudabi";
- case Darwin: return "darwin";
- case DragonFly: return "dragonfly";
- case FreeBSD: return "freebsd";
- case Fuchsia: return "fuchsia";
- case IOS: return "ios";
- case KFreeBSD: return "kfreebsd";
- case Linux: return "linux";
- case Lv2: return "lv2";
- case MacOSX: return "macosx";
- case NetBSD: return "netbsd";
- case OpenBSD: return "openbsd";
- case Solaris: return "solaris";
- case Win32: return "windows";
- case Haiku: return "haiku";
- case Minix: return "minix";
- case RTEMS: return "rtems";
- case NaCl: return "nacl";
- case CNK: return "cnk";
- case AIX: return "aix";
- case CUDA: return "cuda";
- case NVCL: return "nvcl";
- case AMDHSA: return "amdhsa";
- case PS4: return "ps4";
- case ELFIAMCU: return "elfiamcu";
- case TvOS: return "tvos";
- case WatchOS: return "watchos";
- case Mesa3D: return "mesa3d";
- case Contiki: return "contiki";
- case AMDPAL: return "amdpal";
- case HermitCore: return "hermit";
- case Hurd: return "hurd";
- case WASI: return "wasi";
- }
-
- llvm_unreachable("Invalid OSType");
-}
-
-StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) {
- switch (Kind) {
- case UnknownEnvironment: return "unknown";
- case GNU: return "gnu";
- case GNUABIN32: return "gnuabin32";
- case GNUABI64: return "gnuabi64";
- case GNUEABIHF: return "gnueabihf";
- case GNUEABI: return "gnueabi";
- case GNUX32: return "gnux32";
- case CODE16: return "code16";
- case EABI: return "eabi";
- case EABIHF: return "eabihf";
- case Android: return "android";
- case Musl: return "musl";
- case MuslEABI: return "musleabi";
- case MuslEABIHF: return "musleabihf";
- case MSVC: return "msvc";
- case Itanium: return "itanium";
- case Cygnus: return "cygnus";
- case CoreCLR: return "coreclr";
- case Simulator: return "simulator";
- }
-
- llvm_unreachable("Invalid EnvironmentType!");
-}
-
-static Triple::ArchType parseBPFArch(StringRef ArchName) {
- if (ArchName.equals("bpf")) {
- if (sys::IsLittleEndianHost)
- return Triple::bpfel;
- else
- return Triple::bpfeb;
- } else if (ArchName.equals("bpf_be") || ArchName.equals("bpfeb")) {
- return Triple::bpfeb;
- } else if (ArchName.equals("bpf_le") || ArchName.equals("bpfel")) {
- return Triple::bpfel;
- } else {
- return Triple::UnknownArch;
- }
-}
-
-Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
- Triple::ArchType BPFArch(parseBPFArch(Name));
- return StringSwitch<Triple::ArchType>(Name)
- .Case("aarch64", aarch64)
- .Case("aarch64_be", aarch64_be)
- .Case("arc", arc)
- .Case("arm64", aarch64) // "arm64" is an alias for "aarch64"
- .Case("arm", arm)
- .Case("armeb", armeb)
- .Case("avr", avr)
- .StartsWith("bpf", BPFArch)
- .Case("mips", mips)
- .Case("mipsel", mipsel)
- .Case("mips64", mips64)
- .Case("mips64el", mips64el)
- .Case("msp430", msp430)
- .Case("ppc64", ppc64)
- .Case("ppc32", ppc)
- .Case("ppc", ppc)
- .Case("ppc64le", ppc64le)
- .Case("r600", r600)
- .Case("amdgcn", amdgcn)
- .Case("riscv32", riscv32)
- .Case("riscv64", riscv64)
- .Case("hexagon", hexagon)
- .Case("sparc", sparc)
- .Case("sparcel", sparcel)
- .Case("sparcv9", sparcv9)
- .Case("systemz", systemz)
- .Case("tce", tce)
- .Case("tcele", tcele)
- .Case("thumb", thumb)
- .Case("thumbeb", thumbeb)
- .Case("x86", x86)
- .Case("x86-64", x86_64)
- .Case("xcore", xcore)
- .Case("nvptx", nvptx)
- .Case("nvptx64", nvptx64)
- .Case("le32", le32)
- .Case("le64", le64)
- .Case("amdil", amdil)
- .Case("amdil64", amdil64)
- .Case("hsail", hsail)
- .Case("hsail64", hsail64)
- .Case("spir", spir)
- .Case("spir64", spir64)
- .Case("kalimba", kalimba)
- .Case("lanai", lanai)
- .Case("shave", shave)
- .Case("wasm32", wasm32)
- .Case("wasm64", wasm64)
- .Case("renderscript32", renderscript32)
- .Case("renderscript64", renderscript64)
- .Default(UnknownArch);
-}
-
-static Triple::ArchType parseARMArch(StringRef ArchName) {
- ARM::ISAKind ISA = ARM::parseArchISA(ArchName);
- ARM::EndianKind ENDIAN = ARM::parseArchEndian(ArchName);
-
- Triple::ArchType arch = Triple::UnknownArch;
- switch (ENDIAN) {
- case ARM::EndianKind::LITTLE: {
- switch (ISA) {
- case ARM::ISAKind::ARM:
- arch = Triple::arm;
- break;
- case ARM::ISAKind::THUMB:
- arch = Triple::thumb;
- break;
- case ARM::ISAKind::AARCH64:
- arch = Triple::aarch64;
- break;
- case ARM::ISAKind::INVALID:
- break;
- }
- break;
- }
- case ARM::EndianKind::BIG: {
- switch (ISA) {
- case ARM::ISAKind::ARM:
- arch = Triple::armeb;
- break;
- case ARM::ISAKind::THUMB:
- arch = Triple::thumbeb;
- break;
- case ARM::ISAKind::AARCH64:
- arch = Triple::aarch64_be;
- break;
- case ARM::ISAKind::INVALID:
- break;
- }
- break;
- }
- case ARM::EndianKind::INVALID: {
- break;
- }
- }
-
- ArchName = ARM::getCanonicalArchName(ArchName);
- if (ArchName.empty())
- return Triple::UnknownArch;
-
- // Thumb only exists in v4+
- if (ISA == ARM::ISAKind::THUMB &&
- (ArchName.startswith("v2") || ArchName.startswith("v3")))
- return Triple::UnknownArch;
-
- // Thumb only for v6m
- ARM::ProfileKind Profile = ARM::parseArchProfile(ArchName);
- unsigned Version = ARM::parseArchVersion(ArchName);
- if (Profile == ARM::ProfileKind::M && Version == 6) {
- if (ENDIAN == ARM::EndianKind::BIG)
- return Triple::thumbeb;
- else
- return Triple::thumb;
- }
-
- return arch;
-}
-
-static Triple::ArchType parseArch(StringRef ArchName) {
- auto AT = StringSwitch<Triple::ArchType>(ArchName)
- .Cases("i386", "i486", "i586", "i686", Triple::x86)
- // FIXME: Do we need to support these?
- .Cases("i786", "i886", "i986", Triple::x86)
- .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64)
- .Cases("powerpc", "ppc", "ppc32", Triple::ppc)
- .Cases("powerpc64", "ppu", "ppc64", Triple::ppc64)
- .Cases("powerpc64le", "ppc64le", Triple::ppc64le)
- .Case("xscale", Triple::arm)
- .Case("xscaleeb", Triple::armeb)
- .Case("aarch64", Triple::aarch64)
- .Case("aarch64_be", Triple::aarch64_be)
- .Case("arc", Triple::arc)
- .Case("arm64", Triple::aarch64)
- .Case("arm", Triple::arm)
- .Case("armeb", Triple::armeb)
- .Case("thumb", Triple::thumb)
- .Case("thumbeb", Triple::thumbeb)
- .Case("avr", Triple::avr)
- .Case("msp430", Triple::msp430)
- .Cases("mips", "mipseb", "mipsallegrex", "mipsisa32r6",
- "mipsr6", Triple::mips)
- .Cases("mipsel", "mipsallegrexel", "mipsisa32r6el", "mipsr6el",
- Triple::mipsel)
- .Cases("mips64", "mips64eb", "mipsn32", "mipsisa64r6",
- "mips64r6", "mipsn32r6", Triple::mips64)
- .Cases("mips64el", "mipsn32el", "mipsisa64r6el", "mips64r6el",
- "mipsn32r6el", Triple::mips64el)
- .Case("r600", Triple::r600)
- .Case("amdgcn", Triple::amdgcn)
- .Case("riscv32", Triple::riscv32)
- .Case("riscv64", Triple::riscv64)
- .Case("hexagon", Triple::hexagon)
- .Cases("s390x", "systemz", Triple::systemz)
- .Case("sparc", Triple::sparc)
- .Case("sparcel", Triple::sparcel)
- .Cases("sparcv9", "sparc64", Triple::sparcv9)
- .Case("tce", Triple::tce)
- .Case("tcele", Triple::tcele)
- .Case("xcore", Triple::xcore)
- .Case("nvptx", Triple::nvptx)
- .Case("nvptx64", Triple::nvptx64)
- .Case("le32", Triple::le32)
- .Case("le64", Triple::le64)
- .Case("amdil", Triple::amdil)
- .Case("amdil64", Triple::amdil64)
- .Case("hsail", Triple::hsail)
- .Case("hsail64", Triple::hsail64)
- .Case("spir", Triple::spir)
- .Case("spir64", Triple::spir64)
- .StartsWith("kalimba", Triple::kalimba)
- .Case("lanai", Triple::lanai)
- .Case("shave", Triple::shave)
- .Case("wasm32", Triple::wasm32)
- .Case("wasm64", Triple::wasm64)
- .Case("renderscript32", Triple::renderscript32)
- .Case("renderscript64", Triple::renderscript64)
- .Default(Triple::UnknownArch);
-
- // Some architectures require special parsing logic just to compute the
- // ArchType result.
- if (AT == Triple::UnknownArch) {
- if (ArchName.startswith("arm") || ArchName.startswith("thumb") ||
- ArchName.startswith("aarch64"))
- return parseARMArch(ArchName);
- if (ArchName.startswith("bpf"))
- return parseBPFArch(ArchName);
- }
-
- return AT;
-}
-
-static Triple::VendorType parseVendor(StringRef VendorName) {
- return StringSwitch<Triple::VendorType>(VendorName)
- .Case("apple", Triple::Apple)
- .Case("pc", Triple::PC)
- .Case("scei", Triple::SCEI)
- .Case("bgp", Triple::BGP)
- .Case("bgq", Triple::BGQ)
- .Case("fsl", Triple::Freescale)
- .Case("ibm", Triple::IBM)
- .Case("img", Triple::ImaginationTechnologies)
- .Case("mti", Triple::MipsTechnologies)
- .Case("nvidia", Triple::NVIDIA)
- .Case("csr", Triple::CSR)
- .Case("myriad", Triple::Myriad)
- .Case("amd", Triple::AMD)
- .Case("mesa", Triple::Mesa)
- .Case("suse", Triple::SUSE)
- .Case("oe", Triple::OpenEmbedded)
- .Default(Triple::UnknownVendor);
-}
-
-static Triple::OSType parseOS(StringRef OSName) {
- return StringSwitch<Triple::OSType>(OSName)
- .StartsWith("ananas", Triple::Ananas)
- .StartsWith("cloudabi", Triple::CloudABI)
- .StartsWith("darwin", Triple::Darwin)
- .StartsWith("dragonfly", Triple::DragonFly)
- .StartsWith("freebsd", Triple::FreeBSD)
- .StartsWith("fuchsia", Triple::Fuchsia)
- .StartsWith("ios", Triple::IOS)
- .StartsWith("kfreebsd", Triple::KFreeBSD)
- .StartsWith("linux", Triple::Linux)
- .StartsWith("lv2", Triple::Lv2)
- .StartsWith("macos", Triple::MacOSX)
- .StartsWith("netbsd", Triple::NetBSD)
- .StartsWith("openbsd", Triple::OpenBSD)
- .StartsWith("solaris", Triple::Solaris)
- .StartsWith("win32", Triple::Win32)
- .StartsWith("windows", Triple::Win32)
- .StartsWith("haiku", Triple::Haiku)
- .StartsWith("minix", Triple::Minix)
- .StartsWith("rtems", Triple::RTEMS)
- .StartsWith("nacl", Triple::NaCl)
- .StartsWith("cnk", Triple::CNK)
- .StartsWith("aix", Triple::AIX)
- .StartsWith("cuda", Triple::CUDA)
- .StartsWith("nvcl", Triple::NVCL)
- .StartsWith("amdhsa", Triple::AMDHSA)
- .StartsWith("ps4", Triple::PS4)
- .StartsWith("elfiamcu", Triple::ELFIAMCU)
- .StartsWith("tvos", Triple::TvOS)
- .StartsWith("watchos", Triple::WatchOS)
- .StartsWith("mesa3d", Triple::Mesa3D)
- .StartsWith("contiki", Triple::Contiki)
- .StartsWith("amdpal", Triple::AMDPAL)
- .StartsWith("hermit", Triple::HermitCore)
- .StartsWith("hurd", Triple::Hurd)
- .StartsWith("wasi", Triple::WASI)
- .Default(Triple::UnknownOS);
-}
-
-static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) {
- return StringSwitch<Triple::EnvironmentType>(EnvironmentName)
- .StartsWith("eabihf", Triple::EABIHF)
- .StartsWith("eabi", Triple::EABI)
- .StartsWith("gnuabin32", Triple::GNUABIN32)
- .StartsWith("gnuabi64", Triple::GNUABI64)
- .StartsWith("gnueabihf", Triple::GNUEABIHF)
- .StartsWith("gnueabi", Triple::GNUEABI)
- .StartsWith("gnux32", Triple::GNUX32)
- .StartsWith("code16", Triple::CODE16)
- .StartsWith("gnu", Triple::GNU)
- .StartsWith("android", Triple::Android)
- .StartsWith("musleabihf", Triple::MuslEABIHF)
- .StartsWith("musleabi", Triple::MuslEABI)
- .StartsWith("musl", Triple::Musl)
- .StartsWith("msvc", Triple::MSVC)
- .StartsWith("itanium", Triple::Itanium)
- .StartsWith("cygnus", Triple::Cygnus)
- .StartsWith("coreclr", Triple::CoreCLR)
- .StartsWith("simulator", Triple::Simulator)
- .Default(Triple::UnknownEnvironment);
-}
-
-static Triple::ObjectFormatType parseFormat(StringRef EnvironmentName) {
- return StringSwitch<Triple::ObjectFormatType>(EnvironmentName)
- .EndsWith("coff", Triple::COFF)
- .EndsWith("elf", Triple::ELF)
- .EndsWith("macho", Triple::MachO)
- .EndsWith("wasm", Triple::Wasm)
- .Default(Triple::UnknownObjectFormat);
-}
-
-static Triple::SubArchType parseSubArch(StringRef SubArchName) {
- if (SubArchName.startswith("mips") &&
- (SubArchName.endswith("r6el") || SubArchName.endswith("r6")))
- return Triple::MipsSubArch_r6;
-
- StringRef ARMSubArch = ARM::getCanonicalArchName(SubArchName);
-
- // For now, this is the small part. Early return.
- if (ARMSubArch.empty())
- return StringSwitch<Triple::SubArchType>(SubArchName)
- .EndsWith("kalimba3", Triple::KalimbaSubArch_v3)
- .EndsWith("kalimba4", Triple::KalimbaSubArch_v4)
- .EndsWith("kalimba5", Triple::KalimbaSubArch_v5)
- .Default(Triple::NoSubArch);
-
- // ARM sub arch.
- switch(ARM::parseArch(ARMSubArch)) {
- case ARM::ArchKind::ARMV4:
- return Triple::NoSubArch;
- case ARM::ArchKind::ARMV4T:
- return Triple::ARMSubArch_v4t;
- case ARM::ArchKind::ARMV5T:
- return Triple::ARMSubArch_v5;
- case ARM::ArchKind::ARMV5TE:
- case ARM::ArchKind::IWMMXT:
- case ARM::ArchKind::IWMMXT2:
- case ARM::ArchKind::XSCALE:
- case ARM::ArchKind::ARMV5TEJ:
- return Triple::ARMSubArch_v5te;
- case ARM::ArchKind::ARMV6:
- return Triple::ARMSubArch_v6;
- case ARM::ArchKind::ARMV6K:
- case ARM::ArchKind::ARMV6KZ:
- return Triple::ARMSubArch_v6k;
- case ARM::ArchKind::ARMV6T2:
- return Triple::ARMSubArch_v6t2;
- case ARM::ArchKind::ARMV6M:
- return Triple::ARMSubArch_v6m;
- case ARM::ArchKind::ARMV7A:
- case ARM::ArchKind::ARMV7R:
- return Triple::ARMSubArch_v7;
- case ARM::ArchKind::ARMV7VE:
- return Triple::ARMSubArch_v7ve;
- case ARM::ArchKind::ARMV7K:
- return Triple::ARMSubArch_v7k;
- case ARM::ArchKind::ARMV7M:
- return Triple::ARMSubArch_v7m;
- case ARM::ArchKind::ARMV7S:
- return Triple::ARMSubArch_v7s;
- case ARM::ArchKind::ARMV7EM:
- return Triple::ARMSubArch_v7em;
- case ARM::ArchKind::ARMV8A:
- return Triple::ARMSubArch_v8;
- case ARM::ArchKind::ARMV8_1A:
- return Triple::ARMSubArch_v8_1a;
- case ARM::ArchKind::ARMV8_2A:
- return Triple::ARMSubArch_v8_2a;
- case ARM::ArchKind::ARMV8_3A:
- return Triple::ARMSubArch_v8_3a;
- case ARM::ArchKind::ARMV8_4A:
- return Triple::ARMSubArch_v8_4a;
- case ARM::ArchKind::ARMV8_5A:
- return Triple::ARMSubArch_v8_5a;
- case ARM::ArchKind::ARMV8R:
- return Triple::ARMSubArch_v8r;
- case ARM::ArchKind::ARMV8MBaseline:
- return Triple::ARMSubArch_v8m_baseline;
- case ARM::ArchKind::ARMV8MMainline:
- return Triple::ARMSubArch_v8m_mainline;
- default:
- return Triple::NoSubArch;
- }
-}
-
-static StringRef getObjectFormatTypeName(Triple::ObjectFormatType Kind) {
- switch (Kind) {
- case Triple::UnknownObjectFormat: return "";
- case Triple::COFF: return "coff";
- case Triple::ELF: return "elf";
- case Triple::MachO: return "macho";
- case Triple::Wasm: return "wasm";
- }
- llvm_unreachable("unknown object format type");
-}
-
-static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
- switch (T.getArch()) {
- case Triple::UnknownArch:
- case Triple::aarch64:
- case Triple::arm:
- case Triple::thumb:
- case Triple::x86:
- case Triple::x86_64:
- if (T.isOSDarwin())
- return Triple::MachO;
- else if (T.isOSWindows())
- return Triple::COFF;
- return Triple::ELF;
-
- case Triple::aarch64_be:
- case Triple::arc:
- case Triple::amdgcn:
- case Triple::amdil:
- case Triple::amdil64:
- case Triple::armeb:
- case Triple::avr:
- case Triple::bpfeb:
- case Triple::bpfel:
- case Triple::hexagon:
- case Triple::lanai:
- case Triple::hsail:
- case Triple::hsail64:
- case Triple::kalimba:
- case Triple::le32:
- case Triple::le64:
- case Triple::mips:
- case Triple::mips64:
- case Triple::mips64el:
- case Triple::mipsel:
- case Triple::msp430:
- case Triple::nvptx:
- case Triple::nvptx64:
- case Triple::ppc64le:
- case Triple::r600:
- case Triple::renderscript32:
- case Triple::renderscript64:
- case Triple::riscv32:
- case Triple::riscv64:
- case Triple::shave:
- case Triple::sparc:
- case Triple::sparcel:
- case Triple::sparcv9:
- case Triple::spir:
- case Triple::spir64:
- case Triple::systemz:
- case Triple::tce:
- case Triple::tcele:
- case Triple::thumbeb:
- case Triple::xcore:
- return Triple::ELF;
-
- case Triple::ppc:
- case Triple::ppc64:
- if (T.isOSDarwin())
- return Triple::MachO;
- return Triple::ELF;
-
- case Triple::wasm32:
- case Triple::wasm64:
- return Triple::Wasm;
- }
- llvm_unreachable("unknown architecture");
-}
-
-/// Construct a triple from the string representation provided.
-///
-/// This stores the string representation and parses the various pieces into
-/// enum members.
-Triple::Triple(const Twine &Str)
- : Data(Str.str()), Arch(UnknownArch), SubArch(NoSubArch),
- Vendor(UnknownVendor), OS(UnknownOS), Environment(UnknownEnvironment),
- ObjectFormat(UnknownObjectFormat) {
- // Do minimal parsing by hand here.
- SmallVector<StringRef, 4> Components;
- StringRef(Data).split(Components, '-', /*MaxSplit*/ 3);
- if (Components.size() > 0) {
- Arch = parseArch(Components[0]);
- SubArch = parseSubArch(Components[0]);
- if (Components.size() > 1) {
- Vendor = parseVendor(Components[1]);
- if (Components.size() > 2) {
- OS = parseOS(Components[2]);
- if (Components.size() > 3) {
- Environment = parseEnvironment(Components[3]);
- ObjectFormat = parseFormat(Components[3]);
- }
- }
- } else {
- Environment =
- StringSwitch<Triple::EnvironmentType>(Components[0])
- .StartsWith("mipsn32", Triple::GNUABIN32)
- .StartsWith("mips64", Triple::GNUABI64)
- .StartsWith("mipsisa64", Triple::GNUABI64)
- .StartsWith("mipsisa32", Triple::GNU)
- .Cases("mips", "mipsel", "mipsr6", "mipsr6el", Triple::GNU)
- .Default(UnknownEnvironment);
- }
- }
- if (ObjectFormat == UnknownObjectFormat)
- ObjectFormat = getDefaultFormat(*this);
-}
-
-/// Construct a triple from string representations of the architecture,
-/// vendor, and OS.
-///
-/// This joins each argument into a canonical string representation and parses
-/// them into enum members. It leaves the environment unknown and omits it from
-/// the string representation.
-Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr)
- : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr).str()),
- Arch(parseArch(ArchStr.str())),
- SubArch(parseSubArch(ArchStr.str())),
- Vendor(parseVendor(VendorStr.str())),
- OS(parseOS(OSStr.str())),
- Environment(), ObjectFormat(Triple::UnknownObjectFormat) {
- ObjectFormat = getDefaultFormat(*this);
-}
-
-/// Construct a triple from string representations of the architecture,
-/// vendor, OS, and environment.
-///
-/// This joins each argument into a canonical string representation and parses
-/// them into enum members.
-Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,
- const Twine &EnvironmentStr)
- : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr + Twine('-') +
- EnvironmentStr).str()),
- Arch(parseArch(ArchStr.str())),
- SubArch(parseSubArch(ArchStr.str())),
- Vendor(parseVendor(VendorStr.str())),
- OS(parseOS(OSStr.str())),
- Environment(parseEnvironment(EnvironmentStr.str())),
- ObjectFormat(parseFormat(EnvironmentStr.str())) {
- if (ObjectFormat == Triple::UnknownObjectFormat)
- ObjectFormat = getDefaultFormat(*this);
-}
-
-std::string Triple::normalize(StringRef Str) {
- bool IsMinGW32 = false;
- bool IsCygwin = false;
-
- // Parse into components.
- SmallVector<StringRef, 4> Components;
- Str.split(Components, '-');
-
- // If the first component corresponds to a known architecture, preferentially
- // use it for the architecture. If the second component corresponds to a
- // known vendor, preferentially use it for the vendor, etc. This avoids silly
- // component movement when a component parses as (eg) both a valid arch and a
- // valid os.
- ArchType Arch = UnknownArch;
- if (Components.size() > 0)
- Arch = parseArch(Components[0]);
- VendorType Vendor = UnknownVendor;
- if (Components.size() > 1)
- Vendor = parseVendor(Components[1]);
- OSType OS = UnknownOS;
- if (Components.size() > 2) {
- OS = parseOS(Components[2]);
- IsCygwin = Components[2].startswith("cygwin");
- IsMinGW32 = Components[2].startswith("mingw");
- }
- EnvironmentType Environment = UnknownEnvironment;
- if (Components.size() > 3)
- Environment = parseEnvironment(Components[3]);
- ObjectFormatType ObjectFormat = UnknownObjectFormat;
- if (Components.size() > 4)
- ObjectFormat = parseFormat(Components[4]);
-
- // Note which components are already in their final position. These will not
- // be moved.
- bool Found[4];
- Found[0] = Arch != UnknownArch;
- Found[1] = Vendor != UnknownVendor;
- Found[2] = OS != UnknownOS;
- Found[3] = Environment != UnknownEnvironment;
-
- // If they are not there already, permute the components into their canonical
- // positions by seeing if they parse as a valid architecture, and if so moving
- // the component to the architecture position etc.
- for (unsigned Pos = 0; Pos != array_lengthof(Found); ++Pos) {
- if (Found[Pos])
- continue; // Already in the canonical position.
-
- for (unsigned Idx = 0; Idx != Components.size(); ++Idx) {
- // Do not reparse any components that already matched.
- if (Idx < array_lengthof(Found) && Found[Idx])
- continue;
-
- // Does this component parse as valid for the target position?
- bool Valid = false;
- StringRef Comp = Components[Idx];
- switch (Pos) {
- default: llvm_unreachable("unexpected component type!");
- case 0:
- Arch = parseArch(Comp);
- Valid = Arch != UnknownArch;
- break;
- case 1:
- Vendor = parseVendor(Comp);
- Valid = Vendor != UnknownVendor;
- break;
- case 2:
- OS = parseOS(Comp);
- IsCygwin = Comp.startswith("cygwin");
- IsMinGW32 = Comp.startswith("mingw");
- Valid = OS != UnknownOS || IsCygwin || IsMinGW32;
- break;
- case 3:
- Environment = parseEnvironment(Comp);
- Valid = Environment != UnknownEnvironment;
- if (!Valid) {
- ObjectFormat = parseFormat(Comp);
- Valid = ObjectFormat != UnknownObjectFormat;
- }
- break;
- }
- if (!Valid)
- continue; // Nope, try the next component.
-
- // Move the component to the target position, pushing any non-fixed
- // components that are in the way to the right. This tends to give
- // good results in the common cases of a forgotten vendor component
- // or a wrongly positioned environment.
- if (Pos < Idx) {
- // Insert left, pushing the existing components to the right. For
- // example, a-b-i386 -> i386-a-b when moving i386 to the front.
- StringRef CurrentComponent(""); // The empty component.
- // Replace the component we are moving with an empty component.
- std::swap(CurrentComponent, Components[Idx]);
- // Insert the component being moved at Pos, displacing any existing
- // components to the right.
- for (unsigned i = Pos; !CurrentComponent.empty(); ++i) {
- // Skip over any fixed components.
- while (i < array_lengthof(Found) && Found[i])
- ++i;
- // Place the component at the new position, getting the component
- // that was at this position - it will be moved right.
- std::swap(CurrentComponent, Components[i]);
- }
- } else if (Pos > Idx) {
- // Push right by inserting empty components until the component at Idx
- // reaches the target position Pos. For example, pc-a -> -pc-a when
- // moving pc to the second position.
- do {
- // Insert one empty component at Idx.
- StringRef CurrentComponent(""); // The empty component.
- for (unsigned i = Idx; i < Components.size();) {
- // Place the component at the new position, getting the component
- // that was at this position - it will be moved right.
- std::swap(CurrentComponent, Components[i]);
- // If it was placed on top of an empty component then we are done.
- if (CurrentComponent.empty())
- break;
- // Advance to the next component, skipping any fixed components.
- while (++i < array_lengthof(Found) && Found[i])
- ;
- }
- // The last component was pushed off the end - append it.
- if (!CurrentComponent.empty())
- Components.push_back(CurrentComponent);
-
- // Advance Idx to the component's new position.
- while (++Idx < array_lengthof(Found) && Found[Idx])
- ;
- } while (Idx < Pos); // Add more until the final position is reached.
- }
- assert(Pos < Components.size() && Components[Pos] == Comp &&
- "Component moved wrong!");
- Found[Pos] = true;
- break;
- }
- }
-
- // Replace empty components with "unknown" value.
- for (unsigned i = 0, e = Components.size(); i < e; ++i) {
- if (Components[i].empty())
- Components[i] = "unknown";
- }
-
- // Special case logic goes here. At this point Arch, Vendor and OS have the
- // correct values for the computed components.
- std::string NormalizedEnvironment;
- if (Environment == Triple::Android && Components[3].startswith("androideabi")) {
- StringRef AndroidVersion = Components[3].drop_front(strlen("androideabi"));
- if (AndroidVersion.empty()) {
- Components[3] = "android";
- } else {
- NormalizedEnvironment = Twine("android", AndroidVersion).str();
- Components[3] = NormalizedEnvironment;
- }
- }
-
- // SUSE uses "gnueabi" to mean "gnueabihf"
- if (Vendor == Triple::SUSE && Environment == llvm::Triple::GNUEABI)
- Components[3] = "gnueabihf";
-
- if (OS == Triple::Win32) {
- Components.resize(4);
- Components[2] = "windows";
- if (Environment == UnknownEnvironment) {
- if (ObjectFormat == UnknownObjectFormat || ObjectFormat == Triple::COFF)
- Components[3] = "msvc";
- else
- Components[3] = getObjectFormatTypeName(ObjectFormat);
- }
- } else if (IsMinGW32) {
- Components.resize(4);
- Components[2] = "windows";
- Components[3] = "gnu";
- } else if (IsCygwin) {
- Components.resize(4);
- Components[2] = "windows";
- Components[3] = "cygnus";
- }
- if (IsMinGW32 || IsCygwin ||
- (OS == Triple::Win32 && Environment != UnknownEnvironment)) {
- if (ObjectFormat != UnknownObjectFormat && ObjectFormat != Triple::COFF) {
- Components.resize(5);
- Components[4] = getObjectFormatTypeName(ObjectFormat);
- }
- }
-
- // Stick the corrected components back together to form the normalized string.
- std::string Normalized;
- for (unsigned i = 0, e = Components.size(); i != e; ++i) {
- if (i) Normalized += '-';
- Normalized += Components[i];
- }
- return Normalized;
-}
-
-StringRef Triple::getArchName() const {
- return StringRef(Data).split('-').first; // Isolate first component
-}
-
-StringRef Triple::getVendorName() const {
- StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
- return Tmp.split('-').first; // Isolate second component
-}
-
-StringRef Triple::getOSName() const {
- StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
- Tmp = Tmp.split('-').second; // Strip second component
- return Tmp.split('-').first; // Isolate third component
-}
-
-StringRef Triple::getEnvironmentName() const {
- StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
- Tmp = Tmp.split('-').second; // Strip second component
- return Tmp.split('-').second; // Strip third component
-}
-
-StringRef Triple::getOSAndEnvironmentName() const {
- StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
- return Tmp.split('-').second; // Strip second component
-}
-
-static unsigned EatNumber(StringRef &Str) {
- assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number");
- unsigned Result = 0;
-
- do {
- // Consume the leading digit.
- Result = Result*10 + (Str[0] - '0');
-
- // Eat the digit.
- Str = Str.substr(1);
- } while (!Str.empty() && Str[0] >= '0' && Str[0] <= '9');
-
- return Result;
-}
-
-static void parseVersionFromName(StringRef Name, unsigned &Major,
- unsigned &Minor, unsigned &Micro) {
- // Any unset version defaults to 0.
- Major = Minor = Micro = 0;
-
- // Parse up to three components.
- unsigned *Components[3] = {&Major, &Minor, &Micro};
- for (unsigned i = 0; i != 3; ++i) {
- if (Name.empty() || Name[0] < '0' || Name[0] > '9')
- break;
-
- // Consume the leading number.
- *Components[i] = EatNumber(Name);
-
- // Consume the separator, if present.
- if (Name.startswith("."))
- Name = Name.substr(1);
- }
-}
-
-void Triple::getEnvironmentVersion(unsigned &Major, unsigned &Minor,
- unsigned &Micro) const {
- StringRef EnvironmentName = getEnvironmentName();
- StringRef EnvironmentTypeName = getEnvironmentTypeName(getEnvironment());
- if (EnvironmentName.startswith(EnvironmentTypeName))
- EnvironmentName = EnvironmentName.substr(EnvironmentTypeName.size());
-
- parseVersionFromName(EnvironmentName, Major, Minor, Micro);
-}
-
-void Triple::getOSVersion(unsigned &Major, unsigned &Minor,
- unsigned &Micro) const {
- StringRef OSName = getOSName();
- // Assume that the OS portion of the triple starts with the canonical name.
- StringRef OSTypeName = getOSTypeName(getOS());
- if (OSName.startswith(OSTypeName))
- OSName = OSName.substr(OSTypeName.size());
- else if (getOS() == MacOSX)
- OSName.consume_front("macos");
-
- parseVersionFromName(OSName, Major, Minor, Micro);
-}
-
-bool Triple::getMacOSXVersion(unsigned &Major, unsigned &Minor,
- unsigned &Micro) const {
- getOSVersion(Major, Minor, Micro);
-
- switch (getOS()) {
- default: llvm_unreachable("unexpected OS for Darwin triple");
- case Darwin:
- // Default to darwin8, i.e., MacOSX 10.4.
- if (Major == 0)
- Major = 8;
- // Darwin version numbers are skewed from OS X versions.
- if (Major < 4)
- return false;
- Micro = 0;
- Minor = Major - 4;
- Major = 10;
- break;
- case MacOSX:
- // Default to 10.4.
- if (Major == 0) {
- Major = 10;
- Minor = 4;
- }
- if (Major != 10)
- return false;
- break;
- case IOS:
- case TvOS:
- case WatchOS:
- // Ignore the version from the triple. This is only handled because the
- // the clang driver combines OS X and IOS support into a common Darwin
- // toolchain that wants to know the OS X version number even when targeting
- // IOS.
- Major = 10;
- Minor = 4;
- Micro = 0;
- break;
- }
- return true;
-}
-
-void Triple::getiOSVersion(unsigned &Major, unsigned &Minor,
- unsigned &Micro) const {
- switch (getOS()) {
- default: llvm_unreachable("unexpected OS for Darwin triple");
- case Darwin:
- case MacOSX:
- // Ignore the version from the triple. This is only handled because the
- // the clang driver combines OS X and IOS support into a common Darwin
- // toolchain that wants to know the iOS version number even when targeting
- // OS X.
- Major = 5;
- Minor = 0;
- Micro = 0;
- break;
- case IOS:
- case TvOS:
- getOSVersion(Major, Minor, Micro);
- // Default to 5.0 (or 7.0 for arm64).
- if (Major == 0)
- Major = (getArch() == aarch64) ? 7 : 5;
- break;
- case WatchOS:
- llvm_unreachable("conflicting triple info");
- }
-}
-
-void Triple::getWatchOSVersion(unsigned &Major, unsigned &Minor,
- unsigned &Micro) const {
- switch (getOS()) {
- default: llvm_unreachable("unexpected OS for Darwin triple");
- case Darwin:
- case MacOSX:
- // Ignore the version from the triple. This is only handled because the
- // the clang driver combines OS X and IOS support into a common Darwin
- // toolchain that wants to know the iOS version number even when targeting
- // OS X.
- Major = 2;
- Minor = 0;
- Micro = 0;
- break;
- case WatchOS:
- getOSVersion(Major, Minor, Micro);
- if (Major == 0)
- Major = 2;
- break;
- case IOS:
- llvm_unreachable("conflicting triple info");
- }
-}
-
-void Triple::setTriple(const Twine &Str) {
- *this = Triple(Str);
-}
-
-void Triple::setArch(ArchType Kind) {
- setArchName(getArchTypeName(Kind));
-}
-
-void Triple::setVendor(VendorType Kind) {
- setVendorName(getVendorTypeName(Kind));
-}
-
-void Triple::setOS(OSType Kind) {
- setOSName(getOSTypeName(Kind));
-}
-
-void Triple::setEnvironment(EnvironmentType Kind) {
- if (ObjectFormat == getDefaultFormat(*this))
- return setEnvironmentName(getEnvironmentTypeName(Kind));
-
- setEnvironmentName((getEnvironmentTypeName(Kind) + Twine("-") +
- getObjectFormatTypeName(ObjectFormat)).str());
-}
-
-void Triple::setObjectFormat(ObjectFormatType Kind) {
- if (Environment == UnknownEnvironment)
- return setEnvironmentName(getObjectFormatTypeName(Kind));
-
- setEnvironmentName((getEnvironmentTypeName(Environment) + Twine("-") +
- getObjectFormatTypeName(Kind)).str());
-}
-
-void Triple::setArchName(StringRef Str) {
- // Work around a miscompilation bug for Twines in gcc 4.0.3.
- SmallString<64> Triple;
- Triple += Str;
- Triple += "-";
- Triple += getVendorName();
- Triple += "-";
- Triple += getOSAndEnvironmentName();
- setTriple(Triple);
-}
-
-void Triple::setVendorName(StringRef Str) {
- setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName());
-}
-
-void Triple::setOSName(StringRef Str) {
- if (hasEnvironment())
- setTriple(getArchName() + "-" + getVendorName() + "-" + Str +
- "-" + getEnvironmentName());
- else
- setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
-}
-
-void Triple::setEnvironmentName(StringRef Str) {
- setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() +
- "-" + Str);
-}
-
-void Triple::setOSAndEnvironmentName(StringRef Str) {
- setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
-}
-
-static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
- switch (Arch) {
- case llvm::Triple::UnknownArch:
- return 0;
-
- case llvm::Triple::avr:
- case llvm::Triple::msp430:
- return 16;
-
- case llvm::Triple::arc:
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::hexagon:
- case llvm::Triple::le32:
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::nvptx:
- case llvm::Triple::ppc:
- case llvm::Triple::r600:
- case llvm::Triple::riscv32:
- case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
- case llvm::Triple::tce:
- case llvm::Triple::tcele:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- case llvm::Triple::x86:
- case llvm::Triple::xcore:
- case llvm::Triple::amdil:
- case llvm::Triple::hsail:
- case llvm::Triple::spir:
- case llvm::Triple::kalimba:
- case llvm::Triple::lanai:
- case llvm::Triple::shave:
- case llvm::Triple::wasm32:
- case llvm::Triple::renderscript32:
- return 32;
-
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_be:
- case llvm::Triple::amdgcn:
- case llvm::Triple::bpfel:
- case llvm::Triple::bpfeb:
- case llvm::Triple::le64:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::nvptx64:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- case llvm::Triple::riscv64:
- case llvm::Triple::sparcv9:
- case llvm::Triple::systemz:
- case llvm::Triple::x86_64:
- case llvm::Triple::amdil64:
- case llvm::Triple::hsail64:
- case llvm::Triple::spir64:
- case llvm::Triple::wasm64:
- case llvm::Triple::renderscript64:
- return 64;
- }
- llvm_unreachable("Invalid architecture value");
-}
-
-bool Triple::isArch64Bit() const {
- return getArchPointerBitWidth(getArch()) == 64;
-}
-
-bool Triple::isArch32Bit() const {
- return getArchPointerBitWidth(getArch()) == 32;
-}
-
-bool Triple::isArch16Bit() const {
- return getArchPointerBitWidth(getArch()) == 16;
-}
-
-Triple Triple::get32BitArchVariant() const {
- Triple T(*this);
- switch (getArch()) {
- case Triple::UnknownArch:
- case Triple::amdgcn:
- case Triple::avr:
- case Triple::bpfel:
- case Triple::bpfeb:
- case Triple::msp430:
- case Triple::systemz:
- case Triple::ppc64le:
- T.setArch(UnknownArch);
- break;
-
- case Triple::amdil:
- case Triple::hsail:
- case Triple::spir:
- case Triple::arc:
- case Triple::arm:
- case Triple::armeb:
- case Triple::hexagon:
- case Triple::kalimba:
- case Triple::le32:
- case Triple::mips:
- case Triple::mipsel:
- case Triple::nvptx:
- case Triple::ppc:
- case Triple::r600:
- case Triple::riscv32:
- case Triple::sparc:
- case Triple::sparcel:
- case Triple::tce:
- case Triple::tcele:
- case Triple::thumb:
- case Triple::thumbeb:
- case Triple::x86:
- case Triple::xcore:
- case Triple::lanai:
- case Triple::shave:
- case Triple::wasm32:
- case Triple::renderscript32:
- // Already 32-bit.
- break;
-
- case Triple::aarch64: T.setArch(Triple::arm); break;
- case Triple::aarch64_be: T.setArch(Triple::armeb); break;
- case Triple::le64: T.setArch(Triple::le32); break;
- case Triple::mips64: T.setArch(Triple::mips); break;
- case Triple::mips64el: T.setArch(Triple::mipsel); break;
- case Triple::nvptx64: T.setArch(Triple::nvptx); break;
- case Triple::ppc64: T.setArch(Triple::ppc); break;
- case Triple::sparcv9: T.setArch(Triple::sparc); break;
- case Triple::riscv64: T.setArch(Triple::riscv32); break;
- case Triple::x86_64: T.setArch(Triple::x86); break;
- case Triple::amdil64: T.setArch(Triple::amdil); break;
- case Triple::hsail64: T.setArch(Triple::hsail); break;
- case Triple::spir64: T.setArch(Triple::spir); break;
- case Triple::wasm64: T.setArch(Triple::wasm32); break;
- case Triple::renderscript64: T.setArch(Triple::renderscript32); break;
- }
- return T;
-}
-
-Triple Triple::get64BitArchVariant() const {
- Triple T(*this);
- switch (getArch()) {
- case Triple::UnknownArch:
- case Triple::arc:
- case Triple::avr:
- case Triple::hexagon:
- case Triple::kalimba:
- case Triple::lanai:
- case Triple::msp430:
- case Triple::r600:
- case Triple::tce:
- case Triple::tcele:
- case Triple::xcore:
- case Triple::sparcel:
- case Triple::shave:
- T.setArch(UnknownArch);
- break;
-
- case Triple::aarch64:
- case Triple::aarch64_be:
- case Triple::bpfel:
- case Triple::bpfeb:
- case Triple::le64:
- case Triple::amdil64:
- case Triple::amdgcn:
- case Triple::hsail64:
- case Triple::spir64:
- case Triple::mips64:
- case Triple::mips64el:
- case Triple::nvptx64:
- case Triple::ppc64:
- case Triple::ppc64le:
- case Triple::riscv64:
- case Triple::sparcv9:
- case Triple::systemz:
- case Triple::x86_64:
- case Triple::wasm64:
- case Triple::renderscript64:
- // Already 64-bit.
- break;
-
- case Triple::arm: T.setArch(Triple::aarch64); break;
- case Triple::armeb: T.setArch(Triple::aarch64_be); break;
- case Triple::le32: T.setArch(Triple::le64); break;
- case Triple::mips: T.setArch(Triple::mips64); break;
- case Triple::mipsel: T.setArch(Triple::mips64el); break;
- case Triple::nvptx: T.setArch(Triple::nvptx64); break;
- case Triple::ppc: T.setArch(Triple::ppc64); break;
- case Triple::sparc: T.setArch(Triple::sparcv9); break;
- case Triple::riscv32: T.setArch(Triple::riscv64); break;
- case Triple::x86: T.setArch(Triple::x86_64); break;
- case Triple::amdil: T.setArch(Triple::amdil64); break;
- case Triple::hsail: T.setArch(Triple::hsail64); break;
- case Triple::spir: T.setArch(Triple::spir64); break;
- case Triple::thumb: T.setArch(Triple::aarch64); break;
- case Triple::thumbeb: T.setArch(Triple::aarch64_be); break;
- case Triple::wasm32: T.setArch(Triple::wasm64); break;
- case Triple::renderscript32: T.setArch(Triple::renderscript64); break;
- }
- return T;
-}
-
-Triple Triple::getBigEndianArchVariant() const {
- Triple T(*this);
- // Already big endian.
- if (!isLittleEndian())
- return T;
- switch (getArch()) {
- case Triple::UnknownArch:
- case Triple::amdgcn:
- case Triple::amdil64:
- case Triple::amdil:
- case Triple::avr:
- case Triple::hexagon:
- case Triple::hsail64:
- case Triple::hsail:
- case Triple::kalimba:
- case Triple::le32:
- case Triple::le64:
- case Triple::msp430:
- case Triple::nvptx64:
- case Triple::nvptx:
- case Triple::r600:
- case Triple::riscv32:
- case Triple::riscv64:
- case Triple::shave:
- case Triple::spir64:
- case Triple::spir:
- case Triple::wasm32:
- case Triple::wasm64:
- case Triple::x86:
- case Triple::x86_64:
- case Triple::xcore:
- case Triple::renderscript32:
- case Triple::renderscript64:
-
- // ARM is intentionally unsupported here, changing the architecture would
- // drop any arch suffixes.
- case Triple::arm:
- case Triple::thumb:
- T.setArch(UnknownArch);
- break;
-
- case Triple::tcele: T.setArch(Triple::tce); break;
- case Triple::aarch64: T.setArch(Triple::aarch64_be); break;
- case Triple::bpfel: T.setArch(Triple::bpfeb); break;
- case Triple::mips64el:T.setArch(Triple::mips64); break;
- case Triple::mipsel: T.setArch(Triple::mips); break;
- case Triple::ppc64le: T.setArch(Triple::ppc64); break;
- case Triple::sparcel: T.setArch(Triple::sparc); break;
- default:
- llvm_unreachable("getBigEndianArchVariant: unknown triple.");
- }
- return T;
-}
-
-Triple Triple::getLittleEndianArchVariant() const {
- Triple T(*this);
- if (isLittleEndian())
- return T;
-
- switch (getArch()) {
- case Triple::UnknownArch:
- case Triple::lanai:
- case Triple::ppc:
- case Triple::sparcv9:
- case Triple::systemz:
-
- // ARM is intentionally unsupported here, changing the architecture would
- // drop any arch suffixes.
- case Triple::armeb:
- case Triple::thumbeb:
- T.setArch(UnknownArch);
- break;
-
- case Triple::tce: T.setArch(Triple::tcele); break;
- case Triple::aarch64_be: T.setArch(Triple::aarch64); break;
- case Triple::bpfeb: T.setArch(Triple::bpfel); break;
- case Triple::mips64: T.setArch(Triple::mips64el); break;
- case Triple::mips: T.setArch(Triple::mipsel); break;
- case Triple::ppc64: T.setArch(Triple::ppc64le); break;
- case Triple::sparc: T.setArch(Triple::sparcel); break;
- default:
- llvm_unreachable("getLittleEndianArchVariant: unknown triple.");
- }
- return T;
-}
-
-bool Triple::isLittleEndian() const {
- switch (getArch()) {
- case Triple::aarch64:
- case Triple::amdgcn:
- case Triple::amdil64:
- case Triple::amdil:
- case Triple::arm:
- case Triple::avr:
- case Triple::bpfel:
- case Triple::hexagon:
- case Triple::hsail64:
- case Triple::hsail:
- case Triple::kalimba:
- case Triple::le32:
- case Triple::le64:
- case Triple::mips64el:
- case Triple::mipsel:
- case Triple::msp430:
- case Triple::nvptx64:
- case Triple::nvptx:
- case Triple::ppc64le:
- case Triple::r600:
- case Triple::riscv32:
- case Triple::riscv64:
- case Triple::shave:
- case Triple::sparcel:
- case Triple::spir64:
- case Triple::spir:
- case Triple::thumb:
- case Triple::wasm32:
- case Triple::wasm64:
- case Triple::x86:
- case Triple::x86_64:
- case Triple::xcore:
- case Triple::tcele:
- case Triple::renderscript32:
- case Triple::renderscript64:
- return true;
- default:
- return false;
- }
-}
-
-bool Triple::isCompatibleWith(const Triple &Other) const {
- // ARM and Thumb triples are compatible, if subarch, vendor and OS match.
- if ((getArch() == Triple::thumb && Other.getArch() == Triple::arm) ||
- (getArch() == Triple::arm && Other.getArch() == Triple::thumb) ||
- (getArch() == Triple::thumbeb && Other.getArch() == Triple::armeb) ||
- (getArch() == Triple::armeb && Other.getArch() == Triple::thumbeb)) {
- if (getVendor() == Triple::Apple)
- return getSubArch() == Other.getSubArch() &&
- getVendor() == Other.getVendor() && getOS() == Other.getOS();
- else
- return getSubArch() == Other.getSubArch() &&
- getVendor() == Other.getVendor() && getOS() == Other.getOS() &&
- getEnvironment() == Other.getEnvironment() &&
- getObjectFormat() == Other.getObjectFormat();
- }
-
- // If vendor is apple, ignore the version number.
- if (getVendor() == Triple::Apple)
- return getArch() == Other.getArch() && getSubArch() == Other.getSubArch() &&
- getVendor() == Other.getVendor() && getOS() == Other.getOS();
-
- return *this == Other;
-}
-
-std::string Triple::merge(const Triple &Other) const {
- // If vendor is apple, pick the triple with the larger version number.
- if (getVendor() == Triple::Apple)
- if (Other.isOSVersionLT(*this))
- return str();
-
- return Other.str();
-}
-
-StringRef Triple::getARMCPUForArch(StringRef MArch) const {
- if (MArch.empty())
- MArch = getArchName();
- MArch = ARM::getCanonicalArchName(MArch);
-
- // Some defaults are forced.
- switch (getOS()) {
- case llvm::Triple::FreeBSD:
- case llvm::Triple::NetBSD:
- if (!MArch.empty() && MArch == "v6")
- return "arm1176jzf-s";
- break;
- case llvm::Triple::Win32:
- // FIXME: this is invalid for WindowsCE
- return "cortex-a9";
- case llvm::Triple::MacOSX:
- case llvm::Triple::IOS:
- case llvm::Triple::WatchOS:
- case llvm::Triple::TvOS:
- if (MArch == "v7k")
- return "cortex-a7";
- break;
- default:
- break;
- }
-
- if (MArch.empty())
- return StringRef();
-
- StringRef CPU = ARM::getDefaultCPU(MArch);
- if (!CPU.empty() && !CPU.equals("invalid"))
- return CPU;
-
- // If no specific architecture version is requested, return the minimum CPU
- // required by the OS and environment.
- switch (getOS()) {
- case llvm::Triple::NetBSD:
- switch (getEnvironment()) {
- case llvm::Triple::GNUEABIHF:
- case llvm::Triple::GNUEABI:
- case llvm::Triple::EABIHF:
- case llvm::Triple::EABI:
- return "arm926ej-s";
- default:
- return "strongarm";
- }
- case llvm::Triple::NaCl:
- case llvm::Triple::OpenBSD:
- return "cortex-a8";
- default:
- switch (getEnvironment()) {
- case llvm::Triple::EABIHF:
- case llvm::Triple::GNUEABIHF:
- case llvm::Triple::MuslEABIHF:
- return "arm1176jzf-s";
- default:
- return "arm7tdmi";
- }
- }
-
- llvm_unreachable("invalid arch name");
-}
diff --git a/gnu/llvm/lib/Support/Twine.cpp b/gnu/llvm/lib/Support/Twine.cpp
deleted file mode 100644
index 4726c8ab749..00000000000
--- a/gnu/llvm/lib/Support/Twine.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-//===-- Twine.cpp - Fast Temporary String Concatenation -------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/Twine.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-std::string Twine::str() const {
- // If we're storing only a std::string, just return it.
- if (LHSKind == StdStringKind && RHSKind == EmptyKind)
- return *LHS.stdString;
-
- // If we're storing a formatv_object, we can avoid an extra copy by formatting
- // it immediately and returning the result.
- if (LHSKind == FormatvObjectKind && RHSKind == EmptyKind)
- return LHS.formatvObject->str();
-
- // Otherwise, flatten and copy the contents first.
- SmallString<256> Vec;
- return toStringRef(Vec).str();
-}
-
-void Twine::toVector(SmallVectorImpl<char> &Out) const {
- raw_svector_ostream OS(Out);
- print(OS);
-}
-
-StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const {
- if (isUnary()) {
- switch (getLHSKind()) {
- case CStringKind:
- // Already null terminated, yay!
- return StringRef(LHS.cString);
- case StdStringKind: {
- const std::string *str = LHS.stdString;
- return StringRef(str->c_str(), str->size());
- }
- default:
- break;
- }
- }
- toVector(Out);
- Out.push_back(0);
- Out.pop_back();
- return StringRef(Out.data(), Out.size());
-}
-
-void Twine::printOneChild(raw_ostream &OS, Child Ptr,
- NodeKind Kind) const {
- switch (Kind) {
- case Twine::NullKind: break;
- case Twine::EmptyKind: break;
- case Twine::TwineKind:
- Ptr.twine->print(OS);
- break;
- case Twine::CStringKind:
- OS << Ptr.cString;
- break;
- case Twine::StdStringKind:
- OS << *Ptr.stdString;
- break;
- case Twine::StringRefKind:
- OS << *Ptr.stringRef;
- break;
- case Twine::SmallStringKind:
- OS << *Ptr.smallString;
- break;
- case Twine::FormatvObjectKind:
- OS << *Ptr.formatvObject;
- break;
- case Twine::CharKind:
- OS << Ptr.character;
- break;
- case Twine::DecUIKind:
- OS << Ptr.decUI;
- break;
- case Twine::DecIKind:
- OS << Ptr.decI;
- break;
- case Twine::DecULKind:
- OS << *Ptr.decUL;
- break;
- case Twine::DecLKind:
- OS << *Ptr.decL;
- break;
- case Twine::DecULLKind:
- OS << *Ptr.decULL;
- break;
- case Twine::DecLLKind:
- OS << *Ptr.decLL;
- break;
- case Twine::UHexKind:
- OS.write_hex(*Ptr.uHex);
- break;
- }
-}
-
-void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr,
- NodeKind Kind) const {
- switch (Kind) {
- case Twine::NullKind:
- OS << "null"; break;
- case Twine::EmptyKind:
- OS << "empty"; break;
- case Twine::TwineKind:
- OS << "rope:";
- Ptr.twine->printRepr(OS);
- break;
- case Twine::CStringKind:
- OS << "cstring:\""
- << Ptr.cString << "\"";
- break;
- case Twine::StdStringKind:
- OS << "std::string:\""
- << Ptr.stdString << "\"";
- break;
- case Twine::StringRefKind:
- OS << "stringref:\""
- << Ptr.stringRef << "\"";
- break;
- case Twine::SmallStringKind:
- OS << "smallstring:\"" << *Ptr.smallString << "\"";
- break;
- case Twine::FormatvObjectKind:
- OS << "formatv:\"" << *Ptr.formatvObject << "\"";
- break;
- case Twine::CharKind:
- OS << "char:\"" << Ptr.character << "\"";
- break;
- case Twine::DecUIKind:
- OS << "decUI:\"" << Ptr.decUI << "\"";
- break;
- case Twine::DecIKind:
- OS << "decI:\"" << Ptr.decI << "\"";
- break;
- case Twine::DecULKind:
- OS << "decUL:\"" << *Ptr.decUL << "\"";
- break;
- case Twine::DecLKind:
- OS << "decL:\"" << *Ptr.decL << "\"";
- break;
- case Twine::DecULLKind:
- OS << "decULL:\"" << *Ptr.decULL << "\"";
- break;
- case Twine::DecLLKind:
- OS << "decLL:\"" << *Ptr.decLL << "\"";
- break;
- case Twine::UHexKind:
- OS << "uhex:\"" << Ptr.uHex << "\"";
- break;
- }
-}
-
-void Twine::print(raw_ostream &OS) const {
- printOneChild(OS, LHS, getLHSKind());
- printOneChild(OS, RHS, getRHSKind());
-}
-
-void Twine::printRepr(raw_ostream &OS) const {
- OS << "(Twine ";
- printOneChildRepr(OS, LHS, getLHSKind());
- OS << " ";
- printOneChildRepr(OS, RHS, getRHSKind());
- OS << ")";
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void Twine::dump() const {
- print(dbgs());
-}
-
-LLVM_DUMP_METHOD void Twine::dumpRepr() const {
- printRepr(dbgs());
-}
-#endif
diff --git a/gnu/llvm/lib/Support/Unicode.cpp b/gnu/llvm/lib/Support/Unicode.cpp
deleted file mode 100644
index b719bd826dc..00000000000
--- a/gnu/llvm/lib/Support/Unicode.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-//===- llvm/Support/Unicode.cpp - Unicode character properties -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements functions that allow querying certain properties of
-// Unicode characters.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Unicode.h"
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/UnicodeCharRanges.h"
-
-namespace llvm {
-namespace sys {
-namespace unicode {
-
-bool isPrintable(int UCS) {
- // Sorted list of non-overlapping intervals of code points that are not
- // supposed to be printable.
- static const UnicodeCharRange NonPrintableRanges[] = {
- { 0x0000, 0x001F }, { 0x007F, 0x009F }, { 0x034F, 0x034F },
- { 0x0378, 0x0379 }, { 0x037F, 0x0383 }, { 0x038B, 0x038B },
- { 0x038D, 0x038D }, { 0x03A2, 0x03A2 }, { 0x0528, 0x0530 },
- { 0x0557, 0x0558 }, { 0x0560, 0x0560 }, { 0x0588, 0x0588 },
- { 0x058B, 0x058E }, { 0x0590, 0x0590 }, { 0x05C8, 0x05CF },
- { 0x05EB, 0x05EF }, { 0x05F5, 0x0605 }, { 0x061C, 0x061D },
- { 0x06DD, 0x06DD }, { 0x070E, 0x070F }, { 0x074B, 0x074C },
- { 0x07B2, 0x07BF }, { 0x07FB, 0x07FF }, { 0x082E, 0x082F },
- { 0x083F, 0x083F }, { 0x085C, 0x085D }, { 0x085F, 0x089F },
- { 0x08A1, 0x08A1 }, { 0x08AD, 0x08E3 }, { 0x08FF, 0x08FF },
- { 0x0978, 0x0978 }, { 0x0980, 0x0980 }, { 0x0984, 0x0984 },
- { 0x098D, 0x098E }, { 0x0991, 0x0992 }, { 0x09A9, 0x09A9 },
- { 0x09B1, 0x09B1 }, { 0x09B3, 0x09B5 }, { 0x09BA, 0x09BB },
- { 0x09C5, 0x09C6 }, { 0x09C9, 0x09CA }, { 0x09CF, 0x09D6 },
- { 0x09D8, 0x09DB }, { 0x09DE, 0x09DE }, { 0x09E4, 0x09E5 },
- { 0x09FC, 0x0A00 }, { 0x0A04, 0x0A04 }, { 0x0A0B, 0x0A0E },
- { 0x0A11, 0x0A12 }, { 0x0A29, 0x0A29 }, { 0x0A31, 0x0A31 },
- { 0x0A34, 0x0A34 }, { 0x0A37, 0x0A37 }, { 0x0A3A, 0x0A3B },
- { 0x0A3D, 0x0A3D }, { 0x0A43, 0x0A46 }, { 0x0A49, 0x0A4A },
- { 0x0A4E, 0x0A50 }, { 0x0A52, 0x0A58 }, { 0x0A5D, 0x0A5D },
- { 0x0A5F, 0x0A65 }, { 0x0A76, 0x0A80 }, { 0x0A84, 0x0A84 },
- { 0x0A8E, 0x0A8E }, { 0x0A92, 0x0A92 }, { 0x0AA9, 0x0AA9 },
- { 0x0AB1, 0x0AB1 }, { 0x0AB4, 0x0AB4 }, { 0x0ABA, 0x0ABB },
- { 0x0AC6, 0x0AC6 }, { 0x0ACA, 0x0ACA }, { 0x0ACE, 0x0ACF },
- { 0x0AD1, 0x0ADF }, { 0x0AE4, 0x0AE5 }, { 0x0AF2, 0x0B00 },
- { 0x0B04, 0x0B04 }, { 0x0B0D, 0x0B0E }, { 0x0B11, 0x0B12 },
- { 0x0B29, 0x0B29 }, { 0x0B31, 0x0B31 }, { 0x0B34, 0x0B34 },
- { 0x0B3A, 0x0B3B }, { 0x0B45, 0x0B46 }, { 0x0B49, 0x0B4A },
- { 0x0B4E, 0x0B55 }, { 0x0B58, 0x0B5B }, { 0x0B5E, 0x0B5E },
- { 0x0B64, 0x0B65 }, { 0x0B78, 0x0B81 }, { 0x0B84, 0x0B84 },
- { 0x0B8B, 0x0B8D }, { 0x0B91, 0x0B91 }, { 0x0B96, 0x0B98 },
- { 0x0B9B, 0x0B9B }, { 0x0B9D, 0x0B9D }, { 0x0BA0, 0x0BA2 },
- { 0x0BA5, 0x0BA7 }, { 0x0BAB, 0x0BAD }, { 0x0BBA, 0x0BBD },
- { 0x0BC3, 0x0BC5 }, { 0x0BC9, 0x0BC9 }, { 0x0BCE, 0x0BCF },
- { 0x0BD1, 0x0BD6 }, { 0x0BD8, 0x0BE5 }, { 0x0BFB, 0x0C00 },
- { 0x0C04, 0x0C04 }, { 0x0C0D, 0x0C0D }, { 0x0C11, 0x0C11 },
- { 0x0C29, 0x0C29 }, { 0x0C34, 0x0C34 }, { 0x0C3A, 0x0C3C },
- { 0x0C45, 0x0C45 }, { 0x0C49, 0x0C49 }, { 0x0C4E, 0x0C54 },
- { 0x0C57, 0x0C57 }, { 0x0C5A, 0x0C5F }, { 0x0C64, 0x0C65 },
- { 0x0C70, 0x0C77 }, { 0x0C80, 0x0C81 }, { 0x0C84, 0x0C84 },
- { 0x0C8D, 0x0C8D }, { 0x0C91, 0x0C91 }, { 0x0CA9, 0x0CA9 },
- { 0x0CB4, 0x0CB4 }, { 0x0CBA, 0x0CBB }, { 0x0CC5, 0x0CC5 },
- { 0x0CC9, 0x0CC9 }, { 0x0CCE, 0x0CD4 }, { 0x0CD7, 0x0CDD },
- { 0x0CDF, 0x0CDF }, { 0x0CE4, 0x0CE5 }, { 0x0CF0, 0x0CF0 },
- { 0x0CF3, 0x0D01 }, { 0x0D04, 0x0D04 }, { 0x0D0D, 0x0D0D },
- { 0x0D11, 0x0D11 }, { 0x0D3B, 0x0D3C }, { 0x0D45, 0x0D45 },
- { 0x0D49, 0x0D49 }, { 0x0D4F, 0x0D56 }, { 0x0D58, 0x0D5F },
- { 0x0D64, 0x0D65 }, { 0x0D76, 0x0D78 }, { 0x0D80, 0x0D81 },
- { 0x0D84, 0x0D84 }, { 0x0D97, 0x0D99 }, { 0x0DB2, 0x0DB2 },
- { 0x0DBC, 0x0DBC }, { 0x0DBE, 0x0DBF }, { 0x0DC7, 0x0DC9 },
- { 0x0DCB, 0x0DCE }, { 0x0DD5, 0x0DD5 }, { 0x0DD7, 0x0DD7 },
- { 0x0DE0, 0x0DF1 }, { 0x0DF5, 0x0E00 }, { 0x0E3B, 0x0E3E },
- { 0x0E5C, 0x0E80 }, { 0x0E83, 0x0E83 }, { 0x0E85, 0x0E86 },
- { 0x0E89, 0x0E89 }, { 0x0E8B, 0x0E8C }, { 0x0E8E, 0x0E93 },
- { 0x0E98, 0x0E98 }, { 0x0EA0, 0x0EA0 }, { 0x0EA4, 0x0EA4 },
- { 0x0EA6, 0x0EA6 }, { 0x0EA8, 0x0EA9 }, { 0x0EAC, 0x0EAC },
- { 0x0EBA, 0x0EBA }, { 0x0EBE, 0x0EBF }, { 0x0EC5, 0x0EC5 },
- { 0x0EC7, 0x0EC7 }, { 0x0ECE, 0x0ECF }, { 0x0EDA, 0x0EDB },
- { 0x0EE0, 0x0EFF }, { 0x0F48, 0x0F48 }, { 0x0F6D, 0x0F70 },
- { 0x0F98, 0x0F98 }, { 0x0FBD, 0x0FBD }, { 0x0FCD, 0x0FCD },
- { 0x0FDB, 0x0FFF }, { 0x10C6, 0x10C6 }, { 0x10C8, 0x10CC },
- { 0x10CE, 0x10CF }, { 0x115F, 0x1160 }, { 0x1249, 0x1249 },
- { 0x124E, 0x124F }, { 0x1257, 0x1257 }, { 0x1259, 0x1259 },
- { 0x125E, 0x125F }, { 0x1289, 0x1289 }, { 0x128E, 0x128F },
- { 0x12B1, 0x12B1 }, { 0x12B6, 0x12B7 }, { 0x12BF, 0x12BF },
- { 0x12C1, 0x12C1 }, { 0x12C6, 0x12C7 }, { 0x12D7, 0x12D7 },
- { 0x1311, 0x1311 }, { 0x1316, 0x1317 }, { 0x135B, 0x135C },
- { 0x137D, 0x137F }, { 0x139A, 0x139F }, { 0x13F5, 0x13FF },
- { 0x169D, 0x169F }, { 0x16F1, 0x16FF }, { 0x170D, 0x170D },
- { 0x1715, 0x171F }, { 0x1737, 0x173F }, { 0x1754, 0x175F },
- { 0x176D, 0x176D }, { 0x1771, 0x1771 }, { 0x1774, 0x177F },
- { 0x17B4, 0x17B5 }, { 0x17DE, 0x17DF }, { 0x17EA, 0x17EF },
- { 0x17FA, 0x17FF }, { 0x180B, 0x180D }, { 0x180F, 0x180F },
- { 0x181A, 0x181F }, { 0x1878, 0x187F }, { 0x18AB, 0x18AF },
- { 0x18F6, 0x18FF }, { 0x191D, 0x191F }, { 0x192C, 0x192F },
- { 0x193C, 0x193F }, { 0x1941, 0x1943 }, { 0x196E, 0x196F },
- { 0x1975, 0x197F }, { 0x19AC, 0x19AF }, { 0x19CA, 0x19CF },
- { 0x19DB, 0x19DD }, { 0x1A1C, 0x1A1D }, { 0x1A5F, 0x1A5F },
- { 0x1A7D, 0x1A7E }, { 0x1A8A, 0x1A8F }, { 0x1A9A, 0x1A9F },
- { 0x1AAE, 0x1AFF }, { 0x1B4C, 0x1B4F }, { 0x1B7D, 0x1B7F },
- { 0x1BF4, 0x1BFB }, { 0x1C38, 0x1C3A }, { 0x1C4A, 0x1C4C },
- { 0x1C80, 0x1CBF }, { 0x1CC8, 0x1CCF }, { 0x1CF7, 0x1CFF },
- { 0x1DE7, 0x1DFB }, { 0x1F16, 0x1F17 }, { 0x1F1E, 0x1F1F },
- { 0x1F46, 0x1F47 }, { 0x1F4E, 0x1F4F }, { 0x1F58, 0x1F58 },
- { 0x1F5A, 0x1F5A }, { 0x1F5C, 0x1F5C }, { 0x1F5E, 0x1F5E },
- { 0x1F7E, 0x1F7F }, { 0x1FB5, 0x1FB5 }, { 0x1FC5, 0x1FC5 },
- { 0x1FD4, 0x1FD5 }, { 0x1FDC, 0x1FDC }, { 0x1FF0, 0x1FF1 },
- { 0x1FF5, 0x1FF5 }, { 0x1FFF, 0x1FFF }, { 0x200B, 0x200F },
- { 0x202A, 0x202E }, { 0x2060, 0x206F }, { 0x2072, 0x2073 },
- { 0x208F, 0x208F }, { 0x209D, 0x209F }, { 0x20BB, 0x20CF },
- { 0x20F1, 0x20FF }, { 0x218A, 0x218F }, { 0x23F4, 0x23FF },
- { 0x2427, 0x243F }, { 0x244B, 0x245F }, { 0x2700, 0x2700 },
- { 0x2B4D, 0x2B4F }, { 0x2B5A, 0x2BFF }, { 0x2C2F, 0x2C2F },
- { 0x2C5F, 0x2C5F }, { 0x2CF4, 0x2CF8 }, { 0x2D26, 0x2D26 },
- { 0x2D28, 0x2D2C }, { 0x2D2E, 0x2D2F }, { 0x2D68, 0x2D6E },
- { 0x2D71, 0x2D7E }, { 0x2D97, 0x2D9F }, { 0x2DA7, 0x2DA7 },
- { 0x2DAF, 0x2DAF }, { 0x2DB7, 0x2DB7 }, { 0x2DBF, 0x2DBF },
- { 0x2DC7, 0x2DC7 }, { 0x2DCF, 0x2DCF }, { 0x2DD7, 0x2DD7 },
- { 0x2DDF, 0x2DDF }, { 0x2E3C, 0x2E7F }, { 0x2E9A, 0x2E9A },
- { 0x2EF4, 0x2EFF }, { 0x2FD6, 0x2FEF }, { 0x2FFC, 0x2FFF },
- { 0x3040, 0x3040 }, { 0x3097, 0x3098 }, { 0x3100, 0x3104 },
- { 0x312E, 0x3130 }, { 0x3164, 0x3164 }, { 0x318F, 0x318F },
- { 0x31BB, 0x31BF }, { 0x31E4, 0x31EF }, { 0x321F, 0x321F },
- { 0x32FF, 0x32FF }, { 0x4DB6, 0x4DBF }, { 0x9FCD, 0x9FFF },
- { 0xA48D, 0xA48F }, { 0xA4C7, 0xA4CF }, { 0xA62C, 0xA63F },
- { 0xA698, 0xA69E }, { 0xA6F8, 0xA6FF }, { 0xA78F, 0xA78F },
- { 0xA794, 0xA79F }, { 0xA7AB, 0xA7F7 }, { 0xA82C, 0xA82F },
- { 0xA83A, 0xA83F }, { 0xA878, 0xA87F }, { 0xA8C5, 0xA8CD },
- { 0xA8DA, 0xA8DF }, { 0xA8FC, 0xA8FF }, { 0xA954, 0xA95E },
- { 0xA97D, 0xA97F }, { 0xA9CE, 0xA9CE }, { 0xA9DA, 0xA9DD },
- { 0xA9E0, 0xA9FF }, { 0xAA37, 0xAA3F }, { 0xAA4E, 0xAA4F },
- { 0xAA5A, 0xAA5B }, { 0xAA7C, 0xAA7F }, { 0xAAC3, 0xAADA },
- { 0xAAF7, 0xAB00 }, { 0xAB07, 0xAB08 }, { 0xAB0F, 0xAB10 },
- { 0xAB17, 0xAB1F }, { 0xAB27, 0xAB27 }, { 0xAB2F, 0xABBF },
- { 0xABEE, 0xABEF }, { 0xABFA, 0xABFF }, { 0xD7A4, 0xD7AF },
- { 0xD7C7, 0xD7CA }, { 0xD7FC, 0xDFFF }, { 0xFA6E, 0xFA6F },
- { 0xFADA, 0xFAFF }, { 0xFB07, 0xFB12 }, { 0xFB18, 0xFB1C },
- { 0xFB37, 0xFB37 }, { 0xFB3D, 0xFB3D }, { 0xFB3F, 0xFB3F },
- { 0xFB42, 0xFB42 }, { 0xFB45, 0xFB45 }, { 0xFBC2, 0xFBD2 },
- { 0xFD40, 0xFD4F }, { 0xFD90, 0xFD91 }, { 0xFDC8, 0xFDEF },
- { 0xFDFE, 0xFE0F }, { 0xFE1A, 0xFE1F }, { 0xFE27, 0xFE2F },
- { 0xFE53, 0xFE53 }, { 0xFE67, 0xFE67 }, { 0xFE6C, 0xFE6F },
- { 0xFE75, 0xFE75 }, { 0xFEFD, 0xFEFF }, { 0xFF00, 0xFF00 },
- { 0xFFA0, 0xFFA0 }, { 0xFFBF, 0xFFC1 }, { 0xFFC8, 0xFFC9 },
- { 0xFFD0, 0xFFD1 }, { 0xFFD8, 0xFFD9 }, { 0xFFDD, 0xFFDF },
- { 0xFFE7, 0xFFE7 }, { 0xFFEF, 0xFFFB }, { 0xFFFE, 0xFFFF },
- { 0x1000C, 0x1000C }, { 0x10027, 0x10027 }, { 0x1003B, 0x1003B },
- { 0x1003E, 0x1003E }, { 0x1004E, 0x1004F }, { 0x1005E, 0x1007F },
- { 0x100FB, 0x100FF }, { 0x10103, 0x10106 }, { 0x10134, 0x10136 },
- { 0x1018B, 0x1018F }, { 0x1019C, 0x101CF }, { 0x101FE, 0x1027F },
- { 0x1029D, 0x1029F }, { 0x102D1, 0x102FF }, { 0x1031F, 0x1031F },
- { 0x10324, 0x1032F }, { 0x1034B, 0x1037F }, { 0x1039E, 0x1039E },
- { 0x103C4, 0x103C7 }, { 0x103D6, 0x103FF }, { 0x1049E, 0x1049F },
- { 0x104AA, 0x107FF }, { 0x10806, 0x10807 }, { 0x10809, 0x10809 },
- { 0x10836, 0x10836 }, { 0x10839, 0x1083B }, { 0x1083D, 0x1083E },
- { 0x10856, 0x10856 }, { 0x10860, 0x108FF }, { 0x1091C, 0x1091E },
- { 0x1093A, 0x1093E }, { 0x10940, 0x1097F }, { 0x109B8, 0x109BD },
- { 0x109C0, 0x109FF }, { 0x10A04, 0x10A04 }, { 0x10A07, 0x10A0B },
- { 0x10A14, 0x10A14 }, { 0x10A18, 0x10A18 }, { 0x10A34, 0x10A37 },
- { 0x10A3B, 0x10A3E }, { 0x10A48, 0x10A4F }, { 0x10A59, 0x10A5F },
- { 0x10A80, 0x10AFF }, { 0x10B36, 0x10B38 }, { 0x10B56, 0x10B57 },
- { 0x10B73, 0x10B77 }, { 0x10B80, 0x10BFF }, { 0x10C49, 0x10E5F },
- { 0x10E7F, 0x10FFF }, { 0x1104E, 0x11051 }, { 0x11070, 0x1107F },
- { 0x110BD, 0x110BD }, { 0x110C2, 0x110CF }, { 0x110E9, 0x110EF },
- { 0x110FA, 0x110FF }, { 0x11135, 0x11135 }, { 0x11144, 0x1117F },
- { 0x111C9, 0x111CF }, { 0x111DA, 0x1167F }, { 0x116B8, 0x116BF },
- { 0x116CA, 0x11FFF }, { 0x1236F, 0x123FF }, { 0x12463, 0x1246F },
- { 0x12474, 0x12FFF }, { 0x1342F, 0x167FF }, { 0x16A39, 0x16EFF },
- { 0x16F45, 0x16F4F }, { 0x16F7F, 0x16F8E }, { 0x16FA0, 0x1AFFF },
- { 0x1B002, 0x1CFFF }, { 0x1D0F6, 0x1D0FF }, { 0x1D127, 0x1D128 },
- { 0x1D173, 0x1D17A }, { 0x1D1DE, 0x1D1FF }, { 0x1D246, 0x1D2FF },
- { 0x1D357, 0x1D35F }, { 0x1D372, 0x1D3FF }, { 0x1D455, 0x1D455 },
- { 0x1D49D, 0x1D49D }, { 0x1D4A0, 0x1D4A1 }, { 0x1D4A3, 0x1D4A4 },
- { 0x1D4A7, 0x1D4A8 }, { 0x1D4AD, 0x1D4AD }, { 0x1D4BA, 0x1D4BA },
- { 0x1D4BC, 0x1D4BC }, { 0x1D4C4, 0x1D4C4 }, { 0x1D506, 0x1D506 },
- { 0x1D50B, 0x1D50C }, { 0x1D515, 0x1D515 }, { 0x1D51D, 0x1D51D },
- { 0x1D53A, 0x1D53A }, { 0x1D53F, 0x1D53F }, { 0x1D545, 0x1D545 },
- { 0x1D547, 0x1D549 }, { 0x1D551, 0x1D551 }, { 0x1D6A6, 0x1D6A7 },
- { 0x1D7CC, 0x1D7CD }, { 0x1D800, 0x1EDFF }, { 0x1EE04, 0x1EE04 },
- { 0x1EE20, 0x1EE20 }, { 0x1EE23, 0x1EE23 }, { 0x1EE25, 0x1EE26 },
- { 0x1EE28, 0x1EE28 }, { 0x1EE33, 0x1EE33 }, { 0x1EE38, 0x1EE38 },
- { 0x1EE3A, 0x1EE3A }, { 0x1EE3C, 0x1EE41 }, { 0x1EE43, 0x1EE46 },
- { 0x1EE48, 0x1EE48 }, { 0x1EE4A, 0x1EE4A }, { 0x1EE4C, 0x1EE4C },
- { 0x1EE50, 0x1EE50 }, { 0x1EE53, 0x1EE53 }, { 0x1EE55, 0x1EE56 },
- { 0x1EE58, 0x1EE58 }, { 0x1EE5A, 0x1EE5A }, { 0x1EE5C, 0x1EE5C },
- { 0x1EE5E, 0x1EE5E }, { 0x1EE60, 0x1EE60 }, { 0x1EE63, 0x1EE63 },
- { 0x1EE65, 0x1EE66 }, { 0x1EE6B, 0x1EE6B }, { 0x1EE73, 0x1EE73 },
- { 0x1EE78, 0x1EE78 }, { 0x1EE7D, 0x1EE7D }, { 0x1EE7F, 0x1EE7F },
- { 0x1EE8A, 0x1EE8A }, { 0x1EE9C, 0x1EEA0 }, { 0x1EEA4, 0x1EEA4 },
- { 0x1EEAA, 0x1EEAA }, { 0x1EEBC, 0x1EEEF }, { 0x1EEF2, 0x1EFFF },
- { 0x1F02C, 0x1F02F }, { 0x1F094, 0x1F09F }, { 0x1F0AF, 0x1F0B0 },
- { 0x1F0BF, 0x1F0C0 }, { 0x1F0D0, 0x1F0D0 }, { 0x1F0E0, 0x1F0FF },
- { 0x1F10B, 0x1F10F }, { 0x1F12F, 0x1F12F }, { 0x1F16C, 0x1F16F },
- { 0x1F19B, 0x1F1E5 }, { 0x1F203, 0x1F20F }, { 0x1F23B, 0x1F23F },
- { 0x1F249, 0x1F24F }, { 0x1F252, 0x1F2FF }, { 0x1F321, 0x1F32F },
- { 0x1F336, 0x1F336 }, { 0x1F37D, 0x1F37F }, { 0x1F394, 0x1F39F },
- { 0x1F3C5, 0x1F3C5 }, { 0x1F3CB, 0x1F3DF }, { 0x1F3F1, 0x1F3FF },
- { 0x1F43F, 0x1F43F }, { 0x1F441, 0x1F441 }, { 0x1F4F8, 0x1F4F8 },
- { 0x1F4FD, 0x1F4FF }, { 0x1F53E, 0x1F53F }, { 0x1F544, 0x1F54F },
- { 0x1F568, 0x1F5FA }, { 0x1F641, 0x1F644 }, { 0x1F650, 0x1F67F },
- { 0x1F6C6, 0x1F6FF }, { 0x1F774, 0x1FFFF }, { 0x2A6D7, 0x2A6FF },
- { 0x2B735, 0x2B73F }, { 0x2B81E, 0x2F7FF }, { 0x2FA1E, 0xF0000 },
- { 0xFFFFE, 0xFFFFF }, { 0x10FFFE, 0x10FFFF }
- };
- static const UnicodeCharSet NonPrintables(NonPrintableRanges);
-
- return UCS >= 0 && UCS <= 0x10FFFF && !NonPrintables.contains(UCS);
-}
-
-/// Gets the number of positions a character is likely to occupy when output
-/// on a terminal ("character width"). This depends on the implementation of the
-/// terminal, and there's no standard definition of character width.
-/// The implementation defines it in a way that is expected to be compatible
-/// with a generic Unicode-capable terminal.
-/// \return Character width:
-/// * ErrorNonPrintableCharacter (-1) for non-printable characters (as
-/// identified by isPrintable);
-/// * 0 for non-spacing and enclosing combining marks;
-/// * 2 for CJK characters excluding halfwidth forms;
-/// * 1 for all remaining characters.
-static inline int charWidth(int UCS)
-{
- if (!isPrintable(UCS))
- return ErrorNonPrintableCharacter;
-
- // Sorted list of non-spacing and enclosing combining mark intervals as
- // defined in "3.6 Combination" of
- // http://www.unicode.org/versions/Unicode6.2.0/UnicodeStandard-6.2.pdf
- static const UnicodeCharRange CombiningCharacterRanges[] = {
- { 0x0300, 0x036F }, { 0x0483, 0x0489 }, { 0x0591, 0x05BD },
- { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05C4, 0x05C5 },
- { 0x05C7, 0x05C7 }, { 0x0610, 0x061A }, { 0x064B, 0x065F },
- { 0x0670, 0x0670 }, { 0x06D6, 0x06DC }, { 0x06DF, 0x06E4 },
- { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x0711, 0x0711 },
- { 0x0730, 0x074A }, { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 },
- { 0x0816, 0x0819 }, { 0x081B, 0x0823 }, { 0x0825, 0x0827 },
- { 0x0829, 0x082D }, { 0x0859, 0x085B }, { 0x08E4, 0x08FE },
- { 0x0900, 0x0902 }, { 0x093A, 0x093A }, { 0x093C, 0x093C },
- { 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0957 },
- { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC },
- { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 },
- { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 },
- { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A51, 0x0A51 },
- { 0x0A70, 0x0A71 }, { 0x0A75, 0x0A75 }, { 0x0A81, 0x0A82 },
- { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 },
- { 0x0ACD, 0x0ACD }, { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 },
- { 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B44 },
- { 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B62, 0x0B63 },
- { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD },
- { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D },
- { 0x0C55, 0x0C56 }, { 0x0C62, 0x0C63 }, { 0x0CBC, 0x0CBC },
- { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
- { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D44 }, { 0x0D4D, 0x0D4D },
- { 0x0D62, 0x0D63 }, { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 },
- { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A },
- { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 },
- { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 },
- { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 },
- { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 },
- { 0x0F8D, 0x0F97 }, { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 },
- { 0x102D, 0x1030 }, { 0x1032, 0x1037 }, { 0x1039, 0x103A },
- { 0x103D, 0x103E }, { 0x1058, 0x1059 }, { 0x105E, 0x1060 },
- { 0x1071, 0x1074 }, { 0x1082, 0x1082 }, { 0x1085, 0x1086 },
- { 0x108D, 0x108D }, { 0x109D, 0x109D }, { 0x135D, 0x135F },
- { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
- { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
- { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
- { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
- { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
- { 0x1A17, 0x1A18 }, { 0x1A56, 0x1A56 }, { 0x1A58, 0x1A5E },
- { 0x1A60, 0x1A60 }, { 0x1A62, 0x1A62 }, { 0x1A65, 0x1A6C },
- { 0x1A73, 0x1A7C }, { 0x1A7F, 0x1A7F }, { 0x1B00, 0x1B03 },
- { 0x1B34, 0x1B34 }, { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C },
- { 0x1B42, 0x1B42 }, { 0x1B6B, 0x1B73 }, { 0x1B80, 0x1B81 },
- { 0x1BA2, 0x1BA5 }, { 0x1BA8, 0x1BA9 }, { 0x1BAB, 0x1BAB },
- { 0x1BE6, 0x1BE6 }, { 0x1BE8, 0x1BE9 }, { 0x1BED, 0x1BED },
- { 0x1BEF, 0x1BF1 }, { 0x1C2C, 0x1C33 }, { 0x1C36, 0x1C37 },
- { 0x1CD0, 0x1CD2 }, { 0x1CD4, 0x1CE0 }, { 0x1CE2, 0x1CE8 },
- { 0x1CED, 0x1CED }, { 0x1CF4, 0x1CF4 }, { 0x1DC0, 0x1DE6 },
- { 0x1DFC, 0x1DFF }, { 0x20D0, 0x20F0 }, { 0x2CEF, 0x2CF1 },
- { 0x2D7F, 0x2D7F }, { 0x2DE0, 0x2DFF }, { 0x302A, 0x302D },
- { 0x3099, 0x309A }, { 0xA66F, 0xA672 }, { 0xA674, 0xA67D },
- { 0xA69F, 0xA69F }, { 0xA6F0, 0xA6F1 }, { 0xA802, 0xA802 },
- { 0xA806, 0xA806 }, { 0xA80B, 0xA80B }, { 0xA825, 0xA826 },
- { 0xA8C4, 0xA8C4 }, { 0xA8E0, 0xA8F1 }, { 0xA926, 0xA92D },
- { 0xA947, 0xA951 }, { 0xA980, 0xA982 }, { 0xA9B3, 0xA9B3 },
- { 0xA9B6, 0xA9B9 }, { 0xA9BC, 0xA9BC }, { 0xAA29, 0xAA2E },
- { 0xAA31, 0xAA32 }, { 0xAA35, 0xAA36 }, { 0xAA43, 0xAA43 },
- { 0xAA4C, 0xAA4C }, { 0xAAB0, 0xAAB0 }, { 0xAAB2, 0xAAB4 },
- { 0xAAB7, 0xAAB8 }, { 0xAABE, 0xAABF }, { 0xAAC1, 0xAAC1 },
- { 0xAAEC, 0xAAED }, { 0xAAF6, 0xAAF6 }, { 0xABE5, 0xABE5 },
- { 0xABE8, 0xABE8 }, { 0xABED, 0xABED }, { 0xFB1E, 0xFB1E },
- { 0xFE00, 0xFE0F }, { 0xFE20, 0xFE26 }, { 0x101FD, 0x101FD },
- { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
- { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x11001, 0x11001 },
- { 0x11038, 0x11046 }, { 0x11080, 0x11081 }, { 0x110B3, 0x110B6 },
- { 0x110B9, 0x110BA }, { 0x11100, 0x11102 }, { 0x11127, 0x1112B },
- { 0x1112D, 0x11134 }, { 0x11180, 0x11181 }, { 0x111B6, 0x111BE },
- { 0x116AB, 0x116AB }, { 0x116AD, 0x116AD }, { 0x116B0, 0x116B5 },
- { 0x116B7, 0x116B7 }, { 0x16F8F, 0x16F92 }, { 0x1D167, 0x1D169 },
- { 0x1D17B, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
- { 0x1D242, 0x1D244 }, { 0xE0100, 0xE01EF },
- };
- static const UnicodeCharSet CombiningCharacters(CombiningCharacterRanges);
-
- if (CombiningCharacters.contains(UCS))
- return 0;
-
- static const UnicodeCharRange DoubleWidthCharacterRanges[] = {
- // Hangul Jamo
- { 0x1100, 0x11FF },
- // Deprecated fullwidth angle brackets
- { 0x2329, 0x232A },
- // CJK Misc, CJK Unified Ideographs, Yijing Hexagrams, Yi
- // excluding U+303F (IDEOGRAPHIC HALF FILL SPACE)
- { 0x2E80, 0x303E }, { 0x3040, 0xA4CF },
- // Hangul
- { 0xAC00, 0xD7A3 }, { 0xD7B0, 0xD7C6 }, { 0xD7CB, 0xD7FB },
- // CJK Unified Ideographs
- { 0xF900, 0xFAFF },
- // Vertical forms
- { 0xFE10, 0xFE19 },
- // CJK Compatibility Forms + Small Form Variants
- { 0xFE30, 0xFE6F },
- // Fullwidth forms
- { 0xFF01, 0xFF60 }, { 0xFFE0, 0xFFE6 },
- // CJK Unified Ideographs
- { 0x20000, 0x2A6DF }, { 0x2A700, 0x2B81F }, { 0x2F800, 0x2FA1F }
- };
- static const UnicodeCharSet DoubleWidthCharacters(DoubleWidthCharacterRanges);
-
- if (DoubleWidthCharacters.contains(UCS))
- return 2;
- return 1;
-}
-
-int columnWidthUTF8(StringRef Text) {
- unsigned ColumnWidth = 0;
- unsigned Length;
- for (size_t i = 0, e = Text.size(); i < e; i += Length) {
- Length = getNumBytesForUTF8(Text[i]);
- if (Length <= 0 || i + Length > Text.size())
- return ErrorInvalidUTF8;
- UTF32 buf[1];
- const UTF8 *Start = reinterpret_cast<const UTF8 *>(Text.data() + i);
- UTF32 *Target = &buf[0];
- if (conversionOK != ConvertUTF8toUTF32(&Start, Start + Length, &Target,
- Target + 1, strictConversion))
- return ErrorInvalidUTF8;
- int Width = charWidth(buf[0]);
- if (Width < 0)
- return ErrorNonPrintableCharacter;
- ColumnWidth += Width;
- }
- return ColumnWidth;
-}
-
-} // namespace unicode
-} // namespace sys
-} // namespace llvm
-
diff --git a/gnu/llvm/lib/Support/UnicodeCaseFold.cpp b/gnu/llvm/lib/Support/UnicodeCaseFold.cpp
deleted file mode 100644
index b18d49dbafb..00000000000
--- a/gnu/llvm/lib/Support/UnicodeCaseFold.cpp
+++ /dev/null
@@ -1,742 +0,0 @@
-//===---------- Support/UnicodeCaseFold.cpp -------------------------------===//
-//
-// This file was generated by utils/unicode-case-fold.py from the Unicode
-// case folding database at
-// http://www.unicode.org/Public/9.0.0/ucd/CaseFolding.txt
-//
-// To regenerate this file, run:
-// utils/unicode-case-fold.py \
-// "http://www.unicode.org/Public/9.0.0/ucd/CaseFolding.txt" \
-// > lib/Support/UnicodeCaseFold.cpp
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Unicode.h"
-
-int llvm::sys::unicode::foldCharSimple(int C) {
- if (C < 0x0041)
- return C;
- // 26 characters
- if (C <= 0x005a)
- return C + 32;
- // MICRO SIGN
- if (C == 0x00b5)
- return 0x03bc;
- if (C < 0x00c0)
- return C;
- // 23 characters
- if (C <= 0x00d6)
- return C + 32;
- if (C < 0x00d8)
- return C;
- // 7 characters
- if (C <= 0x00de)
- return C + 32;
- if (C < 0x0100)
- return C;
- // 24 characters
- if (C <= 0x012e)
- return C | 1;
- if (C < 0x0132)
- return C;
- // 3 characters
- if (C <= 0x0136)
- return C | 1;
- if (C < 0x0139)
- return C;
- // 8 characters
- if (C <= 0x0147 && C % 2 == 1)
- return C + 1;
- if (C < 0x014a)
- return C;
- // 23 characters
- if (C <= 0x0176)
- return C | 1;
- // LATIN CAPITAL LETTER Y WITH DIAERESIS
- if (C == 0x0178)
- return 0x00ff;
- if (C < 0x0179)
- return C;
- // 3 characters
- if (C <= 0x017d && C % 2 == 1)
- return C + 1;
- // LATIN SMALL LETTER LONG S
- if (C == 0x017f)
- return 0x0073;
- // LATIN CAPITAL LETTER B WITH HOOK
- if (C == 0x0181)
- return 0x0253;
- if (C < 0x0182)
- return C;
- // 2 characters
- if (C <= 0x0184)
- return C | 1;
- // LATIN CAPITAL LETTER OPEN O
- if (C == 0x0186)
- return 0x0254;
- // LATIN CAPITAL LETTER C WITH HOOK
- if (C == 0x0187)
- return 0x0188;
- if (C < 0x0189)
- return C;
- // 2 characters
- if (C <= 0x018a)
- return C + 205;
- // LATIN CAPITAL LETTER D WITH TOPBAR
- if (C == 0x018b)
- return 0x018c;
- // LATIN CAPITAL LETTER REVERSED E
- if (C == 0x018e)
- return 0x01dd;
- // LATIN CAPITAL LETTER SCHWA
- if (C == 0x018f)
- return 0x0259;
- // LATIN CAPITAL LETTER OPEN E
- if (C == 0x0190)
- return 0x025b;
- // LATIN CAPITAL LETTER F WITH HOOK
- if (C == 0x0191)
- return 0x0192;
- // LATIN CAPITAL LETTER G WITH HOOK
- if (C == 0x0193)
- return 0x0260;
- // LATIN CAPITAL LETTER GAMMA
- if (C == 0x0194)
- return 0x0263;
- // LATIN CAPITAL LETTER IOTA
- if (C == 0x0196)
- return 0x0269;
- // LATIN CAPITAL LETTER I WITH STROKE
- if (C == 0x0197)
- return 0x0268;
- // LATIN CAPITAL LETTER K WITH HOOK
- if (C == 0x0198)
- return 0x0199;
- // LATIN CAPITAL LETTER TURNED M
- if (C == 0x019c)
- return 0x026f;
- // LATIN CAPITAL LETTER N WITH LEFT HOOK
- if (C == 0x019d)
- return 0x0272;
- // LATIN CAPITAL LETTER O WITH MIDDLE TILDE
- if (C == 0x019f)
- return 0x0275;
- if (C < 0x01a0)
- return C;
- // 3 characters
- if (C <= 0x01a4)
- return C | 1;
- // LATIN LETTER YR
- if (C == 0x01a6)
- return 0x0280;
- // LATIN CAPITAL LETTER TONE TWO
- if (C == 0x01a7)
- return 0x01a8;
- // LATIN CAPITAL LETTER ESH
- if (C == 0x01a9)
- return 0x0283;
- // LATIN CAPITAL LETTER T WITH HOOK
- if (C == 0x01ac)
- return 0x01ad;
- // LATIN CAPITAL LETTER T WITH RETROFLEX HOOK
- if (C == 0x01ae)
- return 0x0288;
- // LATIN CAPITAL LETTER U WITH HORN
- if (C == 0x01af)
- return 0x01b0;
- if (C < 0x01b1)
- return C;
- // 2 characters
- if (C <= 0x01b2)
- return C + 217;
- if (C < 0x01b3)
- return C;
- // 2 characters
- if (C <= 0x01b5 && C % 2 == 1)
- return C + 1;
- // LATIN CAPITAL LETTER EZH
- if (C == 0x01b7)
- return 0x0292;
- if (C < 0x01b8)
- return C;
- // 2 characters
- if (C <= 0x01bc && C % 4 == 0)
- return C + 1;
- // LATIN CAPITAL LETTER DZ WITH CARON
- if (C == 0x01c4)
- return 0x01c6;
- // LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
- if (C == 0x01c5)
- return 0x01c6;
- // LATIN CAPITAL LETTER LJ
- if (C == 0x01c7)
- return 0x01c9;
- // LATIN CAPITAL LETTER L WITH SMALL LETTER J
- if (C == 0x01c8)
- return 0x01c9;
- // LATIN CAPITAL LETTER NJ
- if (C == 0x01ca)
- return 0x01cc;
- if (C < 0x01cb)
- return C;
- // 9 characters
- if (C <= 0x01db && C % 2 == 1)
- return C + 1;
- if (C < 0x01de)
- return C;
- // 9 characters
- if (C <= 0x01ee)
- return C | 1;
- // LATIN CAPITAL LETTER DZ
- if (C == 0x01f1)
- return 0x01f3;
- if (C < 0x01f2)
- return C;
- // 2 characters
- if (C <= 0x01f4)
- return C | 1;
- // LATIN CAPITAL LETTER HWAIR
- if (C == 0x01f6)
- return 0x0195;
- // LATIN CAPITAL LETTER WYNN
- if (C == 0x01f7)
- return 0x01bf;
- if (C < 0x01f8)
- return C;
- // 20 characters
- if (C <= 0x021e)
- return C | 1;
- // LATIN CAPITAL LETTER N WITH LONG RIGHT LEG
- if (C == 0x0220)
- return 0x019e;
- if (C < 0x0222)
- return C;
- // 9 characters
- if (C <= 0x0232)
- return C | 1;
- // LATIN CAPITAL LETTER A WITH STROKE
- if (C == 0x023a)
- return 0x2c65;
- // LATIN CAPITAL LETTER C WITH STROKE
- if (C == 0x023b)
- return 0x023c;
- // LATIN CAPITAL LETTER L WITH BAR
- if (C == 0x023d)
- return 0x019a;
- // LATIN CAPITAL LETTER T WITH DIAGONAL STROKE
- if (C == 0x023e)
- return 0x2c66;
- // LATIN CAPITAL LETTER GLOTTAL STOP
- if (C == 0x0241)
- return 0x0242;
- // LATIN CAPITAL LETTER B WITH STROKE
- if (C == 0x0243)
- return 0x0180;
- // LATIN CAPITAL LETTER U BAR
- if (C == 0x0244)
- return 0x0289;
- // LATIN CAPITAL LETTER TURNED V
- if (C == 0x0245)
- return 0x028c;
- if (C < 0x0246)
- return C;
- // 5 characters
- if (C <= 0x024e)
- return C | 1;
- // COMBINING GREEK YPOGEGRAMMENI
- if (C == 0x0345)
- return 0x03b9;
- if (C < 0x0370)
- return C;
- // 2 characters
- if (C <= 0x0372)
- return C | 1;
- // GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA
- if (C == 0x0376)
- return 0x0377;
- // GREEK CAPITAL LETTER YOT
- if (C == 0x037f)
- return 0x03f3;
- // GREEK CAPITAL LETTER ALPHA WITH TONOS
- if (C == 0x0386)
- return 0x03ac;
- if (C < 0x0388)
- return C;
- // 3 characters
- if (C <= 0x038a)
- return C + 37;
- // GREEK CAPITAL LETTER OMICRON WITH TONOS
- if (C == 0x038c)
- return 0x03cc;
- if (C < 0x038e)
- return C;
- // 2 characters
- if (C <= 0x038f)
- return C + 63;
- if (C < 0x0391)
- return C;
- // 17 characters
- if (C <= 0x03a1)
- return C + 32;
- if (C < 0x03a3)
- return C;
- // 9 characters
- if (C <= 0x03ab)
- return C + 32;
- // GREEK SMALL LETTER FINAL SIGMA
- if (C == 0x03c2)
- return 0x03c3;
- // GREEK CAPITAL KAI SYMBOL
- if (C == 0x03cf)
- return 0x03d7;
- // GREEK BETA SYMBOL
- if (C == 0x03d0)
- return 0x03b2;
- // GREEK THETA SYMBOL
- if (C == 0x03d1)
- return 0x03b8;
- // GREEK PHI SYMBOL
- if (C == 0x03d5)
- return 0x03c6;
- // GREEK PI SYMBOL
- if (C == 0x03d6)
- return 0x03c0;
- if (C < 0x03d8)
- return C;
- // 12 characters
- if (C <= 0x03ee)
- return C | 1;
- // GREEK KAPPA SYMBOL
- if (C == 0x03f0)
- return 0x03ba;
- // GREEK RHO SYMBOL
- if (C == 0x03f1)
- return 0x03c1;
- // GREEK CAPITAL THETA SYMBOL
- if (C == 0x03f4)
- return 0x03b8;
- // GREEK LUNATE EPSILON SYMBOL
- if (C == 0x03f5)
- return 0x03b5;
- // GREEK CAPITAL LETTER SHO
- if (C == 0x03f7)
- return 0x03f8;
- // GREEK CAPITAL LUNATE SIGMA SYMBOL
- if (C == 0x03f9)
- return 0x03f2;
- // GREEK CAPITAL LETTER SAN
- if (C == 0x03fa)
- return 0x03fb;
- if (C < 0x03fd)
- return C;
- // 3 characters
- if (C <= 0x03ff)
- return C + -130;
- if (C < 0x0400)
- return C;
- // 16 characters
- if (C <= 0x040f)
- return C + 80;
- if (C < 0x0410)
- return C;
- // 32 characters
- if (C <= 0x042f)
- return C + 32;
- if (C < 0x0460)
- return C;
- // 17 characters
- if (C <= 0x0480)
- return C | 1;
- if (C < 0x048a)
- return C;
- // 27 characters
- if (C <= 0x04be)
- return C | 1;
- // CYRILLIC LETTER PALOCHKA
- if (C == 0x04c0)
- return 0x04cf;
- if (C < 0x04c1)
- return C;
- // 7 characters
- if (C <= 0x04cd && C % 2 == 1)
- return C + 1;
- if (C < 0x04d0)
- return C;
- // 48 characters
- if (C <= 0x052e)
- return C | 1;
- if (C < 0x0531)
- return C;
- // 38 characters
- if (C <= 0x0556)
- return C + 48;
- if (C < 0x10a0)
- return C;
- // 38 characters
- if (C <= 0x10c5)
- return C + 7264;
- if (C < 0x10c7)
- return C;
- // 2 characters
- if (C <= 0x10cd && C % 6 == 5)
- return C + 7264;
- if (C < 0x13f8)
- return C;
- // 6 characters
- if (C <= 0x13fd)
- return C + -8;
- // CYRILLIC SMALL LETTER ROUNDED VE
- if (C == 0x1c80)
- return 0x0432;
- // CYRILLIC SMALL LETTER LONG-LEGGED DE
- if (C == 0x1c81)
- return 0x0434;
- // CYRILLIC SMALL LETTER NARROW O
- if (C == 0x1c82)
- return 0x043e;
- if (C < 0x1c83)
- return C;
- // 2 characters
- if (C <= 0x1c84)
- return C + -6210;
- // CYRILLIC SMALL LETTER THREE-LEGGED TE
- if (C == 0x1c85)
- return 0x0442;
- // CYRILLIC SMALL LETTER TALL HARD SIGN
- if (C == 0x1c86)
- return 0x044a;
- // CYRILLIC SMALL LETTER TALL YAT
- if (C == 0x1c87)
- return 0x0463;
- // CYRILLIC SMALL LETTER UNBLENDED UK
- if (C == 0x1c88)
- return 0xa64b;
- if (C < 0x1e00)
- return C;
- // 75 characters
- if (C <= 0x1e94)
- return C | 1;
- // LATIN SMALL LETTER LONG S WITH DOT ABOVE
- if (C == 0x1e9b)
- return 0x1e61;
- // LATIN CAPITAL LETTER SHARP S
- if (C == 0x1e9e)
- return 0x00df;
- if (C < 0x1ea0)
- return C;
- // 48 characters
- if (C <= 0x1efe)
- return C | 1;
- if (C < 0x1f08)
- return C;
- // 8 characters
- if (C <= 0x1f0f)
- return C + -8;
- if (C < 0x1f18)
- return C;
- // 6 characters
- if (C <= 0x1f1d)
- return C + -8;
- if (C < 0x1f28)
- return C;
- // 8 characters
- if (C <= 0x1f2f)
- return C + -8;
- if (C < 0x1f38)
- return C;
- // 8 characters
- if (C <= 0x1f3f)
- return C + -8;
- if (C < 0x1f48)
- return C;
- // 6 characters
- if (C <= 0x1f4d)
- return C + -8;
- if (C < 0x1f59)
- return C;
- // 4 characters
- if (C <= 0x1f5f && C % 2 == 1)
- return C + -8;
- if (C < 0x1f68)
- return C;
- // 8 characters
- if (C <= 0x1f6f)
- return C + -8;
- if (C < 0x1f88)
- return C;
- // 8 characters
- if (C <= 0x1f8f)
- return C + -8;
- if (C < 0x1f98)
- return C;
- // 8 characters
- if (C <= 0x1f9f)
- return C + -8;
- if (C < 0x1fa8)
- return C;
- // 8 characters
- if (C <= 0x1faf)
- return C + -8;
- if (C < 0x1fb8)
- return C;
- // 2 characters
- if (C <= 0x1fb9)
- return C + -8;
- if (C < 0x1fba)
- return C;
- // 2 characters
- if (C <= 0x1fbb)
- return C + -74;
- // GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
- if (C == 0x1fbc)
- return 0x1fb3;
- // GREEK PROSGEGRAMMENI
- if (C == 0x1fbe)
- return 0x03b9;
- if (C < 0x1fc8)
- return C;
- // 4 characters
- if (C <= 0x1fcb)
- return C + -86;
- // GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
- if (C == 0x1fcc)
- return 0x1fc3;
- if (C < 0x1fd8)
- return C;
- // 2 characters
- if (C <= 0x1fd9)
- return C + -8;
- if (C < 0x1fda)
- return C;
- // 2 characters
- if (C <= 0x1fdb)
- return C + -100;
- if (C < 0x1fe8)
- return C;
- // 2 characters
- if (C <= 0x1fe9)
- return C + -8;
- if (C < 0x1fea)
- return C;
- // 2 characters
- if (C <= 0x1feb)
- return C + -112;
- // GREEK CAPITAL LETTER RHO WITH DASIA
- if (C == 0x1fec)
- return 0x1fe5;
- if (C < 0x1ff8)
- return C;
- // 2 characters
- if (C <= 0x1ff9)
- return C + -128;
- if (C < 0x1ffa)
- return C;
- // 2 characters
- if (C <= 0x1ffb)
- return C + -126;
- // GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
- if (C == 0x1ffc)
- return 0x1ff3;
- // OHM SIGN
- if (C == 0x2126)
- return 0x03c9;
- // KELVIN SIGN
- if (C == 0x212a)
- return 0x006b;
- // ANGSTROM SIGN
- if (C == 0x212b)
- return 0x00e5;
- // TURNED CAPITAL F
- if (C == 0x2132)
- return 0x214e;
- if (C < 0x2160)
- return C;
- // 16 characters
- if (C <= 0x216f)
- return C + 16;
- // ROMAN NUMERAL REVERSED ONE HUNDRED
- if (C == 0x2183)
- return 0x2184;
- if (C < 0x24b6)
- return C;
- // 26 characters
- if (C <= 0x24cf)
- return C + 26;
- if (C < 0x2c00)
- return C;
- // 47 characters
- if (C <= 0x2c2e)
- return C + 48;
- // LATIN CAPITAL LETTER L WITH DOUBLE BAR
- if (C == 0x2c60)
- return 0x2c61;
- // LATIN CAPITAL LETTER L WITH MIDDLE TILDE
- if (C == 0x2c62)
- return 0x026b;
- // LATIN CAPITAL LETTER P WITH STROKE
- if (C == 0x2c63)
- return 0x1d7d;
- // LATIN CAPITAL LETTER R WITH TAIL
- if (C == 0x2c64)
- return 0x027d;
- if (C < 0x2c67)
- return C;
- // 3 characters
- if (C <= 0x2c6b && C % 2 == 1)
- return C + 1;
- // LATIN CAPITAL LETTER ALPHA
- if (C == 0x2c6d)
- return 0x0251;
- // LATIN CAPITAL LETTER M WITH HOOK
- if (C == 0x2c6e)
- return 0x0271;
- // LATIN CAPITAL LETTER TURNED A
- if (C == 0x2c6f)
- return 0x0250;
- // LATIN CAPITAL LETTER TURNED ALPHA
- if (C == 0x2c70)
- return 0x0252;
- if (C < 0x2c72)
- return C;
- // 2 characters
- if (C <= 0x2c75 && C % 3 == 2)
- return C + 1;
- if (C < 0x2c7e)
- return C;
- // 2 characters
- if (C <= 0x2c7f)
- return C + -10815;
- if (C < 0x2c80)
- return C;
- // 50 characters
- if (C <= 0x2ce2)
- return C | 1;
- if (C < 0x2ceb)
- return C;
- // 2 characters
- if (C <= 0x2ced && C % 2 == 1)
- return C + 1;
- if (C < 0x2cf2)
- return C;
- // 2 characters
- if (C <= 0xa640 && C % 31054 == 11506)
- return C + 1;
- if (C < 0xa642)
- return C;
- // 22 characters
- if (C <= 0xa66c)
- return C | 1;
- if (C < 0xa680)
- return C;
- // 14 characters
- if (C <= 0xa69a)
- return C | 1;
- if (C < 0xa722)
- return C;
- // 7 characters
- if (C <= 0xa72e)
- return C | 1;
- if (C < 0xa732)
- return C;
- // 31 characters
- if (C <= 0xa76e)
- return C | 1;
- if (C < 0xa779)
- return C;
- // 2 characters
- if (C <= 0xa77b && C % 2 == 1)
- return C + 1;
- // LATIN CAPITAL LETTER INSULAR G
- if (C == 0xa77d)
- return 0x1d79;
- if (C < 0xa77e)
- return C;
- // 5 characters
- if (C <= 0xa786)
- return C | 1;
- // LATIN CAPITAL LETTER SALTILLO
- if (C == 0xa78b)
- return 0xa78c;
- // LATIN CAPITAL LETTER TURNED H
- if (C == 0xa78d)
- return 0x0265;
- if (C < 0xa790)
- return C;
- // 2 characters
- if (C <= 0xa792)
- return C | 1;
- if (C < 0xa796)
- return C;
- // 10 characters
- if (C <= 0xa7a8)
- return C | 1;
- // LATIN CAPITAL LETTER H WITH HOOK
- if (C == 0xa7aa)
- return 0x0266;
- // LATIN CAPITAL LETTER REVERSED OPEN E
- if (C == 0xa7ab)
- return 0x025c;
- // LATIN CAPITAL LETTER SCRIPT G
- if (C == 0xa7ac)
- return 0x0261;
- // LATIN CAPITAL LETTER L WITH BELT
- if (C == 0xa7ad)
- return 0x026c;
- // LATIN CAPITAL LETTER SMALL CAPITAL I
- if (C == 0xa7ae)
- return 0x026a;
- // LATIN CAPITAL LETTER TURNED K
- if (C == 0xa7b0)
- return 0x029e;
- // LATIN CAPITAL LETTER TURNED T
- if (C == 0xa7b1)
- return 0x0287;
- // LATIN CAPITAL LETTER J WITH CROSSED-TAIL
- if (C == 0xa7b2)
- return 0x029d;
- // LATIN CAPITAL LETTER CHI
- if (C == 0xa7b3)
- return 0xab53;
- if (C < 0xa7b4)
- return C;
- // 2 characters
- if (C <= 0xa7b6)
- return C | 1;
- if (C < 0xab70)
- return C;
- // 80 characters
- if (C <= 0xabbf)
- return C + -38864;
- if (C < 0xff21)
- return C;
- // 26 characters
- if (C <= 0xff3a)
- return C + 32;
- if (C < 0x10400)
- return C;
- // 40 characters
- if (C <= 0x10427)
- return C + 40;
- if (C < 0x104b0)
- return C;
- // 36 characters
- if (C <= 0x104d3)
- return C + 40;
- if (C < 0x10c80)
- return C;
- // 51 characters
- if (C <= 0x10cb2)
- return C + 64;
- if (C < 0x118a0)
- return C;
- // 32 characters
- if (C <= 0x118bf)
- return C + 32;
- if (C < 0x1e900)
- return C;
- // 34 characters
- if (C <= 0x1e921)
- return C + 34;
-
- return C;
-}
diff --git a/gnu/llvm/lib/Support/Unix/COM.inc b/gnu/llvm/lib/Support/Unix/COM.inc
deleted file mode 100644
index 5b71de74ebf..00000000000
--- a/gnu/llvm/lib/Support/Unix/COM.inc
+++ /dev/null
@@ -1,27 +0,0 @@
-//===- llvm/Support/Unix/COM.inc - Unix COM Implementation -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Unix portion of COM support.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
-namespace sys {
-
-InitializeCOMRAII::InitializeCOMRAII(COMThreadingMode Threading,
- bool SpeedOverMemory) {}
-
-InitializeCOMRAII::~InitializeCOMRAII() {}
-}
-}
diff --git a/gnu/llvm/lib/Support/Unix/DynamicLibrary.inc b/gnu/llvm/lib/Support/Unix/DynamicLibrary.inc
deleted file mode 100644
index 029451f347e..00000000000
--- a/gnu/llvm/lib/Support/Unix/DynamicLibrary.inc
+++ /dev/null
@@ -1,135 +0,0 @@
-//===- Unix/DynamicLibrary.cpp - Unix DL Implementation ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides the UNIX specific implementation of DynamicLibrary.
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
-#include <dlfcn.h>
-
-DynamicLibrary::HandleSet::~HandleSet() {
- // Close the libraries in reverse order.
- for (void *Handle : llvm::reverse(Handles))
- ::dlclose(Handle);
- if (Process)
- ::dlclose(Process);
-
- // llvm_shutdown called, Return to default
- DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker;
-}
-
-void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
- void *Handle = ::dlopen(File, RTLD_LAZY|RTLD_GLOBAL);
- if (!Handle) {
- if (Err) *Err = ::dlerror();
- return &DynamicLibrary::Invalid;
- }
-
-#ifdef __CYGWIN__
- // Cygwin searches symbols only in the main
- // with the handle of dlopen(NULL, RTLD_GLOBAL).
- if (!File)
- Handle = RTLD_DEFAULT;
-#endif
-
- return Handle;
-}
-
-void DynamicLibrary::HandleSet::DLClose(void *Handle) {
- ::dlclose(Handle);
-}
-
-void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
- return ::dlsym(Handle, Symbol);
-}
-
-#else // !HAVE_DLOPEN
-
-DynamicLibrary::HandleSet::~HandleSet() {}
-
-void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
- if (Err) *Err = "dlopen() not supported on this platform";
- return &Invalid;
-}
-
-void DynamicLibrary::HandleSet::DLClose(void *Handle) {
-}
-
-void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
- return nullptr;
-}
-
-#endif
-
-// Must declare the symbols in the global namespace.
-static void *DoSearch(const char* SymbolName) {
-#define EXPLICIT_SYMBOL(SYM) \
- extern void *SYM; if (!strcmp(SymbolName, #SYM)) return (void*)&SYM
-
- // If this is darwin, it has some funky issues, try to solve them here. Some
- // important symbols are marked 'private external' which doesn't allow
- // SearchForAddressOfSymbol to find them. As such, we special case them here,
- // there is only a small handful of them.
-
-#ifdef __APPLE__
- {
- // __eprintf is sometimes used for assert() handling on x86.
- //
- // FIXME: Currently disabled when using Clang, as we don't always have our
- // runtime support libraries available.
-#ifndef __clang__
-#ifdef __i386__
- EXPLICIT_SYMBOL(__eprintf);
-#endif
-#endif
- }
-#endif
-
-#ifdef __CYGWIN__
- {
- EXPLICIT_SYMBOL(_alloca);
- EXPLICIT_SYMBOL(__main);
- }
-#endif
-
-#undef EXPLICIT_SYMBOL
-
-// This macro returns the address of a well-known, explicit symbol
-#define EXPLICIT_SYMBOL(SYM) \
- if (!strcmp(SymbolName, #SYM)) return &SYM
-
-// Under glibc we have a weird situation. The stderr/out/in symbols are both
-// macros and global variables because of standards requirements. So, we
-// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
-#if defined(__GLIBC__)
- {
- EXPLICIT_SYMBOL(stderr);
- EXPLICIT_SYMBOL(stdout);
- EXPLICIT_SYMBOL(stdin);
- }
-#else
- // For everything else, we want to check to make sure the symbol isn't defined
- // as a macro before using EXPLICIT_SYMBOL.
- {
-#ifndef stdin
- EXPLICIT_SYMBOL(stdin);
-#endif
-#ifndef stdout
- EXPLICIT_SYMBOL(stdout);
-#endif
-#ifndef stderr
- EXPLICIT_SYMBOL(stderr);
-#endif
- }
-#endif
-#undef EXPLICIT_SYMBOL
-
- return nullptr;
-}
diff --git a/gnu/llvm/lib/Support/Unix/Host.inc b/gnu/llvm/lib/Support/Unix/Host.inc
deleted file mode 100644
index b65f84bf444..00000000000
--- a/gnu/llvm/lib/Support/Unix/Host.inc
+++ /dev/null
@@ -1,68 +0,0 @@
-//===- llvm/Support/Unix/Host.inc -------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the UNIX Host support.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-#include "Unix.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Config/config.h"
-#include <cctype>
-#include <string>
-#include <sys/utsname.h>
-
-using namespace llvm;
-
-static std::string getOSVersion() {
- struct utsname info;
-
- if (uname(&info))
- return "";
-
- return info.release;
-}
-
-static std::string updateTripleOSVersion(std::string TargetTripleString) {
- // On darwin, we want to update the version to match that of the target.
- std::string::size_type DarwinDashIdx = TargetTripleString.find("-darwin");
- if (DarwinDashIdx != std::string::npos) {
- TargetTripleString.resize(DarwinDashIdx + strlen("-darwin"));
- TargetTripleString += getOSVersion();
- return TargetTripleString;
- }
- std::string::size_type MacOSDashIdx = TargetTripleString.find("-macos");
- if (MacOSDashIdx != std::string::npos) {
- TargetTripleString.resize(MacOSDashIdx);
- // Reset the OS to darwin as the OS version from `uname` doesn't use the
- // macOS version scheme.
- TargetTripleString += "-darwin";
- TargetTripleString += getOSVersion();
- }
- return TargetTripleString;
-}
-
-std::string sys::getDefaultTargetTriple() {
- std::string TargetTripleString =
- updateTripleOSVersion(LLVM_DEFAULT_TARGET_TRIPLE);
-
- // Override the default target with an environment variable named by
- // LLVM_TARGET_TRIPLE_ENV.
-#if defined(LLVM_TARGET_TRIPLE_ENV)
- if (const char *EnvTriple = std::getenv(LLVM_TARGET_TRIPLE_ENV))
- TargetTripleString = EnvTriple;
-#endif
-
- return TargetTripleString;
-}
diff --git a/gnu/llvm/lib/Support/Unix/Memory.inc b/gnu/llvm/lib/Support/Unix/Memory.inc
deleted file mode 100644
index adbfff2f59a..00000000000
--- a/gnu/llvm/lib/Support/Unix/Memory.inc
+++ /dev/null
@@ -1,249 +0,0 @@
-//===- Unix/Memory.cpp - Generic UNIX System Configuration ------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines some functions for various memory management utilities.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Unix.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Process.h"
-
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#ifdef __APPLE__
-#include <mach/mach.h>
-#endif
-
-#ifdef __Fuchsia__
-#include <zircon/syscalls.h>
-#endif
-
-#if defined(__mips__)
-# if defined(__OpenBSD__)
-# include <mips64/sysarch.h>
-# elif !defined(__FreeBSD__)
-# include <sys/cachectl.h>
-# endif
-#endif
-
-#if defined(__APPLE__)
-extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
-#else
-extern "C" void __clear_cache(void *, void*);
-#endif
-
-namespace {
-
-int getPosixProtectionFlags(unsigned Flags) {
- switch (Flags) {
- case llvm::sys::Memory::MF_READ:
- return PROT_READ;
- case llvm::sys::Memory::MF_WRITE:
- return PROT_WRITE;
- case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_WRITE:
- return PROT_READ | PROT_WRITE;
- case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC:
- return PROT_READ | PROT_EXEC;
- case llvm::sys::Memory::MF_READ | llvm::sys::Memory::MF_WRITE |
- llvm::sys::Memory::MF_EXEC:
- return PROT_READ | PROT_WRITE | PROT_EXEC;
- case llvm::sys::Memory::MF_EXEC:
-#if defined(__FreeBSD__)
- // On PowerPC, having an executable page that has no read permission
- // can have unintended consequences. The function InvalidateInstruction-
- // Cache uses instructions dcbf and icbi, both of which are treated by
- // the processor as loads. If the page has no read permissions,
- // executing these instructions will result in a segmentation fault.
- // Somehow, this problem is not present on Linux, but it does happen
- // on FreeBSD.
- return PROT_READ | PROT_EXEC;
-#else
- return PROT_EXEC;
-#endif
- default:
- llvm_unreachable("Illegal memory protection flag specified!");
- }
- // Provide a default return value as required by some compilers.
- return PROT_NONE;
-}
-
-} // anonymous namespace
-
-namespace llvm {
-namespace sys {
-
-MemoryBlock
-Memory::allocateMappedMemory(size_t NumBytes,
- const MemoryBlock *const NearBlock,
- unsigned PFlags,
- std::error_code &EC) {
- EC = std::error_code();
- if (NumBytes == 0)
- return MemoryBlock();
-
- static const size_t PageSize = Process::getPageSize();
- const size_t NumPages = (NumBytes+PageSize-1)/PageSize;
-
- int fd = -1;
-
- int MMFlags = MAP_PRIVATE |
-#ifdef MAP_ANONYMOUS
- MAP_ANONYMOUS
-#else
- MAP_ANON
-#endif
- ; // Ends statement above
-
- int Protect = getPosixProtectionFlags(PFlags);
-
-#if defined(__NetBSD__) && defined(PROT_MPROTECT)
- Protect |= PROT_MPROTECT(PROT_READ | PROT_WRITE | PROT_EXEC);
-#endif
-
- // Use any near hint and the page size to set a page-aligned starting address
- uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) +
- NearBlock->size() : 0;
- if (Start && Start % PageSize)
- Start += PageSize - Start % PageSize;
-
- void *Addr = ::mmap(reinterpret_cast<void*>(Start), PageSize*NumPages,
- Protect, MMFlags, fd, 0);
- if (Addr == MAP_FAILED) {
- if (NearBlock) //Try again without a near hint
- return allocateMappedMemory(NumBytes, nullptr, PFlags, EC);
-
- EC = std::error_code(errno, std::generic_category());
- return MemoryBlock();
- }
-
- MemoryBlock Result;
- Result.Address = Addr;
- Result.Size = NumPages*PageSize;
-
- // Rely on protectMappedMemory to invalidate instruction cache.
- if (PFlags & MF_EXEC) {
- EC = Memory::protectMappedMemory (Result, PFlags);
- if (EC != std::error_code())
- return MemoryBlock();
- }
-
- return Result;
-}
-
-std::error_code
-Memory::releaseMappedMemory(MemoryBlock &M) {
- if (M.Address == nullptr || M.Size == 0)
- return std::error_code();
-
- if (0 != ::munmap(M.Address, M.Size))
- return std::error_code(errno, std::generic_category());
-
- M.Address = nullptr;
- M.Size = 0;
-
- return std::error_code();
-}
-
-std::error_code
-Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) {
- static const size_t PageSize = Process::getPageSize();
- if (M.Address == nullptr || M.Size == 0)
- return std::error_code();
-
- if (!Flags)
- return std::error_code(EINVAL, std::generic_category());
-
- int Protect = getPosixProtectionFlags(Flags);
- uintptr_t Start = alignAddr((uint8_t *)M.Address - PageSize + 1, PageSize);
- uintptr_t End = alignAddr((uint8_t *)M.Address + M.Size, PageSize);
-
- bool InvalidateCache = (Flags & MF_EXEC);
-
-#if defined(__arm__) || defined(__aarch64__)
- // Certain ARM implementations treat icache clear instruction as a memory read,
- // and CPU segfaults on trying to clear cache on !PROT_READ page. Therefore we need
- // to temporarily add PROT_READ for the sake of flushing the instruction caches.
- if (InvalidateCache && !(Protect & PROT_READ)) {
- int Result = ::mprotect((void *)Start, End - Start, Protect | PROT_READ);
- if (Result != 0)
- return std::error_code(errno, std::generic_category());
-
- Memory::InvalidateInstructionCache(M.Address, M.Size);
- InvalidateCache = false;
- }
-#endif
-
- int Result = ::mprotect((void *)Start, End - Start, Protect);
-
- if (Result != 0)
- return std::error_code(errno, std::generic_category());
-
- if (InvalidateCache)
- Memory::InvalidateInstructionCache(M.Address, M.Size);
-
- return std::error_code();
-}
-
-/// InvalidateInstructionCache - Before the JIT can run a block of code
-/// that has been emitted it must invalidate the instruction cache on some
-/// platforms.
-void Memory::InvalidateInstructionCache(const void *Addr,
- size_t Len) {
-
-// icache invalidation for PPC and ARM.
-#if defined(__APPLE__)
-
-# if (defined(__POWERPC__) || defined (__ppc__) || \
- defined(_POWER) || defined(_ARCH_PPC) || defined(__arm__) || \
- defined(__arm64__))
- sys_icache_invalidate(const_cast<void *>(Addr), Len);
-# endif
-
-#elif defined(__Fuchsia__)
-
- zx_status_t Status = zx_cache_flush(Addr, Len, ZX_CACHE_FLUSH_INSN);
- assert(Status == ZX_OK && "cannot invalidate instruction cache");
-
-#else
-
-# if (defined(__POWERPC__) || defined (__ppc__) || \
- defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__)
- const size_t LineSize = 32;
-
- const intptr_t Mask = ~(LineSize - 1);
- const intptr_t StartLine = ((intptr_t) Addr) & Mask;
- const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask;
-
- for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
- asm volatile("dcbf 0, %0" : : "r"(Line));
- asm volatile("sync");
-
- for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
- asm volatile("icbi 0, %0" : : "r"(Line));
- asm volatile("isync");
-# elif (defined(__arm__) || defined(__aarch64__) || defined(__mips__)) && \
- defined(__GNUC__)
- // FIXME: Can we safely always call this for __GNUC__ everywhere?
- const char *Start = static_cast<const char *>(Addr);
- const char *End = Start + Len;
- __clear_cache(const_cast<char *>(Start), const_cast<char *>(End));
-# endif
-
-#endif // end apple
-
- ValgrindDiscardTranslations(Addr, Len);
-}
-
-} // namespace sys
-} // namespace llvm
diff --git a/gnu/llvm/lib/Support/Unix/Mutex.inc b/gnu/llvm/lib/Support/Unix/Mutex.inc
deleted file mode 100644
index fe6b1704145..00000000000
--- a/gnu/llvm/lib/Support/Unix/Mutex.inc
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- llvm/Support/Unix/Mutex.inc - Unix Mutex Implementation ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Unix specific (non-pthread) Mutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-namespace llvm
-{
-using namespace sys;
-
-MutexImpl::MutexImpl( bool recursive)
-{
-}
-
-MutexImpl::~MutexImpl()
-{
-}
-
-bool
-MutexImpl::release()
-{
- return true;
-}
-
-bool
-MutexImpl::tryacquire( void )
-{
- return true;
-}
-
-}
diff --git a/gnu/llvm/lib/Support/Unix/Path.inc b/gnu/llvm/lib/Support/Unix/Path.inc
deleted file mode 100644
index d7cc0d627d0..00000000000
--- a/gnu/llvm/lib/Support/Unix/Path.inc
+++ /dev/null
@@ -1,1067 +0,0 @@
-//===- llvm/Support/Unix/Path.inc - Unix Path Implementation ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Unix specific implementation of the Path API.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-#include "Unix.h"
-#include <limits.h>
-#include <stdio.h>
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#include <dirent.h>
-#include <pwd.h>
-
-#ifdef __APPLE__
-#include <mach-o/dyld.h>
-#include <sys/attr.h>
-#elif defined(__DragonFly__)
-#include <sys/mount.h>
-#endif
-
-// Both stdio.h and cstdio are included via different paths and
-// stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros
-// either.
-#undef ferror
-#undef feof
-
-// For GNU Hurd
-#if defined(__GNU__) && !defined(PATH_MAX)
-# define PATH_MAX 4096
-# define MAXPATHLEN 4096
-#endif
-
-#include <sys/types.h>
-#if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && \
- !defined(__linux__) && !defined(__FreeBSD_kernel__)
-#include <sys/statvfs.h>
-#define STATVFS statvfs
-#define FSTATVFS fstatvfs
-#define STATVFS_F_FRSIZE(vfs) vfs.f_frsize
-#else
-#if defined(__OpenBSD__) || defined(__FreeBSD__)
-#include <sys/mount.h>
-#include <sys/param.h>
-#elif defined(__linux__)
-#if defined(HAVE_LINUX_MAGIC_H)
-#include <linux/magic.h>
-#else
-#if defined(HAVE_LINUX_NFS_FS_H)
-#include <linux/nfs_fs.h>
-#endif
-#if defined(HAVE_LINUX_SMB_H)
-#include <linux/smb.h>
-#endif
-#endif
-#include <sys/vfs.h>
-#else
-#include <sys/mount.h>
-#endif
-#define STATVFS statfs
-#define FSTATVFS fstatfs
-#define STATVFS_F_FRSIZE(vfs) static_cast<uint64_t>(vfs.f_bsize)
-#endif
-
-#if defined(__NetBSD__) || defined(__DragonFly__) || defined(__GNU__)
-#define STATVFS_F_FLAG(vfs) (vfs).f_flag
-#else
-#define STATVFS_F_FLAG(vfs) (vfs).f_flags
-#endif
-
-using namespace llvm;
-
-namespace llvm {
-namespace sys {
-namespace fs {
-
-const file_t kInvalidFile = -1;
-
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
- defined(__minix) || defined(__FreeBSD_kernel__) || defined(__linux__) || \
- defined(__CYGWIN__) || defined(__DragonFly__) || defined(_AIX) || defined(__GNU__)
-static int
-test_dir(char ret[PATH_MAX], const char *dir, const char *bin)
-{
- struct stat sb;
- char fullpath[PATH_MAX];
-
- snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin);
- if (!realpath(fullpath, ret))
- return 1;
- if (stat(fullpath, &sb) != 0)
- return 1;
-
- return 0;
-}
-
-static char *
-getprogpath(char ret[PATH_MAX], const char *bin)
-{
- char *pv, *s, *t;
-
- /* First approach: absolute path. */
- if (bin[0] == '/') {
- if (test_dir(ret, "/", bin) == 0)
- return ret;
- return nullptr;
- }
-
- /* Second approach: relative path. */
- if (strchr(bin, '/')) {
- char cwd[PATH_MAX];
- if (!getcwd(cwd, PATH_MAX))
- return nullptr;
- if (test_dir(ret, cwd, bin) == 0)
- return ret;
- return nullptr;
- }
-
- /* Third approach: $PATH */
- if ((pv = getenv("PATH")) == nullptr)
- return nullptr;
- s = pv = strdup(pv);
- if (!pv)
- return nullptr;
- while ((t = strsep(&s, ":")) != nullptr) {
- if (test_dir(ret, t, bin) == 0) {
- free(pv);
- return ret;
- }
- }
- free(pv);
- return nullptr;
-}
-#endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__
-
-/// GetMainExecutable - Return the path to the main executable, given the
-/// value of argv[0] from program startup.
-std::string getMainExecutable(const char *argv0, void *MainAddr) {
-#if defined(__APPLE__)
- // On OS X the executable path is saved to the stack by dyld. Reading it
- // from there is much faster than calling dladdr, especially for large
- // binaries with symbols.
- char exe_path[MAXPATHLEN];
- uint32_t size = sizeof(exe_path);
- if (_NSGetExecutablePath(exe_path, &size) == 0) {
- char link_path[MAXPATHLEN];
- if (realpath(exe_path, link_path))
- return link_path;
- }
-#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
- defined(__minix) || defined(__DragonFly__) || \
- defined(__FreeBSD_kernel__) || defined(_AIX)
- char exe_path[PATH_MAX];
-
- if (getprogpath(exe_path, argv0) != NULL)
- return exe_path;
-#elif defined(__linux__) || defined(__CYGWIN__)
- char exe_path[MAXPATHLEN];
- StringRef aPath("/proc/self/exe");
- if (sys::fs::exists(aPath)) {
- // /proc is not always mounted under Linux (chroot for example).
- ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path));
- if (len < 0)
- return "";
-
- // Null terminate the string for realpath. readlink never null
- // terminates its output.
- len = std::min(len, ssize_t(sizeof(exe_path) - 1));
- exe_path[len] = '\0';
-
- // On Linux, /proc/self/exe always looks through symlinks. However, on
- // GNU/Hurd, /proc/self/exe is a symlink to the path that was used to start
- // the program, and not the eventual binary file. Therefore, call realpath
- // so this behaves the same on all platforms.
-#if _POSIX_VERSION >= 200112 || defined(__GLIBC__)
- char *real_path = realpath(exe_path, NULL);
- std::string ret = std::string(real_path);
- free(real_path);
- return ret;
-#else
- char real_path[MAXPATHLEN];
- realpath(exe_path, real_path);
- return std::string(real_path);
-#endif
- } else {
- // Fall back to the classical detection.
- if (getprogpath(exe_path, argv0))
- return exe_path;
- }
-#elif defined(HAVE_DLFCN_H) && defined(HAVE_DLADDR)
- // Use dladdr to get executable path if available.
- Dl_info DLInfo;
- int err = dladdr(MainAddr, &DLInfo);
- if (err == 0)
- return "";
-
- // If the filename is a symlink, we need to resolve and return the location of
- // the actual executable.
- char link_path[MAXPATHLEN];
- if (realpath(DLInfo.dli_fname, link_path))
- return link_path;
-#else
-#error GetMainExecutable is not implemented on this host yet.
-#endif
- return "";
-}
-
-TimePoint<> basic_file_status::getLastAccessedTime() const {
- return toTimePoint(fs_st_atime, fs_st_atime_nsec);
-}
-
-TimePoint<> basic_file_status::getLastModificationTime() const {
- return toTimePoint(fs_st_mtime, fs_st_mtime_nsec);
-}
-
-UniqueID file_status::getUniqueID() const {
- return UniqueID(fs_st_dev, fs_st_ino);
-}
-
-uint32_t file_status::getLinkCount() const {
- return fs_st_nlinks;
-}
-
-ErrorOr<space_info> disk_space(const Twine &Path) {
- struct STATVFS Vfs;
- if (::STATVFS(Path.str().c_str(), &Vfs))
- return std::error_code(errno, std::generic_category());
- auto FrSize = STATVFS_F_FRSIZE(Vfs);
- space_info SpaceInfo;
- SpaceInfo.capacity = static_cast<uint64_t>(Vfs.f_blocks) * FrSize;
- SpaceInfo.free = static_cast<uint64_t>(Vfs.f_bfree) * FrSize;
- SpaceInfo.available = static_cast<uint64_t>(Vfs.f_bavail) * FrSize;
- return SpaceInfo;
-}
-
-std::error_code current_path(SmallVectorImpl<char> &result) {
- result.clear();
-
- const char *pwd = ::getenv("PWD");
- llvm::sys::fs::file_status PWDStatus, DotStatus;
- if (pwd && llvm::sys::path::is_absolute(pwd) &&
- !llvm::sys::fs::status(pwd, PWDStatus) &&
- !llvm::sys::fs::status(".", DotStatus) &&
- PWDStatus.getUniqueID() == DotStatus.getUniqueID()) {
- result.append(pwd, pwd + strlen(pwd));
- return std::error_code();
- }
-
-#ifdef MAXPATHLEN
- result.reserve(MAXPATHLEN);
-#else
-// For GNU Hurd
- result.reserve(1024);
-#endif
-
- while (true) {
- if (::getcwd(result.data(), result.capacity()) == nullptr) {
- // See if there was a real error.
- if (errno != ENOMEM)
- return std::error_code(errno, std::generic_category());
- // Otherwise there just wasn't enough space.
- result.reserve(result.capacity() * 2);
- } else
- break;
- }
-
- result.set_size(strlen(result.data()));
- return std::error_code();
-}
-
-std::error_code set_current_path(const Twine &path) {
- SmallString<128> path_storage;
- StringRef p = path.toNullTerminatedStringRef(path_storage);
-
- if (::chdir(p.begin()) == -1)
- return std::error_code(errno, std::generic_category());
-
- return std::error_code();
-}
-
-std::error_code create_directory(const Twine &path, bool IgnoreExisting,
- perms Perms) {
- SmallString<128> path_storage;
- StringRef p = path.toNullTerminatedStringRef(path_storage);
-
- if (::mkdir(p.begin(), Perms) == -1) {
- if (errno != EEXIST || !IgnoreExisting)
- return std::error_code(errno, std::generic_category());
- }
-
- return std::error_code();
-}
-
-// Note that we are using symbolic link because hard links are not supported by
-// all filesystems (SMB doesn't).
-std::error_code create_link(const Twine &to, const Twine &from) {
- // Get arguments.
- SmallString<128> from_storage;
- SmallString<128> to_storage;
- StringRef f = from.toNullTerminatedStringRef(from_storage);
- StringRef t = to.toNullTerminatedStringRef(to_storage);
-
- if (::symlink(t.begin(), f.begin()) == -1)
- return std::error_code(errno, std::generic_category());
-
- return std::error_code();
-}
-
-std::error_code create_hard_link(const Twine &to, const Twine &from) {
- // Get arguments.
- SmallString<128> from_storage;
- SmallString<128> to_storage;
- StringRef f = from.toNullTerminatedStringRef(from_storage);
- StringRef t = to.toNullTerminatedStringRef(to_storage);
-
- if (::link(t.begin(), f.begin()) == -1)
- return std::error_code(errno, std::generic_category());
-
- return std::error_code();
-}
-
-std::error_code remove(const Twine &path, bool IgnoreNonExisting) {
- SmallString<128> path_storage;
- StringRef p = path.toNullTerminatedStringRef(path_storage);
-
- struct stat buf;
- if (lstat(p.begin(), &buf) != 0) {
- if (errno != ENOENT || !IgnoreNonExisting)
- return std::error_code(errno, std::generic_category());
- return std::error_code();
- }
-
- // Note: this check catches strange situations. In all cases, LLVM should
- // only be involved in the creation and deletion of regular files. This
- // check ensures that what we're trying to erase is a regular file. It
- // effectively prevents LLVM from erasing things like /dev/null, any block
- // special file, or other things that aren't "regular" files.
- if (!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) && !S_ISLNK(buf.st_mode))
- return make_error_code(errc::operation_not_permitted);
-
- if (::remove(p.begin()) == -1) {
- if (errno != ENOENT || !IgnoreNonExisting)
- return std::error_code(errno, std::generic_category());
- }
-
- return std::error_code();
-}
-
-static bool is_local_impl(struct STATVFS &Vfs) {
-#if defined(__linux__) || defined(__GNU__)
-#ifndef NFS_SUPER_MAGIC
-#define NFS_SUPER_MAGIC 0x6969
-#endif
-#ifndef SMB_SUPER_MAGIC
-#define SMB_SUPER_MAGIC 0x517B
-#endif
-#ifndef CIFS_MAGIC_NUMBER
-#define CIFS_MAGIC_NUMBER 0xFF534D42
-#endif
-#ifdef __GNU__
- switch ((uint32_t)Vfs.__f_type) {
-#else
- switch ((uint32_t)Vfs.f_type) {
-#endif
- case NFS_SUPER_MAGIC:
- case SMB_SUPER_MAGIC:
- case CIFS_MAGIC_NUMBER:
- return false;
- default:
- return true;
- }
-#elif defined(__CYGWIN__)
- // Cygwin doesn't expose this information; would need to use Win32 API.
- return false;
-#elif defined(__Fuchsia__)
- // Fuchsia doesn't yet support remote filesystem mounts.
- return true;
-#elif defined(__HAIKU__)
- // Haiku doesn't expose this information.
- return false;
-#elif defined(__sun)
- // statvfs::f_basetype contains a null-terminated FSType name of the mounted target
- StringRef fstype(Vfs.f_basetype);
- // NFS is the only non-local fstype??
- return !fstype.equals("nfs");
-#else
- return !!(STATVFS_F_FLAG(Vfs) & MNT_LOCAL);
-#endif
-}
-
-std::error_code is_local(const Twine &Path, bool &Result) {
- struct STATVFS Vfs;
- if (::STATVFS(Path.str().c_str(), &Vfs))
- return std::error_code(errno, std::generic_category());
-
- Result = is_local_impl(Vfs);
- return std::error_code();
-}
-
-std::error_code is_local(int FD, bool &Result) {
- struct STATVFS Vfs;
- if (::FSTATVFS(FD, &Vfs))
- return std::error_code(errno, std::generic_category());
-
- Result = is_local_impl(Vfs);
- return std::error_code();
-}
-
-std::error_code rename(const Twine &from, const Twine &to) {
- // Get arguments.
- SmallString<128> from_storage;
- SmallString<128> to_storage;
- StringRef f = from.toNullTerminatedStringRef(from_storage);
- StringRef t = to.toNullTerminatedStringRef(to_storage);
-
- if (::rename(f.begin(), t.begin()) == -1)
- return std::error_code(errno, std::generic_category());
-
- return std::error_code();
-}
-
-std::error_code resize_file(int FD, uint64_t Size) {
-#if defined(HAVE_POSIX_FALLOCATE)
- // If we have posix_fallocate use it. Unlike ftruncate it always allocates
- // space, so we get an error if the disk is full.
- if (int Err = ::posix_fallocate(FD, 0, Size)) {
- if (Err != EINVAL && Err != EOPNOTSUPP)
- return std::error_code(Err, std::generic_category());
- }
-#endif
- // Use ftruncate as a fallback. It may or may not allocate space. At least on
- // OS X with HFS+ it does.
- if (::ftruncate(FD, Size) == -1)
- return std::error_code(errno, std::generic_category());
-
- return std::error_code();
-}
-
-static int convertAccessMode(AccessMode Mode) {
- switch (Mode) {
- case AccessMode::Exist:
- return F_OK;
- case AccessMode::Write:
- return W_OK;
- case AccessMode::Execute:
- return R_OK | X_OK; // scripts also need R_OK.
- }
- llvm_unreachable("invalid enum");
-}
-
-std::error_code access(const Twine &Path, AccessMode Mode) {
- SmallString<128> PathStorage;
- StringRef P = Path.toNullTerminatedStringRef(PathStorage);
-
- if (::access(P.begin(), convertAccessMode(Mode)) == -1)
- return std::error_code(errno, std::generic_category());
-
- if (Mode == AccessMode::Execute) {
- // Don't say that directories are executable.
- struct stat buf;
- if (0 != stat(P.begin(), &buf))
- return errc::permission_denied;
- if (!S_ISREG(buf.st_mode))
- return errc::permission_denied;
- }
-
- return std::error_code();
-}
-
-bool can_execute(const Twine &Path) {
- return !access(Path, AccessMode::Execute);
-}
-
-bool equivalent(file_status A, file_status B) {
- assert(status_known(A) && status_known(B));
- return A.fs_st_dev == B.fs_st_dev &&
- A.fs_st_ino == B.fs_st_ino;
-}
-
-std::error_code equivalent(const Twine &A, const Twine &B, bool &result) {
- file_status fsA, fsB;
- if (std::error_code ec = status(A, fsA))
- return ec;
- if (std::error_code ec = status(B, fsB))
- return ec;
- result = equivalent(fsA, fsB);
- return std::error_code();
-}
-
-static void expandTildeExpr(SmallVectorImpl<char> &Path) {
- StringRef PathStr(Path.begin(), Path.size());
- if (PathStr.empty() || !PathStr.startswith("~"))
- return;
-
- PathStr = PathStr.drop_front();
- StringRef Expr =
- PathStr.take_until([](char c) { return path::is_separator(c); });
- StringRef Remainder = PathStr.substr(Expr.size() + 1);
- SmallString<128> Storage;
- if (Expr.empty()) {
- // This is just ~/..., resolve it to the current user's home dir.
- if (!path::home_directory(Storage)) {
- // For some reason we couldn't get the home directory. Just exit.
- return;
- }
-
- // Overwrite the first character and insert the rest.
- Path[0] = Storage[0];
- Path.insert(Path.begin() + 1, Storage.begin() + 1, Storage.end());
- return;
- }
-
- // This is a string of the form ~username/, look up this user's entry in the
- // password database.
- struct passwd *Entry = nullptr;
- std::string User = Expr.str();
- Entry = ::getpwnam(User.c_str());
-
- if (!Entry) {
- // Unable to look up the entry, just return back the original path.
- return;
- }
-
- Storage = Remainder;
- Path.clear();
- Path.append(Entry->pw_dir, Entry->pw_dir + strlen(Entry->pw_dir));
- llvm::sys::path::append(Path, Storage);
-}
-
-
-void expand_tilde(const Twine &path, SmallVectorImpl<char> &dest) {
- dest.clear();
- if (path.isTriviallyEmpty())
- return;
-
- path.toVector(dest);
- expandTildeExpr(dest);
-
- return;
-}
-
-static file_type typeForMode(mode_t Mode) {
- if (S_ISDIR(Mode))
- return file_type::directory_file;
- else if (S_ISREG(Mode))
- return file_type::regular_file;
- else if (S_ISBLK(Mode))
- return file_type::block_file;
- else if (S_ISCHR(Mode))
- return file_type::character_file;
- else if (S_ISFIFO(Mode))
- return file_type::fifo_file;
- else if (S_ISSOCK(Mode))
- return file_type::socket_file;
- else if (S_ISLNK(Mode))
- return file_type::symlink_file;
- return file_type::type_unknown;
-}
-
-static std::error_code fillStatus(int StatRet, const struct stat &Status,
- file_status &Result) {
- if (StatRet != 0) {
- std::error_code EC(errno, std::generic_category());
- if (EC == errc::no_such_file_or_directory)
- Result = file_status(file_type::file_not_found);
- else
- Result = file_status(file_type::status_error);
- return EC;
- }
-
- uint32_t atime_nsec, mtime_nsec;
-#if defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
- atime_nsec = Status.st_atimespec.tv_nsec;
- mtime_nsec = Status.st_mtimespec.tv_nsec;
-#elif defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
- atime_nsec = Status.st_atim.tv_nsec;
- mtime_nsec = Status.st_mtim.tv_nsec;
-#else
- atime_nsec = mtime_nsec = 0;
-#endif
-
- perms Perms = static_cast<perms>(Status.st_mode) & all_perms;
- Result = file_status(typeForMode(Status.st_mode), Perms, Status.st_dev,
- Status.st_nlink, Status.st_ino,
- Status.st_atime, atime_nsec, Status.st_mtime, mtime_nsec,
- Status.st_uid, Status.st_gid, Status.st_size);
-
- return std::error_code();
-}
-
-std::error_code status(const Twine &Path, file_status &Result, bool Follow) {
- SmallString<128> PathStorage;
- StringRef P = Path.toNullTerminatedStringRef(PathStorage);
-
- struct stat Status;
- int StatRet = (Follow ? ::stat : ::lstat)(P.begin(), &Status);
- return fillStatus(StatRet, Status, Result);
-}
-
-std::error_code status(int FD, file_status &Result) {
- struct stat Status;
- int StatRet = ::fstat(FD, &Status);
- return fillStatus(StatRet, Status, Result);
-}
-
-std::error_code setPermissions(const Twine &Path, perms Permissions) {
- SmallString<128> PathStorage;
- StringRef P = Path.toNullTerminatedStringRef(PathStorage);
-
- if (::chmod(P.begin(), Permissions))
- return std::error_code(errno, std::generic_category());
- return std::error_code();
-}
-
-std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
- TimePoint<> ModificationTime) {
-#if defined(HAVE_FUTIMENS)
- timespec Times[2];
- Times[0] = sys::toTimeSpec(AccessTime);
- Times[1] = sys::toTimeSpec(ModificationTime);
- if (::futimens(FD, Times))
- return std::error_code(errno, std::generic_category());
- return std::error_code();
-#elif defined(HAVE_FUTIMES)
- timeval Times[2];
- Times[0] = sys::toTimeVal(
- std::chrono::time_point_cast<std::chrono::microseconds>(AccessTime));
- Times[1] =
- sys::toTimeVal(std::chrono::time_point_cast<std::chrono::microseconds>(
- ModificationTime));
- if (::futimes(FD, Times))
- return std::error_code(errno, std::generic_category());
- return std::error_code();
-#else
-#warning Missing futimes() and futimens()
- return make_error_code(errc::function_not_supported);
-#endif
-}
-
-std::error_code mapped_file_region::init(int FD, uint64_t Offset,
- mapmode Mode) {
- assert(Size != 0);
-
- int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE;
- int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE);
-#if defined(__APPLE__)
- //----------------------------------------------------------------------
- // Newer versions of MacOSX have a flag that will allow us to read from
- // binaries whose code signature is invalid without crashing by using
- // the MAP_RESILIENT_CODESIGN flag. Also if a file from removable media
- // is mapped we can avoid crashing and return zeroes to any pages we try
- // to read if the media becomes unavailable by using the
- // MAP_RESILIENT_MEDIA flag. These flags are only usable when mapping
- // with PROT_READ, so take care not to specify them otherwise.
- //----------------------------------------------------------------------
- if (Mode == readonly) {
-#if defined(MAP_RESILIENT_CODESIGN)
- flags |= MAP_RESILIENT_CODESIGN;
-#endif
-#if defined(MAP_RESILIENT_MEDIA)
- flags |= MAP_RESILIENT_MEDIA;
-#endif
- }
-#endif // #if defined (__APPLE__)
-
- Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset);
- if (Mapping == MAP_FAILED)
- return std::error_code(errno, std::generic_category());
- return std::error_code();
-}
-
-mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length,
- uint64_t offset, std::error_code &ec)
- : Size(length), Mapping(), Mode(mode) {
- (void)Mode;
- ec = init(fd, offset, mode);
- if (ec)
- Mapping = nullptr;
-}
-
-mapped_file_region::~mapped_file_region() {
- if (Mapping)
- ::munmap(Mapping, Size);
-}
-
-size_t mapped_file_region::size() const {
- assert(Mapping && "Mapping failed but used anyway!");
- return Size;
-}
-
-char *mapped_file_region::data() const {
- assert(Mapping && "Mapping failed but used anyway!");
- return reinterpret_cast<char*>(Mapping);
-}
-
-const char *mapped_file_region::const_data() const {
- assert(Mapping && "Mapping failed but used anyway!");
- return reinterpret_cast<const char*>(Mapping);
-}
-
-int mapped_file_region::alignment() {
- return Process::getPageSize();
-}
-
-std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
- StringRef path,
- bool follow_symlinks) {
- SmallString<128> path_null(path);
- DIR *directory = ::opendir(path_null.c_str());
- if (!directory)
- return std::error_code(errno, std::generic_category());
-
- it.IterationHandle = reinterpret_cast<intptr_t>(directory);
- // Add something for replace_filename to replace.
- path::append(path_null, ".");
- it.CurrentEntry = directory_entry(path_null.str(), follow_symlinks);
- return directory_iterator_increment(it);
-}
-
-std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) {
- if (it.IterationHandle)
- ::closedir(reinterpret_cast<DIR *>(it.IterationHandle));
- it.IterationHandle = 0;
- it.CurrentEntry = directory_entry();
- return std::error_code();
-}
-
-static file_type direntType(dirent* Entry) {
- // Most platforms provide the file type in the dirent: Linux/BSD/Mac.
- // The DTTOIF macro lets us reuse our status -> type conversion.
-#if defined(_DIRENT_HAVE_D_TYPE) && defined(DTTOIF)
- return typeForMode(DTTOIF(Entry->d_type));
-#else
- // Other platforms such as Solaris require a stat() to get the type.
- return file_type::type_unknown;
-#endif
-}
-
-std::error_code detail::directory_iterator_increment(detail::DirIterState &It) {
- errno = 0;
- dirent *CurDir = ::readdir(reinterpret_cast<DIR *>(It.IterationHandle));
- if (CurDir == nullptr && errno != 0) {
- return std::error_code(errno, std::generic_category());
- } else if (CurDir != nullptr) {
- StringRef Name(CurDir->d_name);
- if ((Name.size() == 1 && Name[0] == '.') ||
- (Name.size() == 2 && Name[0] == '.' && Name[1] == '.'))
- return directory_iterator_increment(It);
- It.CurrentEntry.replace_filename(Name, direntType(CurDir));
- } else
- return directory_iterator_destruct(It);
-
- return std::error_code();
-}
-
-ErrorOr<basic_file_status> directory_entry::status() const {
- file_status s;
- if (auto EC = fs::status(Path, s, FollowSymlinks))
- return EC;
- return s;
-}
-
-#if !defined(F_GETPATH)
-static bool hasProcSelfFD() {
- // If we have a /proc filesystem mounted, we can quickly establish the
- // real name of the file with readlink
- static const bool Result = (::access("/proc/self/fd", R_OK) == 0);
- return Result;
-}
-#endif
-
-static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags,
- FileAccess Access) {
- int Result = 0;
- if (Access == FA_Read)
- Result |= O_RDONLY;
- else if (Access == FA_Write)
- Result |= O_WRONLY;
- else if (Access == (FA_Read | FA_Write))
- Result |= O_RDWR;
-
- // This is for compatibility with old code that assumed F_Append implied
- // would open an existing file. See Windows/Path.inc for a longer comment.
- if (Flags & F_Append)
- Disp = CD_OpenAlways;
-
- if (Disp == CD_CreateNew) {
- Result |= O_CREAT; // Create if it doesn't exist.
- Result |= O_EXCL; // Fail if it does.
- } else if (Disp == CD_CreateAlways) {
- Result |= O_CREAT; // Create if it doesn't exist.
- Result |= O_TRUNC; // Truncate if it does.
- } else if (Disp == CD_OpenAlways) {
- Result |= O_CREAT; // Create if it doesn't exist.
- } else if (Disp == CD_OpenExisting) {
- // Nothing special, just don't add O_CREAT and we get these semantics.
- }
-
- if (Flags & F_Append)
- Result |= O_APPEND;
-
-#ifdef O_CLOEXEC
- if (!(Flags & OF_ChildInherit))
- Result |= O_CLOEXEC;
-#endif
-
- return Result;
-}
-
-std::error_code openFile(const Twine &Name, int &ResultFD,
- CreationDisposition Disp, FileAccess Access,
- OpenFlags Flags, unsigned Mode) {
- int OpenFlags = nativeOpenFlags(Disp, Flags, Access);
-
- SmallString<128> Storage;
- StringRef P = Name.toNullTerminatedStringRef(Storage);
- // Call ::open in a lambda to avoid overload resolution in RetryAfterSignal
- // when open is overloaded, such as in Bionic.
- auto Open = [&]() { return ::open(P.begin(), OpenFlags, Mode); };
- if ((ResultFD = sys::RetryAfterSignal(-1, Open)) < 0)
- return std::error_code(errno, std::generic_category());
-#ifndef O_CLOEXEC
- if (!(Flags & OF_ChildInherit)) {
- int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC);
- (void)r;
- assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed");
- }
-#endif
- return std::error_code();
-}
-
-Expected<int> openNativeFile(const Twine &Name, CreationDisposition Disp,
- FileAccess Access, OpenFlags Flags,
- unsigned Mode) {
-
- int FD;
- std::error_code EC = openFile(Name, FD, Disp, Access, Flags, Mode);
- if (EC)
- return errorCodeToError(EC);
- return FD;
-}
-
-std::error_code openFileForRead(const Twine &Name, int &ResultFD,
- OpenFlags Flags,
- SmallVectorImpl<char> *RealPath) {
- std::error_code EC =
- openFile(Name, ResultFD, CD_OpenExisting, FA_Read, Flags, 0666);
- if (EC)
- return EC;
-
- // Attempt to get the real name of the file, if the user asked
- if(!RealPath)
- return std::error_code();
- RealPath->clear();
-#if defined(F_GETPATH)
- // When F_GETPATH is availble, it is the quickest way to get
- // the real path name.
- char Buffer[MAXPATHLEN];
- if (::fcntl(ResultFD, F_GETPATH, Buffer) != -1)
- RealPath->append(Buffer, Buffer + strlen(Buffer));
-#else
- char Buffer[PATH_MAX];
- if (hasProcSelfFD()) {
- char ProcPath[64];
- snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", ResultFD);
- ssize_t CharCount = ::readlink(ProcPath, Buffer, sizeof(Buffer));
- if (CharCount > 0)
- RealPath->append(Buffer, Buffer + CharCount);
- } else {
- SmallString<128> Storage;
- StringRef P = Name.toNullTerminatedStringRef(Storage);
-
- // Use ::realpath to get the real path name
- if (::realpath(P.begin(), Buffer) != nullptr)
- RealPath->append(Buffer, Buffer + strlen(Buffer));
- }
-#endif
- return std::error_code();
-}
-
-Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags,
- SmallVectorImpl<char> *RealPath) {
- file_t ResultFD;
- std::error_code EC = openFileForRead(Name, ResultFD, Flags, RealPath);
- if (EC)
- return errorCodeToError(EC);
- return ResultFD;
-}
-
-void closeFile(file_t &F) {
- ::close(F);
- F = kInvalidFile;
-}
-
-template <typename T>
-static std::error_code remove_directories_impl(const T &Entry,
- bool IgnoreErrors) {
- std::error_code EC;
- directory_iterator Begin(Entry, EC, false);
- directory_iterator End;
- while (Begin != End) {
- auto &Item = *Begin;
- ErrorOr<basic_file_status> st = Item.status();
- if (!st && !IgnoreErrors)
- return st.getError();
-
- if (is_directory(*st)) {
- EC = remove_directories_impl(Item, IgnoreErrors);
- if (EC && !IgnoreErrors)
- return EC;
- }
-
- EC = fs::remove(Item.path(), true);
- if (EC && !IgnoreErrors)
- return EC;
-
- Begin.increment(EC);
- if (EC && !IgnoreErrors)
- return EC;
- }
- return std::error_code();
-}
-
-std::error_code remove_directories(const Twine &path, bool IgnoreErrors) {
- auto EC = remove_directories_impl(path, IgnoreErrors);
- if (EC && !IgnoreErrors)
- return EC;
- EC = fs::remove(path, true);
- if (EC && !IgnoreErrors)
- return EC;
- return std::error_code();
-}
-
-std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest,
- bool expand_tilde) {
- dest.clear();
- if (path.isTriviallyEmpty())
- return std::error_code();
-
- if (expand_tilde) {
- SmallString<128> Storage;
- path.toVector(Storage);
- expandTildeExpr(Storage);
- return real_path(Storage, dest, false);
- }
-
- SmallString<128> Storage;
- StringRef P = path.toNullTerminatedStringRef(Storage);
- char Buffer[PATH_MAX];
- if (::realpath(P.begin(), Buffer) == nullptr)
- return std::error_code(errno, std::generic_category());
- dest.append(Buffer, Buffer + strlen(Buffer));
- return std::error_code();
-}
-
-} // end namespace fs
-
-namespace path {
-
-bool home_directory(SmallVectorImpl<char> &result) {
- char *RequestedDir = getenv("HOME");
- if (!RequestedDir) {
- struct passwd *pw = getpwuid(getuid());
- if (pw && pw->pw_dir)
- RequestedDir = pw->pw_dir;
- }
- if (!RequestedDir)
- return false;
-
- result.clear();
- result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
- return true;
-}
-
-static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) {
- #if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR)
- // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR.
- // macros defined in <unistd.h> on darwin >= 9
- int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR
- : _CS_DARWIN_USER_CACHE_DIR;
- size_t ConfLen = confstr(ConfName, nullptr, 0);
- if (ConfLen > 0) {
- do {
- Result.resize(ConfLen);
- ConfLen = confstr(ConfName, Result.data(), Result.size());
- } while (ConfLen > 0 && ConfLen != Result.size());
-
- if (ConfLen > 0) {
- assert(Result.back() == 0);
- Result.pop_back();
- return true;
- }
-
- Result.clear();
- }
- #endif
- return false;
-}
-
-static const char *getEnvTempDir() {
- // Check whether the temporary directory is specified by an environment
- // variable.
- const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
- for (const char *Env : EnvironmentVariables) {
- if (const char *Dir = std::getenv(Env))
- return Dir;
- }
-
- return nullptr;
-}
-
-static const char *getDefaultTempDir(bool ErasedOnReboot) {
-#ifdef P_tmpdir
- if ((bool)P_tmpdir)
- return P_tmpdir;
-#endif
-
- if (ErasedOnReboot)
- return "/tmp";
- return "/var/tmp";
-}
-
-void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) {
- Result.clear();
-
- if (ErasedOnReboot) {
- // There is no env variable for the cache directory.
- if (const char *RequestedDir = getEnvTempDir()) {
- Result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
- return;
- }
- }
-
- if (getDarwinConfDir(ErasedOnReboot, Result))
- return;
-
- const char *RequestedDir = getDefaultTempDir(ErasedOnReboot);
- Result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
-}
-
-} // end namespace path
-
-} // end namespace sys
-} // end namespace llvm
diff --git a/gnu/llvm/lib/Support/Unix/Process.inc b/gnu/llvm/lib/Support/Unix/Process.inc
deleted file mode 100644
index 1d8a6c8a8db..00000000000
--- a/gnu/llvm/lib/Support/Unix/Process.inc
+++ /dev/null
@@ -1,464 +0,0 @@
-//===- Unix/Process.cpp - Unix Process Implementation --------- -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides the generic Unix implementation of the Process class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Unix.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/MutexGuard.h"
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-// DragonFlyBSD, and OpenBSD have deprecated <malloc.h> for
-// <stdlib.h> instead. Unix.h includes this for us already.
-#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
- !defined(__OpenBSD__)
-#include <malloc.h>
-#endif
-#if defined(HAVE_MALLCTL)
-#include <malloc_np.h>
-#endif
-#ifdef HAVE_MALLOC_MALLOC_H
-#include <malloc/malloc.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-#ifdef HAVE_TERMIOS_H
-# include <termios.h>
-#endif
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-using namespace llvm;
-using namespace sys;
-
-static std::pair<std::chrono::microseconds, std::chrono::microseconds> getRUsageTimes() {
-#if defined(HAVE_GETRUSAGE)
- struct rusage RU;
- ::getrusage(RUSAGE_SELF, &RU);
- return { toDuration(RU.ru_utime), toDuration(RU.ru_stime) };
-#else
-#warning Cannot get usage times on this platform
- return { std::chrono::microseconds::zero(), std::chrono::microseconds::zero() };
-#endif
-}
-
-// On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
-// offset in mmap(3) should be aligned to the AllocationGranularity.
-unsigned Process::getPageSize() {
-#if defined(HAVE_GETPAGESIZE)
- static const int page_size = ::getpagesize();
-#elif defined(HAVE_SYSCONF)
- static long page_size = ::sysconf(_SC_PAGE_SIZE);
-#else
-#error Cannot get the page size on this machine
-#endif
- return static_cast<unsigned>(page_size);
-}
-
-size_t Process::GetMallocUsage() {
-#if defined(HAVE_MALLINFO)
- struct mallinfo mi;
- mi = ::mallinfo();
- return mi.uordblks;
-#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
- malloc_statistics_t Stats;
- malloc_zone_statistics(malloc_default_zone(), &Stats);
- return Stats.size_in_use; // darwin
-#elif defined(HAVE_MALLCTL)
- size_t alloc, sz;
- sz = sizeof(size_t);
- if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0)
- return alloc;
- return 0;
-#elif defined(HAVE_SBRK)
- // Note this is only an approximation and more closely resembles
- // the value returned by mallinfo in the arena field.
- static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
- char *EndOfMemory = (char*)sbrk(0);
- if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
- return EndOfMemory - StartOfMemory;
- return 0;
-#else
-#warning Cannot get malloc info on this platform
- return 0;
-#endif
-}
-
-void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time,
- std::chrono::nanoseconds &sys_time) {
- elapsed = std::chrono::system_clock::now();
- std::tie(user_time, sys_time) = getRUsageTimes();
-}
-
-#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
-#include <mach/mach.h>
-#endif
-
-// Some LLVM programs such as bugpoint produce core files as a normal part of
-// their operation. To prevent the disk from filling up, this function
-// does what's necessary to prevent their generation.
-void Process::PreventCoreFiles() {
-#if HAVE_SETRLIMIT
- struct rlimit rlim;
- rlim.rlim_cur = rlim.rlim_max = 0;
- setrlimit(RLIMIT_CORE, &rlim);
-#endif
-
-#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
- // Disable crash reporting on Mac OS X 10.0-10.4
-
- // get information about the original set of exception ports for the task
- mach_msg_type_number_t Count = 0;
- exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
- exception_port_t OriginalPorts[EXC_TYPES_COUNT];
- exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
- thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
- kern_return_t err =
- task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
- &Count, OriginalPorts, OriginalBehaviors,
- OriginalFlavors);
- if (err == KERN_SUCCESS) {
- // replace each with MACH_PORT_NULL.
- for (unsigned i = 0; i != Count; ++i)
- task_set_exception_ports(mach_task_self(), OriginalMasks[i],
- MACH_PORT_NULL, OriginalBehaviors[i],
- OriginalFlavors[i]);
- }
-
- // Disable crash reporting on Mac OS X 10.5
- signal(SIGABRT, _exit);
- signal(SIGILL, _exit);
- signal(SIGFPE, _exit);
- signal(SIGSEGV, _exit);
- signal(SIGBUS, _exit);
-#endif
-
- coreFilesPrevented = true;
-}
-
-Optional<std::string> Process::GetEnv(StringRef Name) {
- std::string NameStr = Name.str();
- const char *Val = ::getenv(NameStr.c_str());
- if (!Val)
- return None;
- return std::string(Val);
-}
-
-namespace {
-class FDCloser {
-public:
- FDCloser(int &FD) : FD(FD), KeepOpen(false) {}
- void keepOpen() { KeepOpen = true; }
- ~FDCloser() {
- if (!KeepOpen && FD >= 0)
- ::close(FD);
- }
-
-private:
- FDCloser(const FDCloser &) = delete;
- void operator=(const FDCloser &) = delete;
-
- int &FD;
- bool KeepOpen;
-};
-}
-
-std::error_code Process::FixupStandardFileDescriptors() {
- int NullFD = -1;
- FDCloser FDC(NullFD);
- const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
- for (int StandardFD : StandardFDs) {
- struct stat st;
- errno = 0;
- if (RetryAfterSignal(-1, ::fstat, StandardFD, &st) < 0) {
- assert(errno && "expected errno to be set if fstat failed!");
- // fstat should return EBADF if the file descriptor is closed.
- if (errno != EBADF)
- return std::error_code(errno, std::generic_category());
- }
- // if fstat succeeds, move on to the next FD.
- if (!errno)
- continue;
- assert(errno == EBADF && "expected errno to have EBADF at this point!");
-
- if (NullFD < 0) {
- // Call ::open in a lambda to avoid overload resolution in
- // RetryAfterSignal when open is overloaded, such as in Bionic.
- auto Open = [&]() { return ::open("/dev/null", O_RDWR); };
- if ((NullFD = RetryAfterSignal(-1, Open)) < 0)
- return std::error_code(errno, std::generic_category());
- }
-
- if (NullFD == StandardFD)
- FDC.keepOpen();
- else if (dup2(NullFD, StandardFD) < 0)
- return std::error_code(errno, std::generic_category());
- }
- return std::error_code();
-}
-
-std::error_code Process::SafelyCloseFileDescriptor(int FD) {
- // Create a signal set filled with *all* signals.
- sigset_t FullSet;
- if (sigfillset(&FullSet) < 0)
- return std::error_code(errno, std::generic_category());
- // Atomically swap our current signal mask with a full mask.
- sigset_t SavedSet;
-#if LLVM_ENABLE_THREADS
- if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet))
- return std::error_code(EC, std::generic_category());
-#else
- if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0)
- return std::error_code(errno, std::generic_category());
-#endif
- // Attempt to close the file descriptor.
- // We need to save the error, if one occurs, because our subsequent call to
- // pthread_sigmask might tamper with errno.
- int ErrnoFromClose = 0;
- if (::close(FD) < 0)
- ErrnoFromClose = errno;
- // Restore the signal mask back to what we saved earlier.
- int EC = 0;
-#if LLVM_ENABLE_THREADS
- EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr);
-#else
- if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0)
- EC = errno;
-#endif
- // The error code from close takes precedence over the one from
- // pthread_sigmask.
- if (ErrnoFromClose)
- return std::error_code(ErrnoFromClose, std::generic_category());
- return std::error_code(EC, std::generic_category());
-}
-
-bool Process::StandardInIsUserInput() {
- return FileDescriptorIsDisplayed(STDIN_FILENO);
-}
-
-bool Process::StandardOutIsDisplayed() {
- return FileDescriptorIsDisplayed(STDOUT_FILENO);
-}
-
-bool Process::StandardErrIsDisplayed() {
- return FileDescriptorIsDisplayed(STDERR_FILENO);
-}
-
-bool Process::FileDescriptorIsDisplayed(int fd) {
-#if HAVE_ISATTY
- return isatty(fd);
-#else
- // If we don't have isatty, just return false.
- return false;
-#endif
-}
-
-static unsigned getColumns(int FileID) {
- // If COLUMNS is defined in the environment, wrap to that many columns.
- if (const char *ColumnsStr = std::getenv("COLUMNS")) {
- int Columns = std::atoi(ColumnsStr);
- if (Columns > 0)
- return Columns;
- }
-
- unsigned Columns = 0;
-
-#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
- // Try to determine the width of the terminal.
- struct winsize ws;
- if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
- Columns = ws.ws_col;
-#endif
-
- return Columns;
-}
-
-unsigned Process::StandardOutColumns() {
- if (!StandardOutIsDisplayed())
- return 0;
-
- return getColumns(1);
-}
-
-unsigned Process::StandardErrColumns() {
- if (!StandardErrIsDisplayed())
- return 0;
-
- return getColumns(2);
-}
-
-#ifdef HAVE_TERMINFO
-// We manually declare these extern functions because finding the correct
-// headers from various terminfo, curses, or other sources is harder than
-// writing their specs down.
-extern "C" int setupterm(char *term, int filedes, int *errret);
-extern "C" struct term *set_curterm(struct term *termp);
-extern "C" int del_curterm(struct term *termp);
-extern "C" int tigetnum(char *capname);
-#endif
-
-#ifdef HAVE_TERMINFO
-static ManagedStatic<sys::Mutex> TermColorMutex;
-#endif
-
-static bool terminalHasColors(int fd) {
-#if defined(__OpenBSD__)
- return false;
-#endif
-
-#ifdef HAVE_TERMINFO
- // First, acquire a global lock because these C routines are thread hostile.
- MutexGuard G(*TermColorMutex);
-
- int errret = 0;
- if (setupterm(nullptr, fd, &errret) != 0)
- // Regardless of why, if we can't get terminfo, we shouldn't try to print
- // colors.
- return false;
-
- // Test whether the terminal as set up supports color output. How to do this
- // isn't entirely obvious. We can use the curses routine 'has_colors' but it
- // would be nice to avoid a dependency on curses proper when we can make do
- // with a minimal terminfo parsing library. Also, we don't really care whether
- // the terminal supports the curses-specific color changing routines, merely
- // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
- // strategy here is just to query the baseline colors capability and if it
- // supports colors at all to assume it will translate the escape codes into
- // whatever range of colors it does support. We can add more detailed tests
- // here if users report them as necessary.
- //
- // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
- // the terminfo says that no colors are supported.
- bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
-
- // Now extract the structure allocated by setupterm and free its memory
- // through a really silly dance.
- struct term *termp = set_curterm(nullptr);
- (void)del_curterm(termp); // Drop any errors here.
-
- // Return true if we found a color capabilities for the current terminal.
- if (HasColors)
- return true;
-#else
- // When the terminfo database is not available, check if the current terminal
- // is one of terminals that are known to support ANSI color escape codes.
- if (const char *TermStr = std::getenv("TERM")) {
- return StringSwitch<bool>(TermStr)
- .Case("ansi", true)
- .Case("cygwin", true)
- .Case("linux", true)
- .StartsWith("screen", true)
- .StartsWith("xterm", true)
- .StartsWith("vt100", true)
- .StartsWith("rxvt", true)
- .EndsWith("color", true)
- .Default(false);
- }
-#endif
-
- // Otherwise, be conservative.
- return false;
-}
-
-bool Process::FileDescriptorHasColors(int fd) {
- // A file descriptor has colors if it is displayed and the terminal has
- // colors.
- return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
-}
-
-bool Process::StandardOutHasColors() {
- return FileDescriptorHasColors(STDOUT_FILENO);
-}
-
-bool Process::StandardErrHasColors() {
- return FileDescriptorHasColors(STDERR_FILENO);
-}
-
-void Process::UseANSIEscapeCodes(bool /*enable*/) {
- // No effect.
-}
-
-bool Process::ColorNeedsFlush() {
- // No, we use ANSI escape sequences.
- return false;
-}
-
-const char *Process::OutputColor(char code, bool bold, bool bg) {
- return colorcodes[bg?1:0][bold?1:0][code&7];
-}
-
-const char *Process::OutputBold(bool bg) {
- return "\033[1m";
-}
-
-const char *Process::OutputReverse() {
- return "\033[7m";
-}
-
-const char *Process::ResetColor() {
- return "\033[0m";
-}
-
-#if !HAVE_DECL_ARC4RANDOM
-static unsigned GetRandomNumberSeed() {
- // Attempt to get the initial seed from /dev/urandom, if possible.
- int urandomFD = open("/dev/urandom", O_RDONLY);
-
- if (urandomFD != -1) {
- unsigned seed;
- // Don't use a buffered read to avoid reading more data
- // from /dev/urandom than we need.
- int count = read(urandomFD, (void *)&seed, sizeof(seed));
-
- close(urandomFD);
-
- // Return the seed if the read was successful.
- if (count == sizeof(seed))
- return seed;
- }
-
- // Otherwise, swizzle the current time and the process ID to form a reasonable
- // seed.
- const auto Now = std::chrono::high_resolution_clock::now();
- return hash_combine(Now.time_since_epoch().count(), ::getpid());
-}
-#endif
-
-unsigned llvm::sys::Process::GetRandomNumber() {
-#if HAVE_DECL_ARC4RANDOM
- return arc4random();
-#else
- static int x = (static_cast<void>(::srand(GetRandomNumberSeed())), 0);
- (void)x;
- return ::rand();
-#endif
-}
diff --git a/gnu/llvm/lib/Support/Unix/Program.inc b/gnu/llvm/lib/Support/Unix/Program.inc
deleted file mode 100644
index d0abc3763e8..00000000000
--- a/gnu/llvm/lib/Support/Unix/Program.inc
+++ /dev/null
@@ -1,497 +0,0 @@
-//===- llvm/Support/Unix/Program.cpp -----------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Unix specific portion of the Program class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-#include "Unix.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/StringSaver.h"
-#include "llvm/Support/raw_ostream.h"
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-#if HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_POSIX_SPAWN
-#include <spawn.h>
-
-#if defined(__APPLE__)
-#include <TargetConditionals.h>
-#endif
-
-#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
-#define USE_NSGETENVIRON 1
-#else
-#define USE_NSGETENVIRON 0
-#endif
-
-#if !USE_NSGETENVIRON
- extern char **environ;
-#else
-#include <crt_externs.h> // _NSGetEnviron
-#endif
-#endif
-
-namespace llvm {
-
-using namespace sys;
-
-ProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {}
-
-ErrorOr<std::string> sys::findProgramByName(StringRef Name,
- ArrayRef<StringRef> Paths) {
- assert(!Name.empty() && "Must have a name!");
- // Use the given path verbatim if it contains any slashes; this matches
- // the behavior of sh(1) and friends.
- if (Name.find('/') != StringRef::npos)
- return std::string(Name);
-
- SmallVector<StringRef, 16> EnvironmentPaths;
- if (Paths.empty())
- if (const char *PathEnv = std::getenv("PATH")) {
- SplitString(PathEnv, EnvironmentPaths, ":");
- Paths = EnvironmentPaths;
- }
-
- for (auto Path : Paths) {
- if (Path.empty())
- continue;
-
- // Check to see if this first directory contains the executable...
- SmallString<128> FilePath(Path);
- sys::path::append(FilePath, Name);
- if (sys::fs::can_execute(FilePath.c_str()))
- return std::string(FilePath.str()); // Found the executable!
- }
- return errc::no_such_file_or_directory;
-}
-
-static bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) {
- if (!Path) // Noop
- return false;
- std::string File;
- if (Path->empty())
- // Redirect empty paths to /dev/null
- File = "/dev/null";
- else
- File = *Path;
-
- // Open the file
- int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666);
- if (InFD == -1) {
- MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for "
- + (FD == 0 ? "input" : "output"));
- return true;
- }
-
- // Install it as the requested FD
- if (dup2(InFD, FD) == -1) {
- MakeErrMsg(ErrMsg, "Cannot dup2");
- close(InFD);
- return true;
- }
- close(InFD); // Close the original FD
- return false;
-}
-
-#ifdef HAVE_POSIX_SPAWN
-static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg,
- posix_spawn_file_actions_t *FileActions) {
- if (!Path) // Noop
- return false;
- const char *File;
- if (Path->empty())
- // Redirect empty paths to /dev/null
- File = "/dev/null";
- else
- File = Path->c_str();
-
- if (int Err = posix_spawn_file_actions_addopen(
- FileActions, FD, File,
- FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666))
- return MakeErrMsg(ErrMsg, "Cannot dup2", Err);
- return false;
-}
-#endif
-
-static void TimeOutHandler(int Sig) {
-}
-
-static void SetMemoryLimits(unsigned size) {
-#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT
- struct rlimit r;
- __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
-
- // Heap size
- getrlimit (RLIMIT_DATA, &r);
- r.rlim_cur = limit;
- setrlimit (RLIMIT_DATA, &r);
-#ifdef RLIMIT_RSS
- // Resident set size.
- getrlimit (RLIMIT_RSS, &r);
- r.rlim_cur = limit;
- setrlimit (RLIMIT_RSS, &r);
-#endif
-#endif
-}
-
-}
-
-static std::vector<const char *>
-toNullTerminatedCStringArray(ArrayRef<StringRef> Strings, StringSaver &Saver) {
- std::vector<const char *> Result;
- for (StringRef S : Strings)
- Result.push_back(Saver.save(S).data());
- Result.push_back(nullptr);
- return Result;
-}
-
-static bool Execute(ProcessInfo &PI, StringRef Program,
- ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
- ArrayRef<Optional<StringRef>> Redirects,
- unsigned MemoryLimit, std::string *ErrMsg) {
- if (!llvm::sys::fs::exists(Program)) {
- if (ErrMsg)
- *ErrMsg = std::string("Executable \"") + Program.str() +
- std::string("\" doesn't exist!");
- return false;
- }
-
- BumpPtrAllocator Allocator;
- StringSaver Saver(Allocator);
- std::vector<const char *> ArgVector, EnvVector;
- const char **Argv = nullptr;
- const char **Envp = nullptr;
- ArgVector = toNullTerminatedCStringArray(Args, Saver);
- Argv = ArgVector.data();
- if (Env) {
- EnvVector = toNullTerminatedCStringArray(*Env, Saver);
- Envp = EnvVector.data();
- }
-
- // If this OS has posix_spawn and there is no memory limit being implied, use
- // posix_spawn. It is more efficient than fork/exec.
-#ifdef HAVE_POSIX_SPAWN
- if (MemoryLimit == 0) {
- posix_spawn_file_actions_t FileActionsStore;
- posix_spawn_file_actions_t *FileActions = nullptr;
-
- // If we call posix_spawn_file_actions_addopen we have to make sure the
- // c strings we pass to it stay alive until the call to posix_spawn,
- // so we copy any StringRefs into this variable.
- std::string RedirectsStorage[3];
-
- if (!Redirects.empty()) {
- assert(Redirects.size() == 3);
- std::string *RedirectsStr[3] = {nullptr, nullptr, nullptr};
- for (int I = 0; I < 3; ++I) {
- if (Redirects[I]) {
- RedirectsStorage[I] = *Redirects[I];
- RedirectsStr[I] = &RedirectsStorage[I];
- }
- }
-
- FileActions = &FileActionsStore;
- posix_spawn_file_actions_init(FileActions);
-
- // Redirect stdin/stdout.
- if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) ||
- RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions))
- return false;
- if (!Redirects[1] || !Redirects[2] || *Redirects[1] != *Redirects[2]) {
- // Just redirect stderr
- if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions))
- return false;
- } else {
- // If stdout and stderr should go to the same place, redirect stderr
- // to the FD already open for stdout.
- if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2))
- return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err);
- }
- }
-
- if (!Envp)
-#if !USE_NSGETENVIRON
- Envp = const_cast<const char **>(environ);
-#else
- // environ is missing in dylibs.
- Envp = const_cast<const char **>(*_NSGetEnviron());
-#endif
-
- // Explicitly initialized to prevent what appears to be a valgrind false
- // positive.
- pid_t PID = 0;
- int Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
- /*attrp*/ nullptr, const_cast<char **>(Argv),
- const_cast<char **>(Envp));
-
- if (FileActions)
- posix_spawn_file_actions_destroy(FileActions);
-
- if (Err)
- return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err);
-
- PI.Pid = PID;
- PI.Process = PID;
-
- return true;
- }
-#endif
-
- // Create a child process.
- int child = fork();
- switch (child) {
- // An error occurred: Return to the caller.
- case -1:
- MakeErrMsg(ErrMsg, "Couldn't fork");
- return false;
-
- // Child process: Execute the program.
- case 0: {
- // Redirect file descriptors...
- if (!Redirects.empty()) {
- // Redirect stdin
- if (RedirectIO(Redirects[0], 0, ErrMsg)) { return false; }
- // Redirect stdout
- if (RedirectIO(Redirects[1], 1, ErrMsg)) { return false; }
- if (Redirects[1] && Redirects[2] && *Redirects[1] == *Redirects[2]) {
- // If stdout and stderr should go to the same place, redirect stderr
- // to the FD already open for stdout.
- if (-1 == dup2(1,2)) {
- MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
- return false;
- }
- } else {
- // Just redirect stderr
- if (RedirectIO(Redirects[2], 2, ErrMsg)) { return false; }
- }
- }
-
- // Set memory limits
- if (MemoryLimit!=0) {
- SetMemoryLimits(MemoryLimit);
- }
-
- // Execute!
- std::string PathStr = Program;
- if (Envp != nullptr)
- execve(PathStr.c_str(), const_cast<char **>(Argv),
- const_cast<char **>(Envp));
- else
- execv(PathStr.c_str(), const_cast<char **>(Argv));
- // If the execve() failed, we should exit. Follow Unix protocol and
- // return 127 if the executable was not found, and 126 otherwise.
- // Use _exit rather than exit so that atexit functions and static
- // object destructors cloned from the parent process aren't
- // redundantly run, and so that any data buffered in stdio buffers
- // cloned from the parent aren't redundantly written out.
- _exit(errno == ENOENT ? 127 : 126);
- }
-
- // Parent process: Break out of the switch to do our processing.
- default:
- break;
- }
-
- PI.Pid = child;
- PI.Process = child;
-
- return true;
-}
-
-namespace llvm {
-
-ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
- bool WaitUntilTerminates, std::string *ErrMsg) {
- struct sigaction Act, Old;
- assert(PI.Pid && "invalid pid to wait on, process not started?");
-
- int WaitPidOptions = 0;
- pid_t ChildPid = PI.Pid;
- if (WaitUntilTerminates) {
- SecondsToWait = 0;
- } else if (SecondsToWait) {
- // Install a timeout handler. The handler itself does nothing, but the
- // simple fact of having a handler at all causes the wait below to return
- // with EINTR, unlike if we used SIG_IGN.
- memset(&Act, 0, sizeof(Act));
- Act.sa_handler = TimeOutHandler;
- sigemptyset(&Act.sa_mask);
- sigaction(SIGALRM, &Act, &Old);
- alarm(SecondsToWait);
- } else if (SecondsToWait == 0)
- WaitPidOptions = WNOHANG;
-
- // Parent process: Wait for the child process to terminate.
- int status;
- ProcessInfo WaitResult;
-
- do {
- WaitResult.Pid = waitpid(ChildPid, &status, WaitPidOptions);
- } while (WaitUntilTerminates && WaitResult.Pid == -1 && errno == EINTR);
-
- if (WaitResult.Pid != PI.Pid) {
- if (WaitResult.Pid == 0) {
- // Non-blocking wait.
- return WaitResult;
- } else {
- if (SecondsToWait && errno == EINTR) {
- // Kill the child.
- kill(PI.Pid, SIGKILL);
-
- // Turn off the alarm and restore the signal handler
- alarm(0);
- sigaction(SIGALRM, &Old, nullptr);
-
- // Wait for child to die
- if (wait(&status) != ChildPid)
- MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
- else
- MakeErrMsg(ErrMsg, "Child timed out", 0);
-
- WaitResult.ReturnCode = -2; // Timeout detected
- return WaitResult;
- } else if (errno != EINTR) {
- MakeErrMsg(ErrMsg, "Error waiting for child process");
- WaitResult.ReturnCode = -1;
- return WaitResult;
- }
- }
- }
-
- // We exited normally without timeout, so turn off the timer.
- if (SecondsToWait && !WaitUntilTerminates) {
- alarm(0);
- sigaction(SIGALRM, &Old, nullptr);
- }
-
- // Return the proper exit status. Detect error conditions
- // so we can return -1 for them and set ErrMsg informatively.
- int result = 0;
- if (WIFEXITED(status)) {
- result = WEXITSTATUS(status);
- WaitResult.ReturnCode = result;
-
- if (result == 127) {
- if (ErrMsg)
- *ErrMsg = llvm::sys::StrError(ENOENT);
- WaitResult.ReturnCode = -1;
- return WaitResult;
- }
- if (result == 126) {
- if (ErrMsg)
- *ErrMsg = "Program could not be executed";
- WaitResult.ReturnCode = -1;
- return WaitResult;
- }
- } else if (WIFSIGNALED(status)) {
- if (ErrMsg) {
- *ErrMsg = strsignal(WTERMSIG(status));
-#ifdef WCOREDUMP
- if (WCOREDUMP(status))
- *ErrMsg += " (core dumped)";
-#endif
- }
- // Return a special value to indicate that the process received an unhandled
- // signal during execution as opposed to failing to execute.
- WaitResult.ReturnCode = -2;
- }
- return WaitResult;
-}
-
-std::error_code sys::ChangeStdinToBinary() {
- // Do nothing, as Unix doesn't differentiate between text and binary.
- return std::error_code();
-}
-
-std::error_code sys::ChangeStdoutToBinary() {
- // Do nothing, as Unix doesn't differentiate between text and binary.
- return std::error_code();
-}
-
-std::error_code
-llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
- WindowsEncodingMethod Encoding /*unused*/) {
- std::error_code EC;
- llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text);
-
- if (EC)
- return EC;
-
- OS << Contents;
-
- if (OS.has_error())
- return make_error_code(errc::io_error);
-
- return EC;
-}
-
-bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program,
- ArrayRef<StringRef> Args) {
- static long ArgMax = sysconf(_SC_ARG_MAX);
- // POSIX requires that _POSIX_ARG_MAX is 4096, which is the lowest possible
- // value for ARG_MAX on a POSIX compliant system.
- static long ArgMin = _POSIX_ARG_MAX;
-
- // This the same baseline used by xargs.
- long EffectiveArgMax = 128 * 1024;
-
- if (EffectiveArgMax > ArgMax)
- EffectiveArgMax = ArgMax;
- else if (EffectiveArgMax < ArgMin)
- EffectiveArgMax = ArgMin;
-
- // System says no practical limit.
- if (ArgMax == -1)
- return true;
-
- // Conservatively account for space required by environment variables.
- long HalfArgMax = EffectiveArgMax / 2;
-
- size_t ArgLength = Program.size() + 1;
- for (StringRef Arg : Args) {
- // Ensure that we do not exceed the MAX_ARG_STRLEN constant on Linux, which
- // does not have a constant unlike what the man pages would have you
- // believe. Since this limit is pretty high, perform the check
- // unconditionally rather than trying to be aggressive and limiting it to
- // Linux only.
- if (Arg.size() >= (32 * 4096))
- return false;
-
- ArgLength += Arg.size() + 1;
- if (ArgLength > size_t(HalfArgMax)) {
- return false;
- }
- }
-
- return true;
-}
-}
diff --git a/gnu/llvm/lib/Support/Unix/README.txt b/gnu/llvm/lib/Support/Unix/README.txt
deleted file mode 100644
index 3d547c2990d..00000000000
--- a/gnu/llvm/lib/Support/Unix/README.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-llvm/lib/Support/Unix README
-===========================
-
-This directory provides implementations of the lib/System classes that
-are common to two or more variants of UNIX. For example, the directory
-structure underneath this directory could look like this:
-
-Unix - only code that is truly generic to all UNIX platforms
- Posix - code that is specific to Posix variants of UNIX
- SUS - code that is specific to the Single Unix Specification
- SysV - code that is specific to System V variants of UNIX
-
-As a rule, only those directories actually needing to be created should be
-created. Also, further subdirectories could be created to reflect versions of
-the various standards. For example, under SUS there could be v1, v2, and v3
-subdirectories to reflect the three major versions of SUS.
diff --git a/gnu/llvm/lib/Support/Unix/RWMutex.inc b/gnu/llvm/lib/Support/Unix/RWMutex.inc
deleted file mode 100644
index 85a104334a2..00000000000
--- a/gnu/llvm/lib/Support/Unix/RWMutex.inc
+++ /dev/null
@@ -1,51 +0,0 @@
-//= llvm/Support/Unix/RWMutex.inc - Unix Reader/Writer Mutual Exclusion Lock =//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Unix specific (non-pthread) RWMutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Mutex.h"
-
-namespace llvm {
-
-using namespace sys;
-
-// This naive implementation treats readers the same as writers. This
-// will therefore deadlock if a thread tries to acquire a read lock
-// multiple times.
-
-RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
-
-RWMutexImpl::~RWMutexImpl() {
- delete static_cast<MutexImpl *>(data_);
-}
-
-bool RWMutexImpl::reader_acquire() {
- return static_cast<MutexImpl *>(data_)->acquire();
-}
-
-bool RWMutexImpl::reader_release() {
- return static_cast<MutexImpl *>(data_)->release();
-}
-
-bool RWMutexImpl::writer_acquire() {
- return static_cast<MutexImpl *>(data_)->acquire();
-}
-
-bool RWMutexImpl::writer_release() {
- return static_cast<MutexImpl *>(data_)->release();
-}
-
-}
diff --git a/gnu/llvm/lib/Support/Unix/Signals.inc b/gnu/llvm/lib/Support/Unix/Signals.inc
deleted file mode 100644
index ad88d5e9690..00000000000
--- a/gnu/llvm/lib/Support/Unix/Signals.inc
+++ /dev/null
@@ -1,586 +0,0 @@
-//===- Signals.cpp - Generic Unix Signals Implementation -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines some helpful functions for dealing with the possibility of
-// Unix signals occurring while your program is running.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is extremely careful to only do signal-safe things while in a
-// signal handler. In particular, memory allocation and acquiring a mutex
-// while in a signal handler should never occur. ManagedStatic isn't usable from
-// a signal handler for 2 reasons:
-//
-// 1. Creating a new one allocates.
-// 2. The signal handler could fire while llvm_shutdown is being processed, in
-// which case the ManagedStatic is in an unknown state because it could
-// already have been destroyed, or be in the process of being destroyed.
-//
-// Modifying the behavior of the signal handlers (such as registering new ones)
-// can acquire a mutex, but all this guarantees is that the signal handler
-// behavior is only modified by one thread at a time. A signal handler can still
-// fire while this occurs!
-//
-// Adding work to a signal handler requires lock-freedom (and assume atomics are
-// always lock-free) because the signal handler could fire while new work is
-// being added.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Unix.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Config/config.h"
-#include "llvm/Demangle/Demangle.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/UniqueLock.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <string>
-#include <sysexits.h>
-#ifdef HAVE_BACKTRACE
-# include BACKTRACE_HEADER // For backtrace().
-#endif
-#if HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-#if HAVE_MACH_MACH_H
-#include <mach/mach.h>
-#endif
-#if HAVE_LINK_H
-#include <link.h>
-#endif
-#ifdef HAVE__UNWIND_BACKTRACE
-// FIXME: We should be able to use <unwind.h> for any target that has an
-// _Unwind_Backtrace function, but on FreeBSD the configure test passes
-// despite the function not existing, and on Android, <unwind.h> conflicts
-// with <link.h>.
-#ifdef __GLIBC__
-#include <unwind.h>
-#else
-#undef HAVE__UNWIND_BACKTRACE
-#endif
-#endif
-
-using namespace llvm;
-
-static RETSIGTYPE SignalHandler(int Sig); // defined below.
-
-/// The function to call if ctrl-c is pressed.
-using InterruptFunctionType = void (*)();
-static std::atomic<InterruptFunctionType> InterruptFunction =
- ATOMIC_VAR_INIT(nullptr);
-
-namespace {
-/// Signal-safe removal of files.
-/// Inserting and erasing from the list isn't signal-safe, but removal of files
-/// themselves is signal-safe. Memory is freed when the head is freed, deletion
-/// is therefore not signal-safe either.
-class FileToRemoveList {
- std::atomic<char *> Filename = ATOMIC_VAR_INIT(nullptr);
- std::atomic<FileToRemoveList *> Next = ATOMIC_VAR_INIT(nullptr);
-
- FileToRemoveList() = default;
- // Not signal-safe.
- FileToRemoveList(const std::string &str) : Filename(strdup(str.c_str())) {}
-
-public:
- // Not signal-safe.
- ~FileToRemoveList() {
- if (FileToRemoveList *N = Next.exchange(nullptr))
- delete N;
- if (char *F = Filename.exchange(nullptr))
- free(F);
- }
-
- // Not signal-safe.
- static void insert(std::atomic<FileToRemoveList *> &Head,
- const std::string &Filename) {
- // Insert the new file at the end of the list.
- FileToRemoveList *NewHead = new FileToRemoveList(Filename);
- std::atomic<FileToRemoveList *> *InsertionPoint = &Head;
- FileToRemoveList *OldHead = nullptr;
- while (!InsertionPoint->compare_exchange_strong(OldHead, NewHead)) {
- InsertionPoint = &OldHead->Next;
- OldHead = nullptr;
- }
- }
-
- // Not signal-safe.
- static void erase(std::atomic<FileToRemoveList *> &Head,
- const std::string &Filename) {
- // Use a lock to avoid concurrent erase: the comparison would access
- // free'd memory.
- static ManagedStatic<sys::SmartMutex<true>> Lock;
- sys::SmartScopedLock<true> Writer(*Lock);
-
- for (FileToRemoveList *Current = Head.load(); Current;
- Current = Current->Next.load()) {
- if (char *OldFilename = Current->Filename.load()) {
- if (OldFilename != Filename)
- continue;
- // Leave an empty filename.
- OldFilename = Current->Filename.exchange(nullptr);
- // The filename might have become null between the time we
- // compared it and we exchanged it.
- if (OldFilename)
- free(OldFilename);
- }
- }
- }
-
- // Signal-safe.
- static void removeAllFiles(std::atomic<FileToRemoveList *> &Head) {
- // If cleanup were to occur while we're removing files we'd have a bad time.
- // Make sure we're OK by preventing cleanup from doing anything while we're
- // removing files. If cleanup races with us and we win we'll have a leak,
- // but we won't crash.
- FileToRemoveList *OldHead = Head.exchange(nullptr);
-
- for (FileToRemoveList *currentFile = OldHead; currentFile;
- currentFile = currentFile->Next.load()) {
- // If erasing was occuring while we're trying to remove files we'd look
- // at free'd data. Take away the path and put it back when done.
- if (char *path = currentFile->Filename.exchange(nullptr)) {
- // Get the status so we can determine if it's a file or directory. If we
- // can't stat the file, ignore it.
- struct stat buf;
- if (stat(path, &buf) != 0)
- continue;
-
- // If this is not a regular file, ignore it. We want to prevent removal
- // of special files like /dev/null, even if the compiler is being run
- // with the super-user permissions.
- if (!S_ISREG(buf.st_mode))
- continue;
-
- // Otherwise, remove the file. We ignore any errors here as there is
- // nothing else we can do.
- unlink(path);
-
- // We're done removing the file, erasing can safely proceed.
- currentFile->Filename.exchange(path);
- }
- }
-
- // We're done removing files, cleanup can safely proceed.
- Head.exchange(OldHead);
- }
-};
-static std::atomic<FileToRemoveList *> FilesToRemove = ATOMIC_VAR_INIT(nullptr);
-
-/// Clean up the list in a signal-friendly manner.
-/// Recall that signals can fire during llvm_shutdown. If this occurs we should
-/// either clean something up or nothing at all, but we shouldn't crash!
-struct FilesToRemoveCleanup {
- // Not signal-safe.
- ~FilesToRemoveCleanup() {
- FileToRemoveList *Head = FilesToRemove.exchange(nullptr);
- if (Head)
- delete Head;
- }
-};
-} // namespace
-
-static StringRef Argv0;
-
-// Signals that represent requested termination. There's no bug or failure, or
-// if there is, it's not our direct responsibility. For whatever reason, our
-// continued execution is no longer desirable.
-static const int IntSigs[] = {
- SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2
-};
-
-// Signals that represent that we have a bug, and our prompt termination has
-// been ordered.
-static const int KillSigs[] = {
- SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGQUIT
-#ifdef SIGSYS
- , SIGSYS
-#endif
-#ifdef SIGXCPU
- , SIGXCPU
-#endif
-#ifdef SIGXFSZ
- , SIGXFSZ
-#endif
-#ifdef SIGEMT
- , SIGEMT
-#endif
-};
-
-static std::atomic<unsigned> NumRegisteredSignals = ATOMIC_VAR_INIT(0);
-static struct {
- struct sigaction SA;
- int SigNo;
-} RegisteredSignalInfo[array_lengthof(IntSigs) + array_lengthof(KillSigs)];
-
-#if defined(HAVE_SIGALTSTACK)
-// Hold onto both the old and new alternate signal stack so that it's not
-// reported as a leak. We don't make any attempt to remove our alt signal
-// stack if we remove our signal handlers; that can't be done reliably if
-// someone else is also trying to do the same thing.
-static stack_t OldAltStack;
-static void* NewAltStackPointer;
-
-static void CreateSigAltStack() {
- const size_t AltStackSize = MINSIGSTKSZ + 64 * 1024;
-
- // If we're executing on the alternate stack, or we already have an alternate
- // signal stack that we're happy with, there's nothing for us to do. Don't
- // reduce the size, some other part of the process might need a larger stack
- // than we do.
- if (sigaltstack(nullptr, &OldAltStack) != 0 ||
- OldAltStack.ss_flags & SS_ONSTACK ||
- (OldAltStack.ss_sp && OldAltStack.ss_size >= AltStackSize))
- return;
-
- stack_t AltStack = {};
- AltStack.ss_sp = static_cast<char *>(safe_malloc(AltStackSize));
- NewAltStackPointer = AltStack.ss_sp; // Save to avoid reporting a leak.
- AltStack.ss_size = AltStackSize;
- if (sigaltstack(&AltStack, &OldAltStack) != 0)
- free(AltStack.ss_sp);
-}
-#else
-static void CreateSigAltStack() {}
-#endif
-
-static void RegisterHandlers() { // Not signal-safe.
- // The mutex prevents other threads from registering handlers while we're
- // doing it. We also have to protect the handlers and their count because
- // a signal handler could fire while we're registeting handlers.
- static ManagedStatic<sys::SmartMutex<true>> SignalHandlerRegistrationMutex;
- sys::SmartScopedLock<true> Guard(*SignalHandlerRegistrationMutex);
-
- // If the handlers are already registered, we're done.
- if (NumRegisteredSignals.load() != 0)
- return;
-
- // Create an alternate stack for signal handling. This is necessary for us to
- // be able to reliably handle signals due to stack overflow.
- CreateSigAltStack();
-
- auto registerHandler = [&](int Signal) {
- unsigned Index = NumRegisteredSignals.load();
- assert(Index < array_lengthof(RegisteredSignalInfo) &&
- "Out of space for signal handlers!");
-
- struct sigaction NewHandler;
-
- NewHandler.sa_handler = SignalHandler;
- NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK;
- sigemptyset(&NewHandler.sa_mask);
-
- // Install the new handler, save the old one in RegisteredSignalInfo.
- sigaction(Signal, &NewHandler, &RegisteredSignalInfo[Index].SA);
- RegisteredSignalInfo[Index].SigNo = Signal;
- ++NumRegisteredSignals;
- };
-
- for (auto S : IntSigs)
- registerHandler(S);
- for (auto S : KillSigs)
- registerHandler(S);
-}
-
-static void UnregisterHandlers() {
- // Restore all of the signal handlers to how they were before we showed up.
- for (unsigned i = 0, e = NumRegisteredSignals.load(); i != e; ++i) {
- sigaction(RegisteredSignalInfo[i].SigNo,
- &RegisteredSignalInfo[i].SA, nullptr);
- --NumRegisteredSignals;
- }
-}
-
-/// Process the FilesToRemove list.
-static void RemoveFilesToRemove() {
- FileToRemoveList::removeAllFiles(FilesToRemove);
-}
-
-// The signal handler that runs.
-static RETSIGTYPE SignalHandler(int Sig) {
- // Restore the signal behavior to default, so that the program actually
- // crashes when we return and the signal reissues. This also ensures that if
- // we crash in our signal handler that the program will terminate immediately
- // instead of recursing in the signal handler.
- UnregisterHandlers();
-
- // Unmask all potentially blocked kill signals.
- sigset_t SigMask;
- sigfillset(&SigMask);
- sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
-
- {
- RemoveFilesToRemove();
-
- if (std::find(std::begin(IntSigs), std::end(IntSigs), Sig)
- != std::end(IntSigs)) {
- if (auto OldInterruptFunction = InterruptFunction.exchange(nullptr))
- return OldInterruptFunction();
-
- // Send a special return code that drivers can check for, from sysexits.h.
- if (Sig == SIGPIPE)
- exit(EX_IOERR);
-
- raise(Sig); // Execute the default handler.
- return;
- }
- }
-
- // Otherwise if it is a fault (like SEGV) run any handler.
- llvm::sys::RunSignalHandlers();
-
-#ifdef __s390__
- // On S/390, certain signals are delivered with PSW Address pointing to
- // *after* the faulting instruction. Simply returning from the signal
- // handler would continue execution after that point, instead of
- // re-raising the signal. Raise the signal manually in those cases.
- if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP)
- raise(Sig);
-#endif
-}
-
-void llvm::sys::RunInterruptHandlers() {
- RemoveFilesToRemove();
-}
-
-void llvm::sys::SetInterruptFunction(void (*IF)()) {
- InterruptFunction.exchange(IF);
- RegisterHandlers();
-}
-
-// The public API
-bool llvm::sys::RemoveFileOnSignal(StringRef Filename,
- std::string* ErrMsg) {
- // Ensure that cleanup will occur as soon as one file is added.
- static ManagedStatic<FilesToRemoveCleanup> FilesToRemoveCleanup;
- *FilesToRemoveCleanup;
- FileToRemoveList::insert(FilesToRemove, Filename.str());
- RegisterHandlers();
- return false;
-}
-
-// The public API
-void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) {
- FileToRemoveList::erase(FilesToRemove, Filename.str());
-}
-
-/// Add a function to be called when a signal is delivered to the process. The
-/// handler can have a cookie passed to it to identify what instance of the
-/// handler it is.
-void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr,
- void *Cookie) { // Signal-safe.
- insertSignalHandler(FnPtr, Cookie);
- RegisterHandlers();
-}
-
-#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && HAVE_LINK_H && \
- (defined(__linux__) || defined(__FreeBSD__) || \
- defined(__FreeBSD_kernel__) || defined(__NetBSD__))
-struct DlIteratePhdrData {
- void **StackTrace;
- int depth;
- bool first;
- const char **modules;
- intptr_t *offsets;
- const char *main_exec_name;
-};
-
-static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
- DlIteratePhdrData *data = (DlIteratePhdrData*)arg;
- const char *name = data->first ? data->main_exec_name : info->dlpi_name;
- data->first = false;
- for (int i = 0; i < info->dlpi_phnum; i++) {
- const auto *phdr = &info->dlpi_phdr[i];
- if (phdr->p_type != PT_LOAD)
- continue;
- intptr_t beg = info->dlpi_addr + phdr->p_vaddr;
- intptr_t end = beg + phdr->p_memsz;
- for (int j = 0; j < data->depth; j++) {
- if (data->modules[j])
- continue;
- intptr_t addr = (intptr_t)data->StackTrace[j];
- if (beg <= addr && addr < end) {
- data->modules[j] = name;
- data->offsets[j] = addr - info->dlpi_addr;
- }
- }
- }
- return 0;
-}
-
-/// If this is an ELF platform, we can find all loaded modules and their virtual
-/// addresses with dl_iterate_phdr.
-static bool findModulesAndOffsets(void **StackTrace, int Depth,
- const char **Modules, intptr_t *Offsets,
- const char *MainExecutableName,
- StringSaver &StrPool) {
- DlIteratePhdrData data = {StackTrace, Depth, true,
- Modules, Offsets, MainExecutableName};
- dl_iterate_phdr(dl_iterate_phdr_cb, &data);
- return true;
-}
-#else
-/// This platform does not have dl_iterate_phdr, so we do not yet know how to
-/// find all loaded DSOs.
-static bool findModulesAndOffsets(void **StackTrace, int Depth,
- const char **Modules, intptr_t *Offsets,
- const char *MainExecutableName,
- StringSaver &StrPool) {
- return false;
-}
-#endif // defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && ...
-
-#if ENABLE_BACKTRACES && defined(HAVE__UNWIND_BACKTRACE)
-static int unwindBacktrace(void **StackTrace, int MaxEntries) {
- if (MaxEntries < 0)
- return 0;
-
- // Skip the first frame ('unwindBacktrace' itself).
- int Entries = -1;
-
- auto HandleFrame = [&](_Unwind_Context *Context) -> _Unwind_Reason_Code {
- // Apparently we need to detect reaching the end of the stack ourselves.
- void *IP = (void *)_Unwind_GetIP(Context);
- if (!IP)
- return _URC_END_OF_STACK;
-
- assert(Entries < MaxEntries && "recursively called after END_OF_STACK?");
- if (Entries >= 0)
- StackTrace[Entries] = IP;
-
- if (++Entries == MaxEntries)
- return _URC_END_OF_STACK;
- return _URC_NO_REASON;
- };
-
- _Unwind_Backtrace(
- [](_Unwind_Context *Context, void *Handler) {
- return (*static_cast<decltype(HandleFrame) *>(Handler))(Context);
- },
- static_cast<void *>(&HandleFrame));
- return std::max(Entries, 0);
-}
-#endif
-
-// In the case of a program crash or fault, print out a stack trace so that the
-// user has an indication of why and where we died.
-//
-// On glibc systems we have the 'backtrace' function, which works nicely, but
-// doesn't demangle symbols.
-void llvm::sys::PrintStackTrace(raw_ostream &OS) {
-#if ENABLE_BACKTRACES
- static void *StackTrace[256];
- int depth = 0;
-#if defined(HAVE_BACKTRACE)
- // Use backtrace() to output a backtrace on Linux systems with glibc.
- if (!depth)
- depth = backtrace(StackTrace, static_cast<int>(array_lengthof(StackTrace)));
-#endif
-#if defined(HAVE__UNWIND_BACKTRACE)
- // Try _Unwind_Backtrace() if backtrace() failed.
- if (!depth)
- depth = unwindBacktrace(StackTrace,
- static_cast<int>(array_lengthof(StackTrace)));
-#endif
- if (!depth)
- return;
-
- if (printSymbolizedStackTrace(Argv0, StackTrace, depth, OS))
- return;
-#if HAVE_DLFCN_H && HAVE_DLADDR
- int width = 0;
- for (int i = 0; i < depth; ++i) {
- Dl_info dlinfo;
- dladdr(StackTrace[i], &dlinfo);
- const char* name = strrchr(dlinfo.dli_fname, '/');
-
- int nwidth;
- if (!name) nwidth = strlen(dlinfo.dli_fname);
- else nwidth = strlen(name) - 1;
-
- if (nwidth > width) width = nwidth;
- }
-
- for (int i = 0; i < depth; ++i) {
- Dl_info dlinfo;
- dladdr(StackTrace[i], &dlinfo);
-
- OS << format("%-2d", i);
-
- const char* name = strrchr(dlinfo.dli_fname, '/');
- if (!name) OS << format(" %-*s", width, dlinfo.dli_fname);
- else OS << format(" %-*s", width, name+1);
-
- OS << format(" %#0*lx", (int)(sizeof(void*) * 2) + 2,
- (unsigned long)StackTrace[i]);
-
- if (dlinfo.dli_sname != nullptr) {
- OS << ' ';
- int res;
- char* d = itaniumDemangle(dlinfo.dli_sname, nullptr, nullptr, &res);
- if (!d) OS << dlinfo.dli_sname;
- else OS << d;
- free(d);
-
- // FIXME: When we move to C++11, use %t length modifier. It's not in
- // C++03 and causes gcc to issue warnings. Losing the upper 32 bits of
- // the stack offset for a stack dump isn't likely to cause any problems.
- OS << format(" + %u",(unsigned)((char*)StackTrace[i]-
- (char*)dlinfo.dli_saddr));
- }
- OS << '\n';
- }
-#elif defined(HAVE_BACKTRACE)
- backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
-#endif
-#endif
-}
-
-static void PrintStackTraceSignalHandler(void *) {
- sys::PrintStackTrace(llvm::errs());
-}
-
-void llvm::sys::DisableSystemDialogsOnCrash() {}
-
-/// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
-/// process, print a stack trace and then exit.
-void llvm::sys::PrintStackTraceOnErrorSignal(StringRef Argv0,
- bool DisableCrashReporting) {
- ::Argv0 = Argv0;
-
- AddSignalHandler(PrintStackTraceSignalHandler, nullptr);
-
-#if defined(__APPLE__) && ENABLE_CRASH_OVERRIDES
- // Environment variable to disable any kind of crash dialog.
- if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) {
- mach_port_t self = mach_task_self();
-
- exception_mask_t mask = EXC_MASK_CRASH;
-
- kern_return_t ret = task_set_exception_ports(self,
- mask,
- MACH_PORT_NULL,
- EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES,
- THREAD_STATE_NONE);
- (void)ret;
- }
-#endif
-}
diff --git a/gnu/llvm/lib/Support/Unix/ThreadLocal.inc b/gnu/llvm/lib/Support/Unix/ThreadLocal.inc
deleted file mode 100644
index a6564f0fa28..00000000000
--- a/gnu/llvm/lib/Support/Unix/ThreadLocal.inc
+++ /dev/null
@@ -1,71 +0,0 @@
-//=== llvm/Support/Unix/ThreadLocal.inc - Unix Thread Local Data -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Unix specific (non-pthread) ThreadLocal class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Config/config.h"
-
-#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC)
-
-#include <cassert>
-#include <pthread.h>
-#include <stdlib.h>
-
-namespace llvm {
-using namespace sys;
-
-ThreadLocalImpl::ThreadLocalImpl() : data() {
- static_assert(sizeof(pthread_key_t) <= sizeof(data), "size too big");
- pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
- int errorcode = pthread_key_create(key, nullptr);
- assert(errorcode == 0);
- (void) errorcode;
-}
-
-ThreadLocalImpl::~ThreadLocalImpl() {
- pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
- int errorcode = pthread_key_delete(*key);
- assert(errorcode == 0);
- (void) errorcode;
-}
-
-void ThreadLocalImpl::setInstance(const void* d) {
- pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
- int errorcode = pthread_setspecific(*key, d);
- assert(errorcode == 0);
- (void) errorcode;
-}
-
-void *ThreadLocalImpl::getInstance() {
- pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
- return pthread_getspecific(*key);
-}
-
-void ThreadLocalImpl::removeInstance() {
- setInstance(nullptr);
-}
-
-}
-#else
-namespace llvm {
-using namespace sys;
-ThreadLocalImpl::ThreadLocalImpl() : data() { }
-ThreadLocalImpl::~ThreadLocalImpl() { }
-void ThreadLocalImpl::setInstance(const void* d) { data = const_cast<void*>(d);}
-void *ThreadLocalImpl::getInstance() { return data; }
-void ThreadLocalImpl::removeInstance() { setInstance(0); }
-}
-#endif
diff --git a/gnu/llvm/lib/Support/Unix/Threading.inc b/gnu/llvm/lib/Support/Unix/Threading.inc
deleted file mode 100644
index 92bec36d6a2..00000000000
--- a/gnu/llvm/lib/Support/Unix/Threading.inc
+++ /dev/null
@@ -1,220 +0,0 @@
-//===- Unix/Threading.inc - Unix Threading Implementation ----- -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides the Unix specific implementation of Threading functions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/Twine.h"
-
-#if defined(__APPLE__)
-#include <mach/mach_init.h>
-#include <mach/mach_port.h>
-#endif
-
-#include <pthread.h>
-
-#if defined(__FreeBSD__) || defined(__OpenBSD__)
-#include <pthread_np.h> // For pthread_getthreadid_np() / pthread_set_name_np()
-#endif
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <errno.h>
-#include <sys/sysctl.h>
-#include <sys/user.h>
-#include <unistd.h>
-#endif
-
-#if defined(__NetBSD__)
-#include <lwp.h> // For _lwp_self()
-#endif
-
-#if defined(__linux__)
-#include <sys/syscall.h> // For syscall codes
-#include <unistd.h> // For syscall()
-#endif
-
-namespace {
- struct ThreadInfo {
- void(*UserFn)(void *);
- void *UserData;
- };
-}
-
-static void *ExecuteOnThread_Dispatch(void *Arg) {
- ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
- TI->UserFn(TI->UserData);
- return nullptr;
-}
-
-void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData,
- unsigned RequestedStackSize) {
- ThreadInfo Info = { Fn, UserData };
- pthread_attr_t Attr;
- pthread_t Thread;
-
- // Construct the attributes object.
- if (::pthread_attr_init(&Attr) != 0)
- return;
-
- // Set the requested stack size, if given.
- if (RequestedStackSize != 0) {
- if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
- goto error;
- }
-
- // Construct and execute the thread.
- if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
- goto error;
-
- // Wait for the thread and clean up.
- ::pthread_join(Thread, nullptr);
-
-error:
- ::pthread_attr_destroy(&Attr);
-}
-
-
-uint64_t llvm::get_threadid() {
-#if defined(__APPLE__)
- // Calling "mach_thread_self()" bumps the reference count on the thread
- // port, so we need to deallocate it. mach_task_self() doesn't bump the ref
- // count.
- thread_port_t Self = mach_thread_self();
- mach_port_deallocate(mach_task_self(), Self);
- return Self;
-#elif defined(__FreeBSD__)
- return uint64_t(pthread_getthreadid_np());
-#elif defined(__NetBSD__)
- return uint64_t(_lwp_self());
-#elif defined(__ANDROID__)
- return uint64_t(gettid());
-#elif defined(__linux__)
- return uint64_t(syscall(SYS_gettid));
-#else
- return uint64_t(pthread_self());
-#endif
-}
-
-
-static constexpr uint32_t get_max_thread_name_length_impl() {
-#if defined(__NetBSD__)
- return PTHREAD_MAX_NAMELEN_NP;
-#elif defined(__APPLE__)
- return 64;
-#elif defined(__linux__)
-#if HAVE_PTHREAD_SETNAME_NP
- return 16;
-#else
- return 0;
-#endif
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- return 16;
-#elif defined(__OpenBSD__)
- return 32;
-#else
- return 0;
-#endif
-}
-
-uint32_t llvm::get_max_thread_name_length() {
- return get_max_thread_name_length_impl();
-}
-
-void llvm::set_thread_name(const Twine &Name) {
- // Make sure the input is null terminated.
- SmallString<64> Storage;
- StringRef NameStr = Name.toNullTerminatedStringRef(Storage);
-
- // Truncate from the beginning, not the end, if the specified name is too
- // long. For one, this ensures that the resulting string is still null
- // terminated, but additionally the end of a long thread name will usually
- // be more unique than the beginning, since a common pattern is for similar
- // threads to share a common prefix.
- // Note that the name length includes the null terminator.
- if (get_max_thread_name_length() > 0)
- NameStr = NameStr.take_back(get_max_thread_name_length() - 1);
- (void)NameStr;
-#if defined(__linux__)
-#if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || defined(__ANDROID__)
-#if HAVE_PTHREAD_SETNAME_NP
- ::pthread_setname_np(::pthread_self(), NameStr.data());
-#endif
-#endif
-#elif defined(__FreeBSD__) || defined(__OpenBSD__)
- ::pthread_set_name_np(::pthread_self(), NameStr.data());
-#elif defined(__NetBSD__)
- ::pthread_setname_np(::pthread_self(), "%s",
- const_cast<char *>(NameStr.data()));
-#elif defined(__APPLE__)
- ::pthread_setname_np(NameStr.data());
-#endif
-}
-
-void llvm::get_thread_name(SmallVectorImpl<char> &Name) {
- Name.clear();
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- int pid = ::getpid();
- uint64_t tid = get_threadid();
-
- struct kinfo_proc *kp = nullptr, *nkp;
- size_t len = 0;
- int error;
- int ctl[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD,
- (int)pid };
-
- while (1) {
- error = sysctl(ctl, 4, kp, &len, nullptr, 0);
- if (kp == nullptr || (error != 0 && errno == ENOMEM)) {
- // Add extra space in case threads are added before next call.
- len += sizeof(*kp) + len / 10;
- nkp = (struct kinfo_proc *)::realloc(kp, len);
- if (nkp == nullptr) {
- free(kp);
- return;
- }
- kp = nkp;
- continue;
- }
- if (error != 0)
- len = 0;
- break;
- }
-
- for (size_t i = 0; i < len / sizeof(*kp); i++) {
- if (kp[i].ki_tid == (lwpid_t)tid) {
- Name.append(kp[i].ki_tdname, kp[i].ki_tdname + strlen(kp[i].ki_tdname));
- break;
- }
- }
- free(kp);
- return;
-#elif defined(__NetBSD__)
- constexpr uint32_t len = get_max_thread_name_length_impl();
- char buf[len];
- ::pthread_getname_np(::pthread_self(), buf, len);
-
- Name.append(buf, buf + strlen(buf));
-#elif defined(__OpenBSD__)
- constexpr uint32_t len = get_max_thread_name_length_impl();
- char buf[len];
- ::pthread_get_name_np(::pthread_self(), buf, len);
-
- Name.append(buf, buf + strlen(buf));
-#elif defined(__linux__)
-#if HAVE_PTHREAD_GETNAME_NP
- constexpr uint32_t len = get_max_thread_name_length_impl();
- char Buffer[len] = {'\0'}; // FIXME: working around MSan false positive.
- if (0 == ::pthread_getname_np(::pthread_self(), Buffer, len))
- Name.append(Buffer, Buffer + strlen(Buffer));
-#endif
-#endif
-}
diff --git a/gnu/llvm/lib/Support/Unix/Unix.h b/gnu/llvm/lib/Support/Unix/Unix.h
deleted file mode 100644
index 0c5d4de556d..00000000000
--- a/gnu/llvm/lib/Support/Unix/Unix.h
+++ /dev/null
@@ -1,106 +0,0 @@
-//===- llvm/Support/Unix/Unix.h - Common Unix Include File -------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines things specific to Unix implementations.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIB_SUPPORT_UNIX_UNIX_H
-#define LLVM_LIB_SUPPORT_UNIX_UNIX_H
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on all UNIX variants.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Config/config.h" // Get autoconf configuration settings
-#include "llvm/Support/Chrono.h"
-#include "llvm/Support/Errno.h"
-#include <algorithm>
-#include <assert.h>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <string>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-#include <time.h>
-
-#ifdef HAVE_DLFCN_H
-# include <dlfcn.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-
-/// This function builds an error message into \p ErrMsg using the \p prefix
-/// string and the Unix error number given by \p errnum. If errnum is -1, the
-/// default then the value of errno is used.
-/// Make an error message
-///
-/// If the error number can be converted to a string, it will be
-/// separated from prefix by ": ".
-static inline bool MakeErrMsg(
- std::string* ErrMsg, const std::string& prefix, int errnum = -1) {
- if (!ErrMsg)
- return true;
- if (errnum == -1)
- errnum = errno;
- *ErrMsg = prefix + ": " + llvm::sys::StrError(errnum);
- return true;
-}
-
-namespace llvm {
-namespace sys {
-
-/// Convert a struct timeval to a duration. Note that timeval can be used both
-/// as a time point and a duration. Be sure to check what the input represents.
-inline std::chrono::microseconds toDuration(const struct timeval &TV) {
- return std::chrono::seconds(TV.tv_sec) +
- std::chrono::microseconds(TV.tv_usec);
-}
-
-/// Convert a time point to struct timespec.
-inline struct timespec toTimeSpec(TimePoint<> TP) {
- using namespace std::chrono;
-
- struct timespec RetVal;
- RetVal.tv_sec = toTimeT(TP);
- RetVal.tv_nsec = (TP.time_since_epoch() % seconds(1)).count();
- return RetVal;
-}
-
-/// Convert a time point to struct timeval.
-inline struct timeval toTimeVal(TimePoint<std::chrono::microseconds> TP) {
- using namespace std::chrono;
-
- struct timeval RetVal;
- RetVal.tv_sec = toTimeT(TP);
- RetVal.tv_usec = (TP.time_since_epoch() % seconds(1)).count();
- return RetVal;
-}
-
-} // namespace sys
-} // namespace llvm
-
-#endif
diff --git a/gnu/llvm/lib/Support/Unix/Watchdog.inc b/gnu/llvm/lib/Support/Unix/Watchdog.inc
deleted file mode 100644
index f4253391d95..00000000000
--- a/gnu/llvm/lib/Support/Unix/Watchdog.inc
+++ /dev/null
@@ -1,34 +0,0 @@
-//===--- Unix/Watchdog.inc - Unix Watchdog Implementation -------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides the generic Unix implementation of the Watchdog class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Config/config.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-namespace llvm {
- namespace sys {
- Watchdog::Watchdog(unsigned int seconds) {
-#ifdef HAVE_UNISTD_H
- alarm(seconds);
-#endif
- }
-
- Watchdog::~Watchdog() {
-#ifdef HAVE_UNISTD_H
- alarm(0);
-#endif
- }
- }
-}
diff --git a/gnu/llvm/lib/Support/Valgrind.cpp b/gnu/llvm/lib/Support/Valgrind.cpp
deleted file mode 100644
index 8d852a67c07..00000000000
--- a/gnu/llvm/lib/Support/Valgrind.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-//===-- Valgrind.cpp - Implement Valgrind communication ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines Valgrind communication methods, if HAVE_VALGRIND_VALGRIND_H is
-// defined. If we have valgrind.h but valgrind isn't running, its macros are
-// no-ops.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Valgrind.h"
-#include "llvm/Config/config.h"
-#include <cstddef>
-
-#if HAVE_VALGRIND_VALGRIND_H
-#include <valgrind/valgrind.h>
-
-static bool InitNotUnderValgrind() {
- return !RUNNING_ON_VALGRIND;
-}
-
-// This bool is negated from what we'd expect because code may run before it
-// gets initialized. If that happens, it will appear to be 0 (false), and we
-// want that to cause the rest of the code in this file to run the
-// Valgrind-provided macros.
-static const bool NotUnderValgrind = InitNotUnderValgrind();
-
-bool llvm::sys::RunningOnValgrind() {
- if (NotUnderValgrind)
- return false;
- return RUNNING_ON_VALGRIND;
-}
-
-void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) {
- if (NotUnderValgrind)
- return;
-
- VALGRIND_DISCARD_TRANSLATIONS(Addr, Len);
-}
-
-#else // !HAVE_VALGRIND_VALGRIND_H
-
-bool llvm::sys::RunningOnValgrind() {
- return false;
-}
-
-void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) {
-}
-
-#endif // !HAVE_VALGRIND_VALGRIND_H
diff --git a/gnu/llvm/lib/Support/VersionTuple.cpp b/gnu/llvm/lib/Support/VersionTuple.cpp
deleted file mode 100644
index 3f219bfbedf..00000000000
--- a/gnu/llvm/lib/Support/VersionTuple.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-//===- VersionTuple.cpp - Version Number Handling ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the VersionTuple class, which represents a version in
-// the form major[.minor[.subminor]].
-//
-//===----------------------------------------------------------------------===//
-#include "llvm/Support/VersionTuple.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-std::string VersionTuple::getAsString() const {
- std::string Result;
- {
- llvm::raw_string_ostream Out(Result);
- Out << *this;
- }
- return Result;
-}
-
-raw_ostream &llvm::operator<<(raw_ostream &Out, const VersionTuple &V) {
- Out << V.getMajor();
- if (Optional<unsigned> Minor = V.getMinor())
- Out << '.' << *Minor;
- if (Optional<unsigned> Subminor = V.getSubminor())
- Out << '.' << *Subminor;
- if (Optional<unsigned> Build = V.getBuild())
- Out << '.' << *Build;
- return Out;
-}
-
-static bool parseInt(StringRef &input, unsigned &value) {
- assert(value == 0);
- if (input.empty())
- return true;
-
- char next = input[0];
- input = input.substr(1);
- if (next < '0' || next > '9')
- return true;
- value = (unsigned)(next - '0');
-
- while (!input.empty()) {
- next = input[0];
- if (next < '0' || next > '9')
- return false;
- input = input.substr(1);
- value = value * 10 + (unsigned)(next - '0');
- }
-
- return false;
-}
-
-bool VersionTuple::tryParse(StringRef input) {
- unsigned major = 0, minor = 0, micro = 0, build = 0;
-
- // Parse the major version, [0-9]+
- if (parseInt(input, major))
- return true;
-
- if (input.empty()) {
- *this = VersionTuple(major);
- return false;
- }
-
- // If we're not done, parse the minor version, \.[0-9]+
- if (input[0] != '.')
- return true;
- input = input.substr(1);
- if (parseInt(input, minor))
- return true;
-
- if (input.empty()) {
- *this = VersionTuple(major, minor);
- return false;
- }
-
- // If we're not done, parse the micro version, \.[0-9]+
- if (input[0] != '.')
- return true;
- input = input.substr(1);
- if (parseInt(input, micro))
- return true;
-
- if (input.empty()) {
- *this = VersionTuple(major, minor, micro);
- return false;
- }
-
- // If we're not done, parse the micro version, \.[0-9]+
- if (input[0] != '.')
- return true;
- input = input.substr(1);
- if (parseInt(input, build))
- return true;
-
- // If we have characters left over, it's an error.
- if (!input.empty())
- return true;
-
- *this = VersionTuple(major, minor, micro, build);
- return false;
-}
diff --git a/gnu/llvm/lib/Support/VirtualFileSystem.cpp b/gnu/llvm/lib/Support/VirtualFileSystem.cpp
deleted file mode 100644
index f2a8a1bb27a..00000000000
--- a/gnu/llvm/lib/Support/VirtualFileSystem.cpp
+++ /dev/null
@@ -1,2070 +0,0 @@
-//===- VirtualFileSystem.cpp - Virtual File System Layer ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the VirtualFileSystem interface.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/VirtualFileSystem.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Chrono.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/YAMLParser.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <atomic>
-#include <cassert>
-#include <cstdint>
-#include <iterator>
-#include <limits>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <string>
-#include <system_error>
-#include <utility>
-#include <vector>
-
-using namespace llvm;
-using namespace llvm::vfs;
-
-using llvm::sys::fs::file_status;
-using llvm::sys::fs::file_type;
-using llvm::sys::fs::perms;
-using llvm::sys::fs::UniqueID;
-
-Status::Status(const file_status &Status)
- : UID(Status.getUniqueID()), MTime(Status.getLastModificationTime()),
- User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),
- Type(Status.type()), Perms(Status.permissions()) {}
-
-Status::Status(StringRef Name, UniqueID UID, sys::TimePoint<> MTime,
- uint32_t User, uint32_t Group, uint64_t Size, file_type Type,
- perms Perms)
- : Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size),
- Type(Type), Perms(Perms) {}
-
-Status Status::copyWithNewName(const Status &In, StringRef NewName) {
- return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
- In.getUser(), In.getGroup(), In.getSize(), In.getType(),
- In.getPermissions());
-}
-
-Status Status::copyWithNewName(const file_status &In, StringRef NewName) {
- return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
- In.getUser(), In.getGroup(), In.getSize(), In.type(),
- In.permissions());
-}
-
-bool Status::equivalent(const Status &Other) const {
- assert(isStatusKnown() && Other.isStatusKnown());
- return getUniqueID() == Other.getUniqueID();
-}
-
-bool Status::isDirectory() const { return Type == file_type::directory_file; }
-
-bool Status::isRegularFile() const { return Type == file_type::regular_file; }
-
-bool Status::isOther() const {
- return exists() && !isRegularFile() && !isDirectory() && !isSymlink();
-}
-
-bool Status::isSymlink() const { return Type == file_type::symlink_file; }
-
-bool Status::isStatusKnown() const { return Type != file_type::status_error; }
-
-bool Status::exists() const {
- return isStatusKnown() && Type != file_type::file_not_found;
-}
-
-File::~File() = default;
-
-FileSystem::~FileSystem() = default;
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize,
- bool RequiresNullTerminator, bool IsVolatile) {
- auto F = openFileForRead(Name);
- if (!F)
- return F.getError();
-
- return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);
-}
-
-std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
- if (llvm::sys::path::is_absolute(Path))
- return {};
-
- auto WorkingDir = getCurrentWorkingDirectory();
- if (!WorkingDir)
- return WorkingDir.getError();
-
- llvm::sys::fs::make_absolute(WorkingDir.get(), Path);
- return {};
-}
-
-std::error_code FileSystem::getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const {
- return errc::operation_not_permitted;
-}
-
-std::error_code FileSystem::isLocal(const Twine &Path, bool &Result) {
- return errc::operation_not_permitted;
-}
-
-bool FileSystem::exists(const Twine &Path) {
- auto Status = status(Path);
- return Status && Status->exists();
-}
-
-#ifndef NDEBUG
-static bool isTraversalComponent(StringRef Component) {
- return Component.equals("..") || Component.equals(".");
-}
-
-static bool pathHasTraversal(StringRef Path) {
- using namespace llvm::sys;
-
- for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path)))
- if (isTraversalComponent(Comp))
- return true;
- return false;
-}
-#endif
-
-//===-----------------------------------------------------------------------===/
-// RealFileSystem implementation
-//===-----------------------------------------------------------------------===/
-
-namespace {
-
-/// Wrapper around a raw file descriptor.
-class RealFile : public File {
- friend class RealFileSystem;
-
- int FD;
- Status S;
- std::string RealName;
-
- RealFile(int FD, StringRef NewName, StringRef NewRealPathName)
- : FD(FD), S(NewName, {}, {}, {}, {}, {},
- llvm::sys::fs::file_type::status_error, {}),
- RealName(NewRealPathName.str()) {
- assert(FD >= 0 && "Invalid or inactive file descriptor");
- }
-
-public:
- ~RealFile() override;
-
- ErrorOr<Status> status() override;
- ErrorOr<std::string> getName() override;
- ErrorOr<std::unique_ptr<MemoryBuffer>> getBuffer(const Twine &Name,
- int64_t FileSize,
- bool RequiresNullTerminator,
- bool IsVolatile) override;
- std::error_code close() override;
-};
-
-} // namespace
-
-RealFile::~RealFile() { close(); }
-
-ErrorOr<Status> RealFile::status() {
- assert(FD != -1 && "cannot stat closed file");
- if (!S.isStatusKnown()) {
- file_status RealStatus;
- if (std::error_code EC = sys::fs::status(FD, RealStatus))
- return EC;
- S = Status::copyWithNewName(RealStatus, S.getName());
- }
- return S;
-}
-
-ErrorOr<std::string> RealFile::getName() {
- return RealName.empty() ? S.getName().str() : RealName;
-}
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-RealFile::getBuffer(const Twine &Name, int64_t FileSize,
- bool RequiresNullTerminator, bool IsVolatile) {
- assert(FD != -1 && "cannot get buffer for closed file");
- return MemoryBuffer::getOpenFile(FD, Name, FileSize, RequiresNullTerminator,
- IsVolatile);
-}
-
-std::error_code RealFile::close() {
- std::error_code EC = sys::Process::SafelyCloseFileDescriptor(FD);
- FD = -1;
- return EC;
-}
-
-namespace {
-
-/// The file system according to your operating system.
-class RealFileSystem : public FileSystem {
-public:
- ErrorOr<Status> status(const Twine &Path) override;
- ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
- directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
-
- llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
- std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
- std::error_code isLocal(const Twine &Path, bool &Result) override;
- std::error_code getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const override;
-
-private:
- mutable std::mutex CWDMutex;
- mutable std::string CWDCache;
-};
-
-} // namespace
-
-ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
- sys::fs::file_status RealStatus;
- if (std::error_code EC = sys::fs::status(Path, RealStatus))
- return EC;
- return Status::copyWithNewName(RealStatus, Path.str());
-}
-
-ErrorOr<std::unique_ptr<File>>
-RealFileSystem::openFileForRead(const Twine &Name) {
- int FD;
- SmallString<256> RealName;
- if (std::error_code EC =
- sys::fs::openFileForRead(Name, FD, sys::fs::OF_None, &RealName))
- return EC;
- return std::unique_ptr<File>(new RealFile(FD, Name.str(), RealName.str()));
-}
-
-llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
- std::lock_guard<std::mutex> Lock(CWDMutex);
- if (!CWDCache.empty())
- return CWDCache;
- SmallString<256> Dir;
- if (std::error_code EC = llvm::sys::fs::current_path(Dir))
- return EC;
- CWDCache = Dir.str();
- return CWDCache;
-}
-
-std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
- // FIXME: chdir is thread hostile; on the other hand, creating the same
- // behavior as chdir is complex: chdir resolves the path once, thus
- // guaranteeing that all subsequent relative path operations work
- // on the same path the original chdir resulted in. This makes a
- // difference for example on network filesystems, where symlinks might be
- // switched during runtime of the tool. Fixing this depends on having a
- // file system abstraction that allows openat() style interactions.
- if (auto EC = llvm::sys::fs::set_current_path(Path))
- return EC;
-
- // Invalidate cache.
- std::lock_guard<std::mutex> Lock(CWDMutex);
- CWDCache.clear();
- return std::error_code();
-}
-
-std::error_code RealFileSystem::isLocal(const Twine &Path, bool &Result) {
- return llvm::sys::fs::is_local(Path, Result);
-}
-
-std::error_code
-RealFileSystem::getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const {
- return llvm::sys::fs::real_path(Path, Output);
-}
-
-IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
- static IntrusiveRefCntPtr<FileSystem> FS = new RealFileSystem();
- return FS;
-}
-
-namespace {
-
-class RealFSDirIter : public llvm::vfs::detail::DirIterImpl {
- llvm::sys::fs::directory_iterator Iter;
-
-public:
- RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
- if (Iter != llvm::sys::fs::directory_iterator())
- CurrentEntry = directory_entry(Iter->path(), Iter->type());
- }
-
- std::error_code increment() override {
- std::error_code EC;
- Iter.increment(EC);
- CurrentEntry = (Iter == llvm::sys::fs::directory_iterator())
- ? directory_entry()
- : directory_entry(Iter->path(), Iter->type());
- return EC;
- }
-};
-
-} // namespace
-
-directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
- std::error_code &EC) {
- return directory_iterator(std::make_shared<RealFSDirIter>(Dir, EC));
-}
-
-//===-----------------------------------------------------------------------===/
-// OverlayFileSystem implementation
-//===-----------------------------------------------------------------------===/
-
-OverlayFileSystem::OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> BaseFS) {
- FSList.push_back(std::move(BaseFS));
-}
-
-void OverlayFileSystem::pushOverlay(IntrusiveRefCntPtr<FileSystem> FS) {
- FSList.push_back(FS);
- // Synchronize added file systems by duplicating the working directory from
- // the first one in the list.
- FS->setCurrentWorkingDirectory(getCurrentWorkingDirectory().get());
-}
-
-ErrorOr<Status> OverlayFileSystem::status(const Twine &Path) {
- // FIXME: handle symlinks that cross file systems
- for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
- ErrorOr<Status> Status = (*I)->status(Path);
- if (Status || Status.getError() != llvm::errc::no_such_file_or_directory)
- return Status;
- }
- return make_error_code(llvm::errc::no_such_file_or_directory);
-}
-
-ErrorOr<std::unique_ptr<File>>
-OverlayFileSystem::openFileForRead(const llvm::Twine &Path) {
- // FIXME: handle symlinks that cross file systems
- for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
- auto Result = (*I)->openFileForRead(Path);
- if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
- return Result;
- }
- return make_error_code(llvm::errc::no_such_file_or_directory);
-}
-
-llvm::ErrorOr<std::string>
-OverlayFileSystem::getCurrentWorkingDirectory() const {
- // All file systems are synchronized, just take the first working directory.
- return FSList.front()->getCurrentWorkingDirectory();
-}
-
-std::error_code
-OverlayFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
- for (auto &FS : FSList)
- if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
- return EC;
- return {};
-}
-
-std::error_code OverlayFileSystem::isLocal(const Twine &Path, bool &Result) {
- for (auto &FS : FSList)
- if (FS->exists(Path))
- return FS->isLocal(Path, Result);
- return errc::no_such_file_or_directory;
-}
-
-std::error_code
-OverlayFileSystem::getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const {
- for (auto &FS : FSList)
- if (FS->exists(Path))
- return FS->getRealPath(Path, Output);
- return errc::no_such_file_or_directory;
-}
-
-llvm::vfs::detail::DirIterImpl::~DirIterImpl() = default;
-
-namespace {
-
-class OverlayFSDirIterImpl : public llvm::vfs::detail::DirIterImpl {
- OverlayFileSystem &Overlays;
- std::string Path;
- OverlayFileSystem::iterator CurrentFS;
- directory_iterator CurrentDirIter;
- llvm::StringSet<> SeenNames;
-
- std::error_code incrementFS() {
- assert(CurrentFS != Overlays.overlays_end() && "incrementing past end");
- ++CurrentFS;
- for (auto E = Overlays.overlays_end(); CurrentFS != E; ++CurrentFS) {
- std::error_code EC;
- CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
- if (EC && EC != errc::no_such_file_or_directory)
- return EC;
- if (CurrentDirIter != directory_iterator())
- break; // found
- }
- return {};
- }
-
- std::error_code incrementDirIter(bool IsFirstTime) {
- assert((IsFirstTime || CurrentDirIter != directory_iterator()) &&
- "incrementing past end");
- std::error_code EC;
- if (!IsFirstTime)
- CurrentDirIter.increment(EC);
- if (!EC && CurrentDirIter == directory_iterator())
- EC = incrementFS();
- return EC;
- }
-
- std::error_code incrementImpl(bool IsFirstTime) {
- while (true) {
- std::error_code EC = incrementDirIter(IsFirstTime);
- if (EC || CurrentDirIter == directory_iterator()) {
- CurrentEntry = directory_entry();
- return EC;
- }
- CurrentEntry = *CurrentDirIter;
- StringRef Name = llvm::sys::path::filename(CurrentEntry.path());
- if (SeenNames.insert(Name).second)
- return EC; // name not seen before
- }
- llvm_unreachable("returned above");
- }
-
-public:
- OverlayFSDirIterImpl(const Twine &Path, OverlayFileSystem &FS,
- std::error_code &EC)
- : Overlays(FS), Path(Path.str()), CurrentFS(Overlays.overlays_begin()) {
- CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
- EC = incrementImpl(true);
- }
-
- std::error_code increment() override { return incrementImpl(false); }
-};
-
-} // namespace
-
-directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
- std::error_code &EC) {
- return directory_iterator(
- std::make_shared<OverlayFSDirIterImpl>(Dir, *this, EC));
-}
-
-void ProxyFileSystem::anchor() {}
-
-namespace llvm {
-namespace vfs {
-
-namespace detail {
-
-enum InMemoryNodeKind { IME_File, IME_Directory, IME_HardLink };
-
-/// The in memory file system is a tree of Nodes. Every node can either be a
-/// file , hardlink or a directory.
-class InMemoryNode {
- InMemoryNodeKind Kind;
- std::string FileName;
-
-public:
- InMemoryNode(llvm::StringRef FileName, InMemoryNodeKind Kind)
- : Kind(Kind), FileName(llvm::sys::path::filename(FileName)) {}
- virtual ~InMemoryNode() = default;
-
- /// Get the filename of this node (the name without the directory part).
- StringRef getFileName() const { return FileName; }
- InMemoryNodeKind getKind() const { return Kind; }
- virtual std::string toString(unsigned Indent) const = 0;
-};
-
-class InMemoryFile : public InMemoryNode {
- Status Stat;
- std::unique_ptr<llvm::MemoryBuffer> Buffer;
-
-public:
- InMemoryFile(Status Stat, std::unique_ptr<llvm::MemoryBuffer> Buffer)
- : InMemoryNode(Stat.getName(), IME_File), Stat(std::move(Stat)),
- Buffer(std::move(Buffer)) {}
-
- /// Return the \p Status for this node. \p RequestedName should be the name
- /// through which the caller referred to this node. It will override
- /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
- Status getStatus(StringRef RequestedName) const {
- return Status::copyWithNewName(Stat, RequestedName);
- }
- llvm::MemoryBuffer *getBuffer() const { return Buffer.get(); }
-
- std::string toString(unsigned Indent) const override {
- return (std::string(Indent, ' ') + Stat.getName() + "\n").str();
- }
-
- static bool classof(const InMemoryNode *N) {
- return N->getKind() == IME_File;
- }
-};
-
-namespace {
-
-class InMemoryHardLink : public InMemoryNode {
- const InMemoryFile &ResolvedFile;
-
-public:
- InMemoryHardLink(StringRef Path, const InMemoryFile &ResolvedFile)
- : InMemoryNode(Path, IME_HardLink), ResolvedFile(ResolvedFile) {}
- const InMemoryFile &getResolvedFile() const { return ResolvedFile; }
-
- std::string toString(unsigned Indent) const override {
- return std::string(Indent, ' ') + "HardLink to -> " +
- ResolvedFile.toString(0);
- }
-
- static bool classof(const InMemoryNode *N) {
- return N->getKind() == IME_HardLink;
- }
-};
-
-/// Adapt a InMemoryFile for VFS' File interface. The goal is to make
-/// \p InMemoryFileAdaptor mimic as much as possible the behavior of
-/// \p RealFile.
-class InMemoryFileAdaptor : public File {
- const InMemoryFile &Node;
- /// The name to use when returning a Status for this file.
- std::string RequestedName;
-
-public:
- explicit InMemoryFileAdaptor(const InMemoryFile &Node,
- std::string RequestedName)
- : Node(Node), RequestedName(std::move(RequestedName)) {}
-
- llvm::ErrorOr<Status> status() override {
- return Node.getStatus(RequestedName);
- }
-
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
- getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
- bool IsVolatile) override {
- llvm::MemoryBuffer *Buf = Node.getBuffer();
- return llvm::MemoryBuffer::getMemBuffer(
- Buf->getBuffer(), Buf->getBufferIdentifier(), RequiresNullTerminator);
- }
-
- std::error_code close() override { return {}; }
-};
-} // namespace
-
-class InMemoryDirectory : public InMemoryNode {
- Status Stat;
- llvm::StringMap<std::unique_ptr<InMemoryNode>> Entries;
-
-public:
- InMemoryDirectory(Status Stat)
- : InMemoryNode(Stat.getName(), IME_Directory), Stat(std::move(Stat)) {}
-
- /// Return the \p Status for this node. \p RequestedName should be the name
- /// through which the caller referred to this node. It will override
- /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
- Status getStatus(StringRef RequestedName) const {
- return Status::copyWithNewName(Stat, RequestedName);
- }
- InMemoryNode *getChild(StringRef Name) {
- auto I = Entries.find(Name);
- if (I != Entries.end())
- return I->second.get();
- return nullptr;
- }
-
- InMemoryNode *addChild(StringRef Name, std::unique_ptr<InMemoryNode> Child) {
- return Entries.insert(make_pair(Name, std::move(Child)))
- .first->second.get();
- }
-
- using const_iterator = decltype(Entries)::const_iterator;
-
- const_iterator begin() const { return Entries.begin(); }
- const_iterator end() const { return Entries.end(); }
-
- std::string toString(unsigned Indent) const override {
- std::string Result =
- (std::string(Indent, ' ') + Stat.getName() + "\n").str();
- for (const auto &Entry : Entries)
- Result += Entry.second->toString(Indent + 2);
- return Result;
- }
-
- static bool classof(const InMemoryNode *N) {
- return N->getKind() == IME_Directory;
- }
-};
-
-namespace {
-Status getNodeStatus(const InMemoryNode *Node, StringRef RequestedName) {
- if (auto Dir = dyn_cast<detail::InMemoryDirectory>(Node))
- return Dir->getStatus(RequestedName);
- if (auto File = dyn_cast<detail::InMemoryFile>(Node))
- return File->getStatus(RequestedName);
- if (auto Link = dyn_cast<detail::InMemoryHardLink>(Node))
- return Link->getResolvedFile().getStatus(RequestedName);
- llvm_unreachable("Unknown node type");
-}
-} // namespace
-} // namespace detail
-
-InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
- : Root(new detail::InMemoryDirectory(
- Status("", getNextVirtualUniqueID(), llvm::sys::TimePoint<>(), 0, 0,
- 0, llvm::sys::fs::file_type::directory_file,
- llvm::sys::fs::perms::all_all))),
- UseNormalizedPaths(UseNormalizedPaths) {}
-
-InMemoryFileSystem::~InMemoryFileSystem() = default;
-
-std::string InMemoryFileSystem::toString() const {
- return Root->toString(/*Indent=*/0);
-}
-
-bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
- std::unique_ptr<llvm::MemoryBuffer> Buffer,
- Optional<uint32_t> User,
- Optional<uint32_t> Group,
- Optional<llvm::sys::fs::file_type> Type,
- Optional<llvm::sys::fs::perms> Perms,
- const detail::InMemoryFile *HardLinkTarget) {
- SmallString<128> Path;
- P.toVector(Path);
-
- // Fix up relative paths. This just prepends the current working directory.
- std::error_code EC = makeAbsolute(Path);
- assert(!EC);
- (void)EC;
-
- if (useNormalizedPaths())
- llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
-
- if (Path.empty())
- return false;
-
- detail::InMemoryDirectory *Dir = Root.get();
- auto I = llvm::sys::path::begin(Path), E = sys::path::end(Path);
- const auto ResolvedUser = User.getValueOr(0);
- const auto ResolvedGroup = Group.getValueOr(0);
- const auto ResolvedType = Type.getValueOr(sys::fs::file_type::regular_file);
- const auto ResolvedPerms = Perms.getValueOr(sys::fs::all_all);
- assert(!(HardLinkTarget && Buffer) && "HardLink cannot have a buffer");
- // Any intermediate directories we create should be accessible by
- // the owner, even if Perms says otherwise for the final path.
- const auto NewDirectoryPerms = ResolvedPerms | sys::fs::owner_all;
- while (true) {
- StringRef Name = *I;
- detail::InMemoryNode *Node = Dir->getChild(Name);
- ++I;
- if (!Node) {
- if (I == E) {
- // End of the path.
- std::unique_ptr<detail::InMemoryNode> Child;
- if (HardLinkTarget)
- Child.reset(new detail::InMemoryHardLink(P.str(), *HardLinkTarget));
- else {
- // Create a new file or directory.
- Status Stat(P.str(), getNextVirtualUniqueID(),
- llvm::sys::toTimePoint(ModificationTime), ResolvedUser,
- ResolvedGroup, Buffer->getBufferSize(), ResolvedType,
- ResolvedPerms);
- if (ResolvedType == sys::fs::file_type::directory_file) {
- Child.reset(new detail::InMemoryDirectory(std::move(Stat)));
- } else {
- Child.reset(
- new detail::InMemoryFile(std::move(Stat), std::move(Buffer)));
- }
- }
- Dir->addChild(Name, std::move(Child));
- return true;
- }
-
- // Create a new directory. Use the path up to here.
- Status Stat(
- StringRef(Path.str().begin(), Name.end() - Path.str().begin()),
- getNextVirtualUniqueID(), llvm::sys::toTimePoint(ModificationTime),
- ResolvedUser, ResolvedGroup, 0, sys::fs::file_type::directory_file,
- NewDirectoryPerms);
- Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
- Name, llvm::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
- continue;
- }
-
- if (auto *NewDir = dyn_cast<detail::InMemoryDirectory>(Node)) {
- Dir = NewDir;
- } else {
- assert((isa<detail::InMemoryFile>(Node) ||
- isa<detail::InMemoryHardLink>(Node)) &&
- "Must be either file, hardlink or directory!");
-
- // Trying to insert a directory in place of a file.
- if (I != E)
- return false;
-
- // Return false only if the new file is different from the existing one.
- if (auto Link = dyn_cast<detail::InMemoryHardLink>(Node)) {
- return Link->getResolvedFile().getBuffer()->getBuffer() ==
- Buffer->getBuffer();
- }
- return cast<detail::InMemoryFile>(Node)->getBuffer()->getBuffer() ==
- Buffer->getBuffer();
- }
- }
-}
-
-bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
- std::unique_ptr<llvm::MemoryBuffer> Buffer,
- Optional<uint32_t> User,
- Optional<uint32_t> Group,
- Optional<llvm::sys::fs::file_type> Type,
- Optional<llvm::sys::fs::perms> Perms) {
- return addFile(P, ModificationTime, std::move(Buffer), User, Group, Type,
- Perms, /*HardLinkTarget=*/nullptr);
-}
-
-bool InMemoryFileSystem::addFileNoOwn(const Twine &P, time_t ModificationTime,
- llvm::MemoryBuffer *Buffer,
- Optional<uint32_t> User,
- Optional<uint32_t> Group,
- Optional<llvm::sys::fs::file_type> Type,
- Optional<llvm::sys::fs::perms> Perms) {
- return addFile(P, ModificationTime,
- llvm::MemoryBuffer::getMemBuffer(
- Buffer->getBuffer(), Buffer->getBufferIdentifier()),
- std::move(User), std::move(Group), std::move(Type),
- std::move(Perms));
-}
-
-static ErrorOr<const detail::InMemoryNode *>
-lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir,
- const Twine &P) {
- SmallString<128> Path;
- P.toVector(Path);
-
- // Fix up relative paths. This just prepends the current working directory.
- std::error_code EC = FS.makeAbsolute(Path);
- assert(!EC);
- (void)EC;
-
- if (FS.useNormalizedPaths())
- llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
-
- if (Path.empty())
- return Dir;
-
- auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
- while (true) {
- detail::InMemoryNode *Node = Dir->getChild(*I);
- ++I;
- if (!Node)
- return errc::no_such_file_or_directory;
-
- // Return the file if it's at the end of the path.
- if (auto File = dyn_cast<detail::InMemoryFile>(Node)) {
- if (I == E)
- return File;
- return errc::no_such_file_or_directory;
- }
-
- // If Node is HardLink then return the resolved file.
- if (auto File = dyn_cast<detail::InMemoryHardLink>(Node)) {
- if (I == E)
- return &File->getResolvedFile();
- return errc::no_such_file_or_directory;
- }
- // Traverse directories.
- Dir = cast<detail::InMemoryDirectory>(Node);
- if (I == E)
- return Dir;
- }
-}
-
-bool InMemoryFileSystem::addHardLink(const Twine &FromPath,
- const Twine &ToPath) {
- auto FromNode = lookupInMemoryNode(*this, Root.get(), FromPath);
- auto ToNode = lookupInMemoryNode(*this, Root.get(), ToPath);
- // FromPath must not have been added before. ToPath must have been added
- // before. Resolved ToPath must be a File.
- if (!ToNode || FromNode || !isa<detail::InMemoryFile>(*ToNode))
- return false;
- return this->addFile(FromPath, 0, nullptr, None, None, None, None,
- cast<detail::InMemoryFile>(*ToNode));
-}
-
-llvm::ErrorOr<Status> InMemoryFileSystem::status(const Twine &Path) {
- auto Node = lookupInMemoryNode(*this, Root.get(), Path);
- if (Node)
- return detail::getNodeStatus(*Node, Path.str());
- return Node.getError();
-}
-
-llvm::ErrorOr<std::unique_ptr<File>>
-InMemoryFileSystem::openFileForRead(const Twine &Path) {
- auto Node = lookupInMemoryNode(*this, Root.get(), Path);
- if (!Node)
- return Node.getError();
-
- // When we have a file provide a heap-allocated wrapper for the memory buffer
- // to match the ownership semantics for File.
- if (auto *F = dyn_cast<detail::InMemoryFile>(*Node))
- return std::unique_ptr<File>(
- new detail::InMemoryFileAdaptor(*F, Path.str()));
-
- // FIXME: errc::not_a_file?
- return make_error_code(llvm::errc::invalid_argument);
-}
-
-namespace {
-
-/// Adaptor from InMemoryDir::iterator to directory_iterator.
-class InMemoryDirIterator : public llvm::vfs::detail::DirIterImpl {
- detail::InMemoryDirectory::const_iterator I;
- detail::InMemoryDirectory::const_iterator E;
- std::string RequestedDirName;
-
- void setCurrentEntry() {
- if (I != E) {
- SmallString<256> Path(RequestedDirName);
- llvm::sys::path::append(Path, I->second->getFileName());
- sys::fs::file_type Type;
- switch (I->second->getKind()) {
- case detail::IME_File:
- case detail::IME_HardLink:
- Type = sys::fs::file_type::regular_file;
- break;
- case detail::IME_Directory:
- Type = sys::fs::file_type::directory_file;
- break;
- }
- CurrentEntry = directory_entry(Path.str(), Type);
- } else {
- // When we're at the end, make CurrentEntry invalid and DirIterImpl will
- // do the rest.
- CurrentEntry = directory_entry();
- }
- }
-
-public:
- InMemoryDirIterator() = default;
-
- explicit InMemoryDirIterator(const detail::InMemoryDirectory &Dir,
- std::string RequestedDirName)
- : I(Dir.begin()), E(Dir.end()),
- RequestedDirName(std::move(RequestedDirName)) {
- setCurrentEntry();
- }
-
- std::error_code increment() override {
- ++I;
- setCurrentEntry();
- return {};
- }
-};
-
-} // namespace
-
-directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
- std::error_code &EC) {
- auto Node = lookupInMemoryNode(*this, Root.get(), Dir);
- if (!Node) {
- EC = Node.getError();
- return directory_iterator(std::make_shared<InMemoryDirIterator>());
- }
-
- if (auto *DirNode = dyn_cast<detail::InMemoryDirectory>(*Node))
- return directory_iterator(
- std::make_shared<InMemoryDirIterator>(*DirNode, Dir.str()));
-
- EC = make_error_code(llvm::errc::not_a_directory);
- return directory_iterator(std::make_shared<InMemoryDirIterator>());
-}
-
-std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) {
- SmallString<128> Path;
- P.toVector(Path);
-
- // Fix up relative paths. This just prepends the current working directory.
- std::error_code EC = makeAbsolute(Path);
- assert(!EC);
- (void)EC;
-
- if (useNormalizedPaths())
- llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
-
- if (!Path.empty())
- WorkingDirectory = Path.str();
- return {};
-}
-
-std::error_code
-InMemoryFileSystem::getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const {
- auto CWD = getCurrentWorkingDirectory();
- if (!CWD || CWD->empty())
- return errc::operation_not_permitted;
- Path.toVector(Output);
- if (auto EC = makeAbsolute(Output))
- return EC;
- llvm::sys::path::remove_dots(Output, /*remove_dot_dot=*/true);
- return {};
-}
-
-std::error_code InMemoryFileSystem::isLocal(const Twine &Path, bool &Result) {
- Result = false;
- return {};
-}
-
-} // namespace vfs
-} // namespace llvm
-
-//===-----------------------------------------------------------------------===/
-// RedirectingFileSystem implementation
-//===-----------------------------------------------------------------------===/
-
-// FIXME: reuse implementation common with OverlayFSDirIterImpl as these
-// iterators are conceptually similar.
-class llvm::vfs::VFSFromYamlDirIterImpl
- : public llvm::vfs::detail::DirIterImpl {
- std::string Dir;
- RedirectingFileSystem::RedirectingDirectoryEntry::iterator Current, End;
-
- // To handle 'fallthrough' mode we need to iterate at first through
- // RedirectingDirectoryEntry and then through ExternalFS. These operations are
- // done sequentially, we just need to keep a track of what kind of iteration
- // we are currently performing.
-
- /// Flag telling if we should iterate through ExternalFS or stop at the last
- /// RedirectingDirectoryEntry::iterator.
- bool IterateExternalFS;
- /// Flag telling if we have switched to iterating through ExternalFS.
- bool IsExternalFSCurrent = false;
- FileSystem &ExternalFS;
- directory_iterator ExternalDirIter;
- llvm::StringSet<> SeenNames;
-
- /// To combine multiple iterations, different methods are responsible for
- /// different iteration steps.
- /// @{
-
- /// Responsible for dispatching between RedirectingDirectoryEntry iteration
- /// and ExternalFS iteration.
- std::error_code incrementImpl(bool IsFirstTime);
- /// Responsible for RedirectingDirectoryEntry iteration.
- std::error_code incrementContent(bool IsFirstTime);
- /// Responsible for ExternalFS iteration.
- std::error_code incrementExternal();
- /// @}
-
-public:
- VFSFromYamlDirIterImpl(
- const Twine &Path,
- RedirectingFileSystem::RedirectingDirectoryEntry::iterator Begin,
- RedirectingFileSystem::RedirectingDirectoryEntry::iterator End,
- bool IterateExternalFS, FileSystem &ExternalFS, std::error_code &EC);
-
- std::error_code increment() override;
-};
-
-llvm::ErrorOr<std::string>
-RedirectingFileSystem::getCurrentWorkingDirectory() const {
- return ExternalFS->getCurrentWorkingDirectory();
-}
-
-std::error_code
-RedirectingFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
- return ExternalFS->setCurrentWorkingDirectory(Path);
-}
-
-std::error_code RedirectingFileSystem::isLocal(const Twine &Path,
- bool &Result) {
- return ExternalFS->isLocal(Path, Result);
-}
-
-directory_iterator RedirectingFileSystem::dir_begin(const Twine &Dir,
- std::error_code &EC) {
- ErrorOr<RedirectingFileSystem::Entry *> E = lookupPath(Dir);
- if (!E) {
- EC = E.getError();
- if (IsFallthrough && EC == errc::no_such_file_or_directory)
- return ExternalFS->dir_begin(Dir, EC);
- return {};
- }
- ErrorOr<Status> S = status(Dir, *E);
- if (!S) {
- EC = S.getError();
- return {};
- }
- if (!S->isDirectory()) {
- EC = std::error_code(static_cast<int>(errc::not_a_directory),
- std::system_category());
- return {};
- }
-
- auto *D = cast<RedirectingFileSystem::RedirectingDirectoryEntry>(*E);
- return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(
- Dir, D->contents_begin(), D->contents_end(),
- /*IterateExternalFS=*/IsFallthrough, *ExternalFS, EC));
-}
-
-void RedirectingFileSystem::setExternalContentsPrefixDir(StringRef PrefixDir) {
- ExternalContentsPrefixDir = PrefixDir.str();
-}
-
-StringRef RedirectingFileSystem::getExternalContentsPrefixDir() const {
- return ExternalContentsPrefixDir;
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void RedirectingFileSystem::dump() const {
- for (const auto &Root : Roots)
- dumpEntry(Root.get());
-}
-
-LLVM_DUMP_METHOD void
-RedirectingFileSystem::dumpEntry(RedirectingFileSystem::Entry *E,
- int NumSpaces) const {
- StringRef Name = E->getName();
- for (int i = 0, e = NumSpaces; i < e; ++i)
- dbgs() << " ";
- dbgs() << "'" << Name.str().c_str() << "'"
- << "\n";
-
- if (E->getKind() == RedirectingFileSystem::EK_Directory) {
- auto *DE = dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(E);
- assert(DE && "Should be a directory");
-
- for (std::unique_ptr<Entry> &SubEntry :
- llvm::make_range(DE->contents_begin(), DE->contents_end()))
- dumpEntry(SubEntry.get(), NumSpaces + 2);
- }
-}
-#endif
-
-/// A helper class to hold the common YAML parsing state.
-class llvm::vfs::RedirectingFileSystemParser {
- yaml::Stream &Stream;
-
- void error(yaml::Node *N, const Twine &Msg) { Stream.printError(N, Msg); }
-
- // false on error
- bool parseScalarString(yaml::Node *N, StringRef &Result,
- SmallVectorImpl<char> &Storage) {
- const auto *S = dyn_cast<yaml::ScalarNode>(N);
-
- if (!S) {
- error(N, "expected string");
- return false;
- }
- Result = S->getValue(Storage);
- return true;
- }
-
- // false on error
- bool parseScalarBool(yaml::Node *N, bool &Result) {
- SmallString<5> Storage;
- StringRef Value;
- if (!parseScalarString(N, Value, Storage))
- return false;
-
- if (Value.equals_lower("true") || Value.equals_lower("on") ||
- Value.equals_lower("yes") || Value == "1") {
- Result = true;
- return true;
- } else if (Value.equals_lower("false") || Value.equals_lower("off") ||
- Value.equals_lower("no") || Value == "0") {
- Result = false;
- return true;
- }
-
- error(N, "expected boolean value");
- return false;
- }
-
- struct KeyStatus {
- bool Required;
- bool Seen = false;
-
- KeyStatus(bool Required = false) : Required(Required) {}
- };
-
- using KeyStatusPair = std::pair<StringRef, KeyStatus>;
-
- // false on error
- bool checkDuplicateOrUnknownKey(yaml::Node *KeyNode, StringRef Key,
- DenseMap<StringRef, KeyStatus> &Keys) {
- if (!Keys.count(Key)) {
- error(KeyNode, "unknown key");
- return false;
- }
- KeyStatus &S = Keys[Key];
- if (S.Seen) {
- error(KeyNode, Twine("duplicate key '") + Key + "'");
- return false;
- }
- S.Seen = true;
- return true;
- }
-
- // false on error
- bool checkMissingKeys(yaml::Node *Obj, DenseMap<StringRef, KeyStatus> &Keys) {
- for (const auto &I : Keys) {
- if (I.second.Required && !I.second.Seen) {
- error(Obj, Twine("missing key '") + I.first + "'");
- return false;
- }
- }
- return true;
- }
-
- RedirectingFileSystem::Entry *
- lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name,
- RedirectingFileSystem::Entry *ParentEntry = nullptr) {
- if (!ParentEntry) { // Look for a existent root
- for (const auto &Root : FS->Roots) {
- if (Name.equals(Root->getName())) {
- ParentEntry = Root.get();
- return ParentEntry;
- }
- }
- } else { // Advance to the next component
- auto *DE = dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(
- ParentEntry);
- for (std::unique_ptr<RedirectingFileSystem::Entry> &Content :
- llvm::make_range(DE->contents_begin(), DE->contents_end())) {
- auto *DirContent =
- dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(
- Content.get());
- if (DirContent && Name.equals(Content->getName()))
- return DirContent;
- }
- }
-
- // ... or create a new one
- std::unique_ptr<RedirectingFileSystem::Entry> E =
- llvm::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
- Name, Status("", getNextVirtualUniqueID(),
- std::chrono::system_clock::now(), 0, 0, 0,
- file_type::directory_file, sys::fs::all_all));
-
- if (!ParentEntry) { // Add a new root to the overlay
- FS->Roots.push_back(std::move(E));
- ParentEntry = FS->Roots.back().get();
- return ParentEntry;
- }
-
- auto *DE =
- dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(ParentEntry);
- DE->addContent(std::move(E));
- return DE->getLastContent();
- }
-
- void uniqueOverlayTree(RedirectingFileSystem *FS,
- RedirectingFileSystem::Entry *SrcE,
- RedirectingFileSystem::Entry *NewParentE = nullptr) {
- StringRef Name = SrcE->getName();
- switch (SrcE->getKind()) {
- case RedirectingFileSystem::EK_Directory: {
- auto *DE =
- dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(SrcE);
- assert(DE && "Must be a directory");
- // Empty directories could be present in the YAML as a way to
- // describe a file for a current directory after some of its subdir
- // is parsed. This only leads to redundant walks, ignore it.
- if (!Name.empty())
- NewParentE = lookupOrCreateEntry(FS, Name, NewParentE);
- for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
- llvm::make_range(DE->contents_begin(), DE->contents_end()))
- uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
- break;
- }
- case RedirectingFileSystem::EK_File: {
- auto *FE = dyn_cast<RedirectingFileSystem::RedirectingFileEntry>(SrcE);
- assert(FE && "Must be a file");
- assert(NewParentE && "Parent entry must exist");
- auto *DE = dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(
- NewParentE);
- DE->addContent(
- llvm::make_unique<RedirectingFileSystem::RedirectingFileEntry>(
- Name, FE->getExternalContentsPath(), FE->getUseName()));
- break;
- }
- }
- }
-
- std::unique_ptr<RedirectingFileSystem::Entry>
- parseEntry(yaml::Node *N, RedirectingFileSystem *FS, bool IsRootEntry) {
- auto *M = dyn_cast<yaml::MappingNode>(N);
- if (!M) {
- error(N, "expected mapping node for file or directory entry");
- return nullptr;
- }
-
- KeyStatusPair Fields[] = {
- KeyStatusPair("name", true),
- KeyStatusPair("type", true),
- KeyStatusPair("contents", false),
- KeyStatusPair("external-contents", false),
- KeyStatusPair("use-external-name", false),
- };
-
- DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
-
- bool HasContents = false; // external or otherwise
- std::vector<std::unique_ptr<RedirectingFileSystem::Entry>>
- EntryArrayContents;
- std::string ExternalContentsPath;
- std::string Name;
- yaml::Node *NameValueNode;
- auto UseExternalName =
- RedirectingFileSystem::RedirectingFileEntry::NK_NotSet;
- RedirectingFileSystem::EntryKind Kind;
-
- for (auto &I : *M) {
- StringRef Key;
- // Reuse the buffer for key and value, since we don't look at key after
- // parsing value.
- SmallString<256> Buffer;
- if (!parseScalarString(I.getKey(), Key, Buffer))
- return nullptr;
-
- if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
- return nullptr;
-
- StringRef Value;
- if (Key == "name") {
- if (!parseScalarString(I.getValue(), Value, Buffer))
- return nullptr;
-
- NameValueNode = I.getValue();
- if (FS->UseCanonicalizedPaths) {
- SmallString<256> Path(Value);
- // Guarantee that old YAML files containing paths with ".." and "."
- // are properly canonicalized before read into the VFS.
- Path = sys::path::remove_leading_dotslash(Path);
- sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
- Name = Path.str();
- } else {
- Name = Value;
- }
- } else if (Key == "type") {
- if (!parseScalarString(I.getValue(), Value, Buffer))
- return nullptr;
- if (Value == "file")
- Kind = RedirectingFileSystem::EK_File;
- else if (Value == "directory")
- Kind = RedirectingFileSystem::EK_Directory;
- else {
- error(I.getValue(), "unknown value for 'type'");
- return nullptr;
- }
- } else if (Key == "contents") {
- if (HasContents) {
- error(I.getKey(),
- "entry already has 'contents' or 'external-contents'");
- return nullptr;
- }
- HasContents = true;
- auto *Contents = dyn_cast<yaml::SequenceNode>(I.getValue());
- if (!Contents) {
- // FIXME: this is only for directories, what about files?
- error(I.getValue(), "expected array");
- return nullptr;
- }
-
- for (auto &I : *Contents) {
- if (std::unique_ptr<RedirectingFileSystem::Entry> E =
- parseEntry(&I, FS, /*IsRootEntry*/ false))
- EntryArrayContents.push_back(std::move(E));
- else
- return nullptr;
- }
- } else if (Key == "external-contents") {
- if (HasContents) {
- error(I.getKey(),
- "entry already has 'contents' or 'external-contents'");
- return nullptr;
- }
- HasContents = true;
- if (!parseScalarString(I.getValue(), Value, Buffer))
- return nullptr;
-
- SmallString<256> FullPath;
- if (FS->IsRelativeOverlay) {
- FullPath = FS->getExternalContentsPrefixDir();
- assert(!FullPath.empty() &&
- "External contents prefix directory must exist");
- llvm::sys::path::append(FullPath, Value);
- } else {
- FullPath = Value;
- }
-
- if (FS->UseCanonicalizedPaths) {
- // Guarantee that old YAML files containing paths with ".." and "."
- // are properly canonicalized before read into the VFS.
- FullPath = sys::path::remove_leading_dotslash(FullPath);
- sys::path::remove_dots(FullPath, /*remove_dot_dot=*/true);
- }
- ExternalContentsPath = FullPath.str();
- } else if (Key == "use-external-name") {
- bool Val;
- if (!parseScalarBool(I.getValue(), Val))
- return nullptr;
- UseExternalName =
- Val ? RedirectingFileSystem::RedirectingFileEntry::NK_External
- : RedirectingFileSystem::RedirectingFileEntry::NK_Virtual;
- } else {
- llvm_unreachable("key missing from Keys");
- }
- }
-
- if (Stream.failed())
- return nullptr;
-
- // check for missing keys
- if (!HasContents) {
- error(N, "missing key 'contents' or 'external-contents'");
- return nullptr;
- }
- if (!checkMissingKeys(N, Keys))
- return nullptr;
-
- // check invalid configuration
- if (Kind == RedirectingFileSystem::EK_Directory &&
- UseExternalName !=
- RedirectingFileSystem::RedirectingFileEntry::NK_NotSet) {
- error(N, "'use-external-name' is not supported for directories");
- return nullptr;
- }
-
- if (IsRootEntry && !sys::path::is_absolute(Name)) {
- assert(NameValueNode && "Name presence should be checked earlier");
- error(NameValueNode,
- "entry with relative path at the root level is not discoverable");
- return nullptr;
- }
-
- // Remove trailing slash(es), being careful not to remove the root path
- StringRef Trimmed(Name);
- size_t RootPathLen = sys::path::root_path(Trimmed).size();
- while (Trimmed.size() > RootPathLen &&
- sys::path::is_separator(Trimmed.back()))
- Trimmed = Trimmed.slice(0, Trimmed.size() - 1);
- // Get the last component
- StringRef LastComponent = sys::path::filename(Trimmed);
-
- std::unique_ptr<RedirectingFileSystem::Entry> Result;
- switch (Kind) {
- case RedirectingFileSystem::EK_File:
- Result = llvm::make_unique<RedirectingFileSystem::RedirectingFileEntry>(
- LastComponent, std::move(ExternalContentsPath), UseExternalName);
- break;
- case RedirectingFileSystem::EK_Directory:
- Result =
- llvm::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
- LastComponent, std::move(EntryArrayContents),
- Status("", getNextVirtualUniqueID(),
- std::chrono::system_clock::now(), 0, 0, 0,
- file_type::directory_file, sys::fs::all_all));
- break;
- }
-
- StringRef Parent = sys::path::parent_path(Trimmed);
- if (Parent.empty())
- return Result;
-
- // if 'name' contains multiple components, create implicit directory entries
- for (sys::path::reverse_iterator I = sys::path::rbegin(Parent),
- E = sys::path::rend(Parent);
- I != E; ++I) {
- std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> Entries;
- Entries.push_back(std::move(Result));
- Result =
- llvm::make_unique<RedirectingFileSystem::RedirectingDirectoryEntry>(
- *I, std::move(Entries),
- Status("", getNextVirtualUniqueID(),
- std::chrono::system_clock::now(), 0, 0, 0,
- file_type::directory_file, sys::fs::all_all));
- }
- return Result;
- }
-
-public:
- RedirectingFileSystemParser(yaml::Stream &S) : Stream(S) {}
-
- // false on error
- bool parse(yaml::Node *Root, RedirectingFileSystem *FS) {
- auto *Top = dyn_cast<yaml::MappingNode>(Root);
- if (!Top) {
- error(Root, "expected mapping node");
- return false;
- }
-
- KeyStatusPair Fields[] = {
- KeyStatusPair("version", true),
- KeyStatusPair("case-sensitive", false),
- KeyStatusPair("use-external-names", false),
- KeyStatusPair("overlay-relative", false),
- KeyStatusPair("fallthrough", false),
- KeyStatusPair("roots", true),
- };
-
- DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
- std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> RootEntries;
-
- // Parse configuration and 'roots'
- for (auto &I : *Top) {
- SmallString<10> KeyBuffer;
- StringRef Key;
- if (!parseScalarString(I.getKey(), Key, KeyBuffer))
- return false;
-
- if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
- return false;
-
- if (Key == "roots") {
- auto *Roots = dyn_cast<yaml::SequenceNode>(I.getValue());
- if (!Roots) {
- error(I.getValue(), "expected array");
- return false;
- }
-
- for (auto &I : *Roots) {
- if (std::unique_ptr<RedirectingFileSystem::Entry> E =
- parseEntry(&I, FS, /*IsRootEntry*/ true))
- RootEntries.push_back(std::move(E));
- else
- return false;
- }
- } else if (Key == "version") {
- StringRef VersionString;
- SmallString<4> Storage;
- if (!parseScalarString(I.getValue(), VersionString, Storage))
- return false;
- int Version;
- if (VersionString.getAsInteger<int>(10, Version)) {
- error(I.getValue(), "expected integer");
- return false;
- }
- if (Version < 0) {
- error(I.getValue(), "invalid version number");
- return false;
- }
- if (Version != 0) {
- error(I.getValue(), "version mismatch, expected 0");
- return false;
- }
- } else if (Key == "case-sensitive") {
- if (!parseScalarBool(I.getValue(), FS->CaseSensitive))
- return false;
- } else if (Key == "overlay-relative") {
- if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))
- return false;
- } else if (Key == "use-external-names") {
- if (!parseScalarBool(I.getValue(), FS->UseExternalNames))
- return false;
- } else if (Key == "fallthrough") {
- if (!parseScalarBool(I.getValue(), FS->IsFallthrough))
- return false;
- } else {
- llvm_unreachable("key missing from Keys");
- }
- }
-
- if (Stream.failed())
- return false;
-
- if (!checkMissingKeys(Top, Keys))
- return false;
-
- // Now that we sucessefully parsed the YAML file, canonicalize the internal
- // representation to a proper directory tree so that we can search faster
- // inside the VFS.
- for (auto &E : RootEntries)
- uniqueOverlayTree(FS, E.get());
-
- return true;
- }
-};
-
-RedirectingFileSystem *
-RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
- SourceMgr::DiagHandlerTy DiagHandler,
- StringRef YAMLFilePath, void *DiagContext,
- IntrusiveRefCntPtr<FileSystem> ExternalFS) {
- SourceMgr SM;
- yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
-
- SM.setDiagHandler(DiagHandler, DiagContext);
- yaml::document_iterator DI = Stream.begin();
- yaml::Node *Root = DI->getRoot();
- if (DI == Stream.end() || !Root) {
- SM.PrintMessage(SMLoc(), SourceMgr::DK_Error, "expected root node");
- return nullptr;
- }
-
- RedirectingFileSystemParser P(Stream);
-
- std::unique_ptr<RedirectingFileSystem> FS(
- new RedirectingFileSystem(std::move(ExternalFS)));
-
- if (!YAMLFilePath.empty()) {
- // Use the YAML path from -ivfsoverlay to compute the dir to be prefixed
- // to each 'external-contents' path.
- //
- // Example:
- // -ivfsoverlay dummy.cache/vfs/vfs.yaml
- // yields:
- // FS->ExternalContentsPrefixDir => /<absolute_path_to>/dummy.cache/vfs
- //
- SmallString<256> OverlayAbsDir = sys::path::parent_path(YAMLFilePath);
- std::error_code EC = llvm::sys::fs::make_absolute(OverlayAbsDir);
- assert(!EC && "Overlay dir final path must be absolute");
- (void)EC;
- FS->setExternalContentsPrefixDir(OverlayAbsDir);
- }
-
- if (!P.parse(Root, FS.get()))
- return nullptr;
-
- return FS.release();
-}
-
-ErrorOr<RedirectingFileSystem::Entry *>
-RedirectingFileSystem::lookupPath(const Twine &Path_) const {
- SmallString<256> Path;
- Path_.toVector(Path);
-
- // Handle relative paths
- if (std::error_code EC = makeAbsolute(Path))
- return EC;
-
- // Canonicalize path by removing ".", "..", "./", etc components. This is
- // a VFS request, do bot bother about symlinks in the path components
- // but canonicalize in order to perform the correct entry search.
- if (UseCanonicalizedPaths) {
- Path = sys::path::remove_leading_dotslash(Path);
- sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
- }
-
- if (Path.empty())
- return make_error_code(llvm::errc::invalid_argument);
-
- sys::path::const_iterator Start = sys::path::begin(Path);
- sys::path::const_iterator End = sys::path::end(Path);
- for (const auto &Root : Roots) {
- ErrorOr<RedirectingFileSystem::Entry *> Result =
- lookupPath(Start, End, Root.get());
- if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
- return Result;
- }
- return make_error_code(llvm::errc::no_such_file_or_directory);
-}
-
-ErrorOr<RedirectingFileSystem::Entry *>
-RedirectingFileSystem::lookupPath(sys::path::const_iterator Start,
- sys::path::const_iterator End,
- RedirectingFileSystem::Entry *From) const {
-#ifndef _WIN32
- assert(!isTraversalComponent(*Start) &&
- !isTraversalComponent(From->getName()) &&
- "Paths should not contain traversal components");
-#else
- // FIXME: this is here to support windows, remove it once canonicalized
- // paths become globally default.
- if (Start->equals("."))
- ++Start;
-#endif
-
- StringRef FromName = From->getName();
-
- // Forward the search to the next component in case this is an empty one.
- if (!FromName.empty()) {
- if (CaseSensitive ? !Start->equals(FromName)
- : !Start->equals_lower(FromName))
- // failure to match
- return make_error_code(llvm::errc::no_such_file_or_directory);
-
- ++Start;
-
- if (Start == End) {
- // Match!
- return From;
- }
- }
-
- auto *DE = dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(From);
- if (!DE)
- return make_error_code(llvm::errc::not_a_directory);
-
- for (const std::unique_ptr<RedirectingFileSystem::Entry> &DirEntry :
- llvm::make_range(DE->contents_begin(), DE->contents_end())) {
- ErrorOr<RedirectingFileSystem::Entry *> Result =
- lookupPath(Start, End, DirEntry.get());
- if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
- return Result;
- }
- return make_error_code(llvm::errc::no_such_file_or_directory);
-}
-
-static Status getRedirectedFileStatus(const Twine &Path, bool UseExternalNames,
- Status ExternalStatus) {
- Status S = ExternalStatus;
- if (!UseExternalNames)
- S = Status::copyWithNewName(S, Path.str());
- S.IsVFSMapped = true;
- return S;
-}
-
-ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path,
- RedirectingFileSystem::Entry *E) {
- assert(E != nullptr);
- if (auto *F = dyn_cast<RedirectingFileSystem::RedirectingFileEntry>(E)) {
- ErrorOr<Status> S = ExternalFS->status(F->getExternalContentsPath());
- assert(!S || S->getName() == F->getExternalContentsPath());
- if (S)
- return getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
- *S);
- return S;
- } else { // directory
- auto *DE = cast<RedirectingFileSystem::RedirectingDirectoryEntry>(E);
- return Status::copyWithNewName(DE->getStatus(), Path.str());
- }
-}
-
-ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path) {
- ErrorOr<RedirectingFileSystem::Entry *> Result = lookupPath(Path);
- if (!Result) {
- if (IsFallthrough &&
- Result.getError() == llvm::errc::no_such_file_or_directory) {
- return ExternalFS->status(Path);
- }
- return Result.getError();
- }
- return status(Path, *Result);
-}
-
-namespace {
-
-/// Provide a file wrapper with an overriden status.
-class FileWithFixedStatus : public File {
- std::unique_ptr<File> InnerFile;
- Status S;
-
-public:
- FileWithFixedStatus(std::unique_ptr<File> InnerFile, Status S)
- : InnerFile(std::move(InnerFile)), S(std::move(S)) {}
-
- ErrorOr<Status> status() override { return S; }
- ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
-
- getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
- bool IsVolatile) override {
- return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
- IsVolatile);
- }
-
- std::error_code close() override { return InnerFile->close(); }
-};
-
-} // namespace
-
-ErrorOr<std::unique_ptr<File>>
-RedirectingFileSystem::openFileForRead(const Twine &Path) {
- ErrorOr<RedirectingFileSystem::Entry *> E = lookupPath(Path);
- if (!E) {
- if (IsFallthrough &&
- E.getError() == llvm::errc::no_such_file_or_directory) {
- return ExternalFS->openFileForRead(Path);
- }
- return E.getError();
- }
-
- auto *F = dyn_cast<RedirectingFileSystem::RedirectingFileEntry>(*E);
- if (!F) // FIXME: errc::not_a_file?
- return make_error_code(llvm::errc::invalid_argument);
-
- auto Result = ExternalFS->openFileForRead(F->getExternalContentsPath());
- if (!Result)
- return Result;
-
- auto ExternalStatus = (*Result)->status();
- if (!ExternalStatus)
- return ExternalStatus.getError();
-
- // FIXME: Update the status with the name and VFSMapped.
- Status S = getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
- *ExternalStatus);
- return std::unique_ptr<File>(
- llvm::make_unique<FileWithFixedStatus>(std::move(*Result), S));
-}
-
-std::error_code
-RedirectingFileSystem::getRealPath(const Twine &Path,
- SmallVectorImpl<char> &Output) const {
- ErrorOr<RedirectingFileSystem::Entry *> Result = lookupPath(Path);
- if (!Result) {
- if (IsFallthrough &&
- Result.getError() == llvm::errc::no_such_file_or_directory) {
- return ExternalFS->getRealPath(Path, Output);
- }
- return Result.getError();
- }
-
- if (auto *F =
- dyn_cast<RedirectingFileSystem::RedirectingFileEntry>(*Result)) {
- return ExternalFS->getRealPath(F->getExternalContentsPath(), Output);
- }
- // Even if there is a directory entry, fall back to ExternalFS if allowed,
- // because directories don't have a single external contents path.
- return IsFallthrough ? ExternalFS->getRealPath(Path, Output)
- : llvm::errc::invalid_argument;
-}
-
-IntrusiveRefCntPtr<FileSystem>
-vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
- SourceMgr::DiagHandlerTy DiagHandler,
- StringRef YAMLFilePath, void *DiagContext,
- IntrusiveRefCntPtr<FileSystem> ExternalFS) {
- return RedirectingFileSystem::create(std::move(Buffer), DiagHandler,
- YAMLFilePath, DiagContext,
- std::move(ExternalFS));
-}
-
-static void getVFSEntries(RedirectingFileSystem::Entry *SrcE,
- SmallVectorImpl<StringRef> &Path,
- SmallVectorImpl<YAMLVFSEntry> &Entries) {
- auto Kind = SrcE->getKind();
- if (Kind == RedirectingFileSystem::EK_Directory) {
- auto *DE = dyn_cast<RedirectingFileSystem::RedirectingDirectoryEntry>(SrcE);
- assert(DE && "Must be a directory");
- for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
- llvm::make_range(DE->contents_begin(), DE->contents_end())) {
- Path.push_back(SubEntry->getName());
- getVFSEntries(SubEntry.get(), Path, Entries);
- Path.pop_back();
- }
- return;
- }
-
- assert(Kind == RedirectingFileSystem::EK_File && "Must be a EK_File");
- auto *FE = dyn_cast<RedirectingFileSystem::RedirectingFileEntry>(SrcE);
- assert(FE && "Must be a file");
- SmallString<128> VPath;
- for (auto &Comp : Path)
- llvm::sys::path::append(VPath, Comp);
- Entries.push_back(YAMLVFSEntry(VPath.c_str(), FE->getExternalContentsPath()));
-}
-
-void vfs::collectVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
- SourceMgr::DiagHandlerTy DiagHandler,
- StringRef YAMLFilePath,
- SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
- void *DiagContext,
- IntrusiveRefCntPtr<FileSystem> ExternalFS) {
- RedirectingFileSystem *VFS = RedirectingFileSystem::create(
- std::move(Buffer), DiagHandler, YAMLFilePath, DiagContext,
- std::move(ExternalFS));
- ErrorOr<RedirectingFileSystem::Entry *> RootE = VFS->lookupPath("/");
- if (!RootE)
- return;
- SmallVector<StringRef, 8> Components;
- Components.push_back("/");
- getVFSEntries(*RootE, Components, CollectedEntries);
-}
-
-UniqueID vfs::getNextVirtualUniqueID() {
- static std::atomic<unsigned> UID;
- unsigned ID = ++UID;
- // The following assumes that uint64_t max will never collide with a real
- // dev_t value from the OS.
- return UniqueID(std::numeric_limits<uint64_t>::max(), ID);
-}
-
-void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) {
- assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute");
- assert(sys::path::is_absolute(RealPath) && "real path not absolute");
- assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported");
- Mappings.emplace_back(VirtualPath, RealPath);
-}
-
-namespace {
-
-class JSONWriter {
- llvm::raw_ostream &OS;
- SmallVector<StringRef, 16> DirStack;
-
- unsigned getDirIndent() { return 4 * DirStack.size(); }
- unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
- bool containedIn(StringRef Parent, StringRef Path);
- StringRef containedPart(StringRef Parent, StringRef Path);
- void startDirectory(StringRef Path);
- void endDirectory();
- void writeEntry(StringRef VPath, StringRef RPath);
-
-public:
- JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}
-
- void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,
- Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative,
- StringRef OverlayDir);
-};
-
-} // namespace
-
-bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {
- using namespace llvm::sys;
-
- // Compare each path component.
- auto IParent = path::begin(Parent), EParent = path::end(Parent);
- for (auto IChild = path::begin(Path), EChild = path::end(Path);
- IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
- if (*IParent != *IChild)
- return false;
- }
- // Have we exhausted the parent path?
- return IParent == EParent;
-}
-
-StringRef JSONWriter::containedPart(StringRef Parent, StringRef Path) {
- assert(!Parent.empty());
- assert(containedIn(Parent, Path));
- return Path.slice(Parent.size() + 1, StringRef::npos);
-}
-
-void JSONWriter::startDirectory(StringRef Path) {
- StringRef Name =
- DirStack.empty() ? Path : containedPart(DirStack.back(), Path);
- DirStack.push_back(Path);
- unsigned Indent = getDirIndent();
- OS.indent(Indent) << "{\n";
- OS.indent(Indent + 2) << "'type': 'directory',\n";
- OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(Name) << "\",\n";
- OS.indent(Indent + 2) << "'contents': [\n";
-}
-
-void JSONWriter::endDirectory() {
- unsigned Indent = getDirIndent();
- OS.indent(Indent + 2) << "]\n";
- OS.indent(Indent) << "}";
-
- DirStack.pop_back();
-}
-
-void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) {
- unsigned Indent = getFileIndent();
- OS.indent(Indent) << "{\n";
- OS.indent(Indent + 2) << "'type': 'file',\n";
- OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(VPath) << "\",\n";
- OS.indent(Indent + 2) << "'external-contents': \""
- << llvm::yaml::escape(RPath) << "\"\n";
- OS.indent(Indent) << "}";
-}
-
-void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
- Optional<bool> UseExternalNames,
- Optional<bool> IsCaseSensitive,
- Optional<bool> IsOverlayRelative,
- StringRef OverlayDir) {
- using namespace llvm::sys;
-
- OS << "{\n"
- " 'version': 0,\n";
- if (IsCaseSensitive.hasValue())
- OS << " 'case-sensitive': '"
- << (IsCaseSensitive.getValue() ? "true" : "false") << "',\n";
- if (UseExternalNames.hasValue())
- OS << " 'use-external-names': '"
- << (UseExternalNames.getValue() ? "true" : "false") << "',\n";
- bool UseOverlayRelative = false;
- if (IsOverlayRelative.hasValue()) {
- UseOverlayRelative = IsOverlayRelative.getValue();
- OS << " 'overlay-relative': '" << (UseOverlayRelative ? "true" : "false")
- << "',\n";
- }
- OS << " 'roots': [\n";
-
- if (!Entries.empty()) {
- const YAMLVFSEntry &Entry = Entries.front();
- startDirectory(path::parent_path(Entry.VPath));
-
- StringRef RPath = Entry.RPath;
- if (UseOverlayRelative) {
- unsigned OverlayDirLen = OverlayDir.size();
- assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
- "Overlay dir must be contained in RPath");
- RPath = RPath.slice(OverlayDirLen, RPath.size());
- }
-
- writeEntry(path::filename(Entry.VPath), RPath);
-
- for (const auto &Entry : Entries.slice(1)) {
- StringRef Dir = path::parent_path(Entry.VPath);
- if (Dir == DirStack.back())
- OS << ",\n";
- else {
- while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {
- OS << "\n";
- endDirectory();
- }
- OS << ",\n";
- startDirectory(Dir);
- }
- StringRef RPath = Entry.RPath;
- if (UseOverlayRelative) {
- unsigned OverlayDirLen = OverlayDir.size();
- assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
- "Overlay dir must be contained in RPath");
- RPath = RPath.slice(OverlayDirLen, RPath.size());
- }
- writeEntry(path::filename(Entry.VPath), RPath);
- }
-
- while (!DirStack.empty()) {
- OS << "\n";
- endDirectory();
- }
- OS << "\n";
- }
-
- OS << " ]\n"
- << "}\n";
-}
-
-void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
- llvm::sort(Mappings, [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
- return LHS.VPath < RHS.VPath;
- });
-
- JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
- IsOverlayRelative, OverlayDir);
-}
-
-VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(
- const Twine &_Path,
- RedirectingFileSystem::RedirectingDirectoryEntry::iterator Begin,
- RedirectingFileSystem::RedirectingDirectoryEntry::iterator End,
- bool IterateExternalFS, FileSystem &ExternalFS, std::error_code &EC)
- : Dir(_Path.str()), Current(Begin), End(End),
- IterateExternalFS(IterateExternalFS), ExternalFS(ExternalFS) {
- EC = incrementImpl(/*IsFirstTime=*/true);
-}
-
-std::error_code VFSFromYamlDirIterImpl::increment() {
- return incrementImpl(/*IsFirstTime=*/false);
-}
-
-std::error_code VFSFromYamlDirIterImpl::incrementExternal() {
- assert(!(IsExternalFSCurrent && ExternalDirIter == directory_iterator()) &&
- "incrementing past end");
- std::error_code EC;
- if (IsExternalFSCurrent) {
- ExternalDirIter.increment(EC);
- } else if (IterateExternalFS) {
- ExternalDirIter = ExternalFS.dir_begin(Dir, EC);
- IsExternalFSCurrent = true;
- if (EC && EC != errc::no_such_file_or_directory)
- return EC;
- EC = {};
- }
- if (EC || ExternalDirIter == directory_iterator()) {
- CurrentEntry = directory_entry();
- } else {
- CurrentEntry = *ExternalDirIter;
- }
- return EC;
-}
-
-std::error_code VFSFromYamlDirIterImpl::incrementContent(bool IsFirstTime) {
- assert((IsFirstTime || Current != End) && "cannot iterate past end");
- if (!IsFirstTime)
- ++Current;
- while (Current != End) {
- SmallString<128> PathStr(Dir);
- llvm::sys::path::append(PathStr, (*Current)->getName());
- sys::fs::file_type Type;
- switch ((*Current)->getKind()) {
- case RedirectingFileSystem::EK_Directory:
- Type = sys::fs::file_type::directory_file;
- break;
- case RedirectingFileSystem::EK_File:
- Type = sys::fs::file_type::regular_file;
- break;
- }
- CurrentEntry = directory_entry(PathStr.str(), Type);
- return {};
- }
- return incrementExternal();
-}
-
-std::error_code VFSFromYamlDirIterImpl::incrementImpl(bool IsFirstTime) {
- while (true) {
- std::error_code EC = IsExternalFSCurrent ? incrementExternal()
- : incrementContent(IsFirstTime);
- if (EC || CurrentEntry.path().empty())
- return EC;
- StringRef Name = llvm::sys::path::filename(CurrentEntry.path());
- if (SeenNames.insert(Name).second)
- return EC; // name not seen before
- }
- llvm_unreachable("returned above");
-}
-
-vfs::recursive_directory_iterator::recursive_directory_iterator(
- FileSystem &FS_, const Twine &Path, std::error_code &EC)
- : FS(&FS_) {
- directory_iterator I = FS->dir_begin(Path, EC);
- if (I != directory_iterator()) {
- State = std::make_shared<detail::RecDirIterState>();
- State->Stack.push(I);
- }
-}
-
-vfs::recursive_directory_iterator &
-recursive_directory_iterator::increment(std::error_code &EC) {
- assert(FS && State && !State->Stack.empty() && "incrementing past end");
- assert(!State->Stack.top()->path().empty() && "non-canonical end iterator");
- vfs::directory_iterator End;
-
- if (State->HasNoPushRequest)
- State->HasNoPushRequest = false;
- else {
- if (State->Stack.top()->type() == sys::fs::file_type::directory_file) {
- vfs::directory_iterator I = FS->dir_begin(State->Stack.top()->path(), EC);
- if (I != End) {
- State->Stack.push(I);
- return *this;
- }
- }
- }
-
- while (!State->Stack.empty() && State->Stack.top().increment(EC) == End)
- State->Stack.pop();
-
- if (State->Stack.empty())
- State.reset(); // end iterator
-
- return *this;
-}
diff --git a/gnu/llvm/lib/Support/Watchdog.cpp b/gnu/llvm/lib/Support/Watchdog.cpp
deleted file mode 100644
index be55e3122e7..00000000000
--- a/gnu/llvm/lib/Support/Watchdog.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//===---- Watchdog.cpp - Implement Watchdog ---------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Watchdog class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Watchdog.h"
-#include "llvm/Config/llvm-config.h"
-
-// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
-#include "Unix/Watchdog.inc"
-#endif
-#ifdef _WIN32
-#include "Windows/Watchdog.inc"
-#endif
diff --git a/gnu/llvm/lib/Support/Windows/COM.inc b/gnu/llvm/lib/Support/Windows/COM.inc
deleted file mode 100644
index 54f3ecf28ec..00000000000
--- a/gnu/llvm/lib/Support/Windows/COM.inc
+++ /dev/null
@@ -1,37 +0,0 @@
-//==- llvm/Support/Windows/COM.inc - Windows COM Implementation -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Windows portion of COM support.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only Windows code.
-//===----------------------------------------------------------------------===//
-
-#include <objbase.h>
-
-namespace llvm {
-namespace sys {
-
-InitializeCOMRAII::InitializeCOMRAII(COMThreadingMode Threading,
- bool SpeedOverMemory) {
- DWORD Coinit = 0;
- if (Threading == COMThreadingMode::SingleThreaded)
- Coinit |= COINIT_APARTMENTTHREADED;
- else
- Coinit |= COINIT_MULTITHREADED;
- if (SpeedOverMemory)
- Coinit |= COINIT_SPEED_OVER_MEMORY;
- ::CoInitializeEx(nullptr, Coinit);
-}
-
-InitializeCOMRAII::~InitializeCOMRAII() { ::CoUninitialize(); }
-}
-}
diff --git a/gnu/llvm/lib/Support/Windows/DynamicLibrary.inc b/gnu/llvm/lib/Support/Windows/DynamicLibrary.inc
deleted file mode 100644
index 1d47f0848a6..00000000000
--- a/gnu/llvm/lib/Support/Windows/DynamicLibrary.inc
+++ /dev/null
@@ -1,203 +0,0 @@
-//===- Win32/DynamicLibrary.cpp - Win32 DL Implementation -------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides the Win32 specific implementation of DynamicLibrary.
-//
-//===----------------------------------------------------------------------===//
-
-#include "WindowsSupport.h"
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <psapi.h>
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only Win32 specific code
-//=== and must not be UNIX code.
-//===----------------------------------------------------------------------===//
-
-
-DynamicLibrary::HandleSet::~HandleSet() {
- for (void *Handle : llvm::reverse(Handles))
- FreeLibrary(HMODULE(Handle));
-
- // 'Process' should not be released on Windows.
- assert((!Process || Process==this) && "Bad Handle");
- // llvm_shutdown called, Return to default
- DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker;
-}
-
-void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
- // Create the instance and return it to be the *Process* handle
- // simillar to dlopen(NULL, RTLD_LAZY|RTLD_GLOBAL)
- if (!File)
- return &(*OpenedHandles);
-
- SmallVector<wchar_t, MAX_PATH> FileUnicode;
- if (std::error_code ec = windows::UTF8ToUTF16(File, FileUnicode)) {
- SetLastError(ec.value());
- MakeErrMsg(Err, std::string(File) + ": Can't convert to UTF-16");
- return &DynamicLibrary::Invalid;
- }
-
- HMODULE Handle = LoadLibraryW(FileUnicode.data());
- if (Handle == NULL) {
- MakeErrMsg(Err, std::string(File) + ": Can't open");
- return &DynamicLibrary::Invalid;
- }
-
- return reinterpret_cast<void*>(Handle);
-}
-
-static DynamicLibrary::HandleSet *IsOpenedHandlesInstance(void *Handle) {
- if (!OpenedHandles.isConstructed())
- return nullptr;
- DynamicLibrary::HandleSet &Inst = *OpenedHandles;
- return Handle == &Inst ? &Inst : nullptr;
-}
-
-void DynamicLibrary::HandleSet::DLClose(void *Handle) {
- if (HandleSet* HS = IsOpenedHandlesInstance(Handle))
- HS->Process = nullptr; // Just drop the *Process* handle.
- else
- FreeLibrary((HMODULE)Handle);
-}
-
-static bool GetProcessModules(HANDLE H, DWORD &Bytes, HMODULE *Data = nullptr) {
- // EnumProcessModules will fail on Windows 64 while some versions of
- // MingW-32 don't have EnumProcessModulesEx.
- if (
-#ifdef _WIN64
- !EnumProcessModulesEx(H, Data, Bytes, &Bytes, LIST_MODULES_64BIT)
-#else
- !EnumProcessModules(H, Data, Bytes, &Bytes)
-#endif
- ) {
- std::string Err;
- if (MakeErrMsg(&Err, "EnumProcessModules failure"))
- llvm::errs() << Err << "\n";
- return false;
- }
- return true;
-}
-
-void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
- HandleSet* HS = IsOpenedHandlesInstance(Handle);
- if (!HS)
- return (void *)uintptr_t(GetProcAddress((HMODULE)Handle, Symbol));
-
- // Could have done a dlclose on the *Process* handle
- if (!HS->Process)
- return nullptr;
-
- // Trials indicate EnumProcessModulesEx is consistantly faster than using
- // EnumerateLoadedModules64 or CreateToolhelp32Snapshot.
- //
- // | Handles | DbgHelp.dll | CreateSnapshot | EnumProcessModulesEx
- // |=========|=============|========================================
- // | 37 | 0.0000585 * | 0.0003031 | 0.0000152
- // | 1020 | 0.0026310 * | 0.0121598 | 0.0002683
- // | 2084 | 0.0149418 * | 0.0369936 | 0.0005610
- //
- // * Not including the load time of Dbghelp.dll (~.005 sec)
- //
- // There's still a case to somehow cache the result of EnumProcessModulesEx
- // across invocations, but the complication of doing that properly...
- // Possibly using LdrRegisterDllNotification to invalidate the cache?
-
- DWORD Bytes = 0;
- HMODULE Self = HMODULE(GetCurrentProcess());
- if (!GetProcessModules(Self, Bytes))
- return nullptr;
-
- // Get the most recent list in case any modules added/removed between calls
- // to EnumProcessModulesEx that gets the amount of, then copies the HMODULES.
- // MSDN is pretty clear that if the module list changes during the call to
- // EnumProcessModulesEx the results should not be used.
- std::vector<HMODULE> Handles;
- do {
- assert(Bytes && ((Bytes % sizeof(HMODULE)) == 0) &&
- "Should have at least one module and be aligned");
- Handles.resize(Bytes / sizeof(HMODULE));
- if (!GetProcessModules(Self, Bytes, Handles.data()))
- return nullptr;
- } while (Bytes != (Handles.size() * sizeof(HMODULE)));
-
- // Try EXE first, mirroring what dlsym(dlopen(NULL)) does.
- if (FARPROC Ptr = GetProcAddress(HMODULE(Handles.front()), Symbol))
- return (void *) uintptr_t(Ptr);
-
- if (Handles.size() > 1) {
- // This is different behaviour than what Posix dlsym(dlopen(NULL)) does.
- // Doing that here is causing real problems for the JIT where msvc.dll
- // and ucrt.dll can define the same symbols. The runtime linker will choose
- // symbols from ucrt.dll first, but iterating NOT in reverse here would
- // mean that the msvc.dll versions would be returned.
-
- for (auto I = Handles.rbegin(), E = Handles.rend()-1; I != E; ++I) {
- if (FARPROC Ptr = GetProcAddress(HMODULE(*I), Symbol))
- return (void *) uintptr_t(Ptr);
- }
- }
- return nullptr;
-}
-
-
-// Stack probing routines are in the support library (e.g. libgcc), but we don't
-// have dynamic linking on windows. Provide a hook.
-#define EXPLICIT_SYMBOL(SYM) \
- extern "C" { extern void *SYM; }
-#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO)
-
-#ifdef _M_IX86
-// Win32 on x86 implements certain single-precision math functions as macros.
-// These functions are not exported by the DLL, but will still be needed
-// for symbol-resolution by the JIT loader. Therefore, this Support libray
-// provides helper functions with the same implementation.
-
-#define INLINE_DEF_SYMBOL1(TYP, SYM) \
- extern "C" TYP inline_##SYM(TYP _X) { return SYM(_X); }
-#define INLINE_DEF_SYMBOL2(TYP, SYM) \
- extern "C" TYP inline_##SYM(TYP _X, TYP _Y) { return SYM(_X, _Y); }
-#endif
-
-#include "explicit_symbols.inc"
-
-#undef EXPLICIT_SYMBOL
-#undef EXPLICIT_SYMBOL2
-#undef INLINE_DEF_SYMBOL1
-#undef INLINE_DEF_SYMBOL2
-
-static void *DoSearch(const char *SymbolName) {
-
-#define EXPLICIT_SYMBOL(SYM) \
- if (!strcmp(SymbolName, #SYM)) \
- return (void *)&SYM;
-#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \
- if (!strcmp(SymbolName, #SYMFROM)) \
- return (void *)&SYMTO;
-
-#ifdef _M_IX86
-#define INLINE_DEF_SYMBOL1(TYP, SYM) \
- if (!strcmp(SymbolName, #SYM)) \
- return (void *)&inline_##SYM;
-#define INLINE_DEF_SYMBOL2(TYP, SYM) INLINE_DEF_SYMBOL1(TYP, SYM)
-#endif
-
- {
-#include "explicit_symbols.inc"
- }
-
-#undef EXPLICIT_SYMBOL
-#undef EXPLICIT_SYMBOL2
-#undef INLINE_DEF_SYMBOL1
-#undef INLINE_DEF_SYMBOL2
-
- return nullptr;
-}
diff --git a/gnu/llvm/lib/Support/Windows/Host.inc b/gnu/llvm/lib/Support/Windows/Host.inc
deleted file mode 100644
index 58c4dc5d678..00000000000
--- a/gnu/llvm/lib/Support/Windows/Host.inc
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- llvm/Support/Win32/Host.inc ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Win32 Host support.
-//
-//===----------------------------------------------------------------------===//
-
-#include "WindowsSupport.h"
-#include <cstdio>
-#include <string>
-
-using namespace llvm;
-
-static std::string updateTripleOSVersion(std::string Triple) {
- return Triple;
-}
-
-std::string sys::getDefaultTargetTriple() {
- const char *Triple = LLVM_DEFAULT_TARGET_TRIPLE;
-
- // Override the default target with an environment variable named by LLVM_TARGET_TRIPLE_ENV.
-#if defined(LLVM_TARGET_TRIPLE_ENV)
- if (const char *EnvTriple = std::getenv(LLVM_TARGET_TRIPLE_ENV))
- Triple = EnvTriple;
-#endif
-
- return Triple;
-}
diff --git a/gnu/llvm/lib/Support/Windows/Memory.inc b/gnu/llvm/lib/Support/Windows/Memory.inc
deleted file mode 100644
index 318e65aaa9e..00000000000
--- a/gnu/llvm/lib/Support/Windows/Memory.inc
+++ /dev/null
@@ -1,164 +0,0 @@
-//===- Win32/Memory.cpp - Win32 Memory Implementation -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides the Win32 specific implementation of various Memory
-// management utilities
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/WindowsError.h"
-
-// The Windows.h header must be the last one included.
-#include "WindowsSupport.h"
-
-namespace {
-
-DWORD getWindowsProtectionFlags(unsigned Flags) {
- switch (Flags) {
- // Contrary to what you might expect, the Windows page protection flags
- // are not a bitwise combination of RWX values
- case llvm::sys::Memory::MF_READ:
- return PAGE_READONLY;
- case llvm::sys::Memory::MF_WRITE:
- // Note: PAGE_WRITE is not supported by VirtualProtect
- return PAGE_READWRITE;
- case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_WRITE:
- return PAGE_READWRITE;
- case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC:
- return PAGE_EXECUTE_READ;
- case llvm::sys::Memory::MF_READ |
- llvm::sys::Memory::MF_WRITE |
- llvm::sys::Memory::MF_EXEC:
- return PAGE_EXECUTE_READWRITE;
- case llvm::sys::Memory::MF_EXEC:
- return PAGE_EXECUTE;
- default:
- llvm_unreachable("Illegal memory protection flag specified!");
- }
- // Provide a default return value as required by some compilers.
- return PAGE_NOACCESS;
-}
-
-size_t getAllocationGranularity() {
- SYSTEM_INFO Info;
- ::GetSystemInfo(&Info);
- if (Info.dwPageSize > Info.dwAllocationGranularity)
- return Info.dwPageSize;
- else
- return Info.dwAllocationGranularity;
-}
-
-} // namespace
-
-namespace llvm {
-namespace sys {
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only Win32 specific code
-//=== and must not be UNIX code
-//===----------------------------------------------------------------------===//
-
-MemoryBlock Memory::allocateMappedMemory(size_t NumBytes,
- const MemoryBlock *const NearBlock,
- unsigned Flags,
- std::error_code &EC) {
- EC = std::error_code();
- if (NumBytes == 0)
- return MemoryBlock();
-
- // While we'd be happy to allocate single pages, the Windows allocation
- // granularity may be larger than a single page (in practice, it is 64K)
- // so mapping less than that will create an unreachable fragment of memory.
- // Avoid using one-time initialization of static locals here, since they
- // aren't thread safe with MSVC.
- static volatile size_t GranularityCached;
- size_t Granularity = GranularityCached;
- if (Granularity == 0) {
- Granularity = getAllocationGranularity();
- GranularityCached = Granularity;
- }
-
- const size_t NumBlocks = (NumBytes+Granularity-1)/Granularity;
-
- uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) +
- NearBlock->size()
- : 0;
-
- // If the requested address is not aligned to the allocation granularity,
- // round up to get beyond NearBlock. VirtualAlloc would have rounded down.
- if (Start && Start % Granularity != 0)
- Start += Granularity - Start % Granularity;
-
- DWORD Protect = getWindowsProtectionFlags(Flags);
-
- void *PA = ::VirtualAlloc(reinterpret_cast<void*>(Start),
- NumBlocks*Granularity,
- MEM_RESERVE | MEM_COMMIT, Protect);
- if (PA == NULL) {
- if (NearBlock) {
- // Try again without the NearBlock hint
- return allocateMappedMemory(NumBytes, NULL, Flags, EC);
- }
- EC = mapWindowsError(::GetLastError());
- return MemoryBlock();
- }
-
- MemoryBlock Result;
- Result.Address = PA;
- Result.Size = NumBlocks*Granularity;
-
- if (Flags & MF_EXEC)
- Memory::InvalidateInstructionCache(Result.Address, Result.Size);
-
- return Result;
-}
-
- std::error_code Memory::releaseMappedMemory(MemoryBlock &M) {
- if (M.Address == 0 || M.Size == 0)
- return std::error_code();
-
- if (!VirtualFree(M.Address, 0, MEM_RELEASE))
- return mapWindowsError(::GetLastError());
-
- M.Address = 0;
- M.Size = 0;
-
- return std::error_code();
-}
-
- std::error_code Memory::protectMappedMemory(const MemoryBlock &M,
- unsigned Flags) {
- if (M.Address == 0 || M.Size == 0)
- return std::error_code();
-
- DWORD Protect = getWindowsProtectionFlags(Flags);
-
- DWORD OldFlags;
- if (!VirtualProtect(M.Address, M.Size, Protect, &OldFlags))
- return mapWindowsError(::GetLastError());
-
- if (Flags & MF_EXEC)
- Memory::InvalidateInstructionCache(M.Address, M.Size);
-
- return std::error_code();
-}
-
-/// InvalidateInstructionCache - Before the JIT can run a block of code
-/// that has been emitted it must invalidate the instruction cache on some
-/// platforms.
-void Memory::InvalidateInstructionCache(
- const void *Addr, size_t Len) {
- FlushInstructionCache(GetCurrentProcess(), Addr, Len);
-}
-
-} // namespace sys
-} // namespace llvm
diff --git a/gnu/llvm/lib/Support/Windows/Mutex.inc b/gnu/llvm/lib/Support/Windows/Mutex.inc
deleted file mode 100644
index 0af145ec9a4..00000000000
--- a/gnu/llvm/lib/Support/Windows/Mutex.inc
+++ /dev/null
@@ -1,57 +0,0 @@
-//===- llvm/Support/Win32/Mutex.inc - Win32 Mutex Implementation -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Win32 specific (non-pthread) Mutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic Win32 code that
-//=== is guaranteed to work on *all* Win32 variants.
-//===----------------------------------------------------------------------===//
-
-#include "WindowsSupport.h"
-#include "llvm/Support/Mutex.h"
-
-namespace llvm {
-
-sys::MutexImpl::MutexImpl(bool /*recursive*/)
-{
- data_ = new CRITICAL_SECTION;
- InitializeCriticalSection((LPCRITICAL_SECTION)data_);
-}
-
-sys::MutexImpl::~MutexImpl()
-{
- DeleteCriticalSection((LPCRITICAL_SECTION)data_);
- delete (LPCRITICAL_SECTION)data_;
- data_ = 0;
-}
-
-bool
-sys::MutexImpl::acquire()
-{
- EnterCriticalSection((LPCRITICAL_SECTION)data_);
- return true;
-}
-
-bool
-sys::MutexImpl::release()
-{
- LeaveCriticalSection((LPCRITICAL_SECTION)data_);
- return true;
-}
-
-bool
-sys::MutexImpl::tryacquire()
-{
- return TryEnterCriticalSection((LPCRITICAL_SECTION)data_);
-}
-
-}
diff --git a/gnu/llvm/lib/Support/Windows/Path.inc b/gnu/llvm/lib/Support/Windows/Path.inc
deleted file mode 100644
index d34aa763124..00000000000
--- a/gnu/llvm/lib/Support/Windows/Path.inc
+++ /dev/null
@@ -1,1439 +0,0 @@
-//===- llvm/Support/Windows/Path.inc - Windows Path Impl --------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Windows specific implementation of the Path API.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic Windows code that
-//=== is guaranteed to work on *all* Windows variants.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/WindowsError.h"
-#include <fcntl.h>
-#include <io.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-// These two headers must be included last, and make sure shlobj is required
-// after Windows.h to make sure it picks up our definition of _WIN32_WINNT
-#include "WindowsSupport.h"
-#include <shellapi.h>
-#include <shlobj.h>
-
-#undef max
-
-// MinGW doesn't define this.
-#ifndef _ERRNO_T_DEFINED
-#define _ERRNO_T_DEFINED
-typedef int errno_t;
-#endif
-
-#ifdef _MSC_VER
-# pragma comment(lib, "advapi32.lib") // This provides CryptAcquireContextW.
-# pragma comment(lib, "ole32.lib") // This provides CoTaskMemFree
-#endif
-
-using namespace llvm;
-
-using llvm::sys::windows::UTF8ToUTF16;
-using llvm::sys::windows::CurCPToUTF16;
-using llvm::sys::windows::UTF16ToUTF8;
-using llvm::sys::path::widenPath;
-
-static bool is_separator(const wchar_t value) {
- switch (value) {
- case L'\\':
- case L'/':
- return true;
- default:
- return false;
- }
-}
-
-namespace llvm {
-namespace sys {
-namespace path {
-
-// Convert a UTF-8 path to UTF-16. Also, if the absolute equivalent of the
-// path is longer than CreateDirectory can tolerate, make it absolute and
-// prefixed by '\\?\'.
-std::error_code widenPath(const Twine &Path8,
- SmallVectorImpl<wchar_t> &Path16) {
- const size_t MaxDirLen = MAX_PATH - 12; // Must leave room for 8.3 filename.
-
- // Several operations would convert Path8 to SmallString; more efficient to
- // do it once up front.
- SmallString<128> Path8Str;
- Path8.toVector(Path8Str);
-
- // If we made this path absolute, how much longer would it get?
- size_t CurPathLen;
- if (llvm::sys::path::is_absolute(Twine(Path8Str)))
- CurPathLen = 0; // No contribution from current_path needed.
- else {
- CurPathLen = ::GetCurrentDirectoryW(0, NULL);
- if (CurPathLen == 0)
- return mapWindowsError(::GetLastError());
- }
-
- // Would the absolute path be longer than our limit?
- if ((Path8Str.size() + CurPathLen) >= MaxDirLen &&
- !Path8Str.startswith("\\\\?\\")) {
- SmallString<2*MAX_PATH> FullPath("\\\\?\\");
- if (CurPathLen) {
- SmallString<80> CurPath;
- if (std::error_code EC = llvm::sys::fs::current_path(CurPath))
- return EC;
- FullPath.append(CurPath);
- }
- // Traverse the requested path, canonicalizing . and .. (because the \\?\
- // prefix is documented to treat them as real components). Ignore
- // separators, which can be returned from the iterator if the path has a
- // drive name. We don't need to call native() on the result since append()
- // always attaches preferred_separator.
- for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(Path8Str),
- E = llvm::sys::path::end(Path8Str);
- I != E; ++I) {
- if (I->size() == 1 && is_separator((*I)[0]))
- continue;
- if (I->size() == 1 && *I == ".")
- continue;
- if (I->size() == 2 && *I == "..")
- llvm::sys::path::remove_filename(FullPath);
- else
- llvm::sys::path::append(FullPath, *I);
- }
- return UTF8ToUTF16(FullPath, Path16);
- }
-
- // Just use the caller's original path.
- return UTF8ToUTF16(Path8Str, Path16);
-}
-} // end namespace path
-
-namespace fs {
-
-const file_t kInvalidFile = INVALID_HANDLE_VALUE;
-
-std::string getMainExecutable(const char *argv0, void *MainExecAddr) {
- SmallVector<wchar_t, MAX_PATH> PathName;
- DWORD Size = ::GetModuleFileNameW(NULL, PathName.data(), PathName.capacity());
-
- // A zero return value indicates a failure other than insufficient space.
- if (Size == 0)
- return "";
-
- // Insufficient space is determined by a return value equal to the size of
- // the buffer passed in.
- if (Size == PathName.capacity())
- return "";
-
- // On success, GetModuleFileNameW returns the number of characters written to
- // the buffer not including the NULL terminator.
- PathName.set_size(Size);
-
- // Convert the result from UTF-16 to UTF-8.
- SmallVector<char, MAX_PATH> PathNameUTF8;
- if (UTF16ToUTF8(PathName.data(), PathName.size(), PathNameUTF8))
- return "";
-
- return std::string(PathNameUTF8.data());
-}
-
-UniqueID file_status::getUniqueID() const {
- // The file is uniquely identified by the volume serial number along
- // with the 64-bit file identifier.
- uint64_t FileID = (static_cast<uint64_t>(FileIndexHigh) << 32ULL) |
- static_cast<uint64_t>(FileIndexLow);
-
- return UniqueID(VolumeSerialNumber, FileID);
-}
-
-ErrorOr<space_info> disk_space(const Twine &Path) {
- ULARGE_INTEGER Avail, Total, Free;
- if (!::GetDiskFreeSpaceExA(Path.str().c_str(), &Avail, &Total, &Free))
- return mapWindowsError(::GetLastError());
- space_info SpaceInfo;
- SpaceInfo.capacity =
- (static_cast<uint64_t>(Total.HighPart) << 32) + Total.LowPart;
- SpaceInfo.free = (static_cast<uint64_t>(Free.HighPart) << 32) + Free.LowPart;
- SpaceInfo.available =
- (static_cast<uint64_t>(Avail.HighPart) << 32) + Avail.LowPart;
- return SpaceInfo;
-}
-
-TimePoint<> basic_file_status::getLastAccessedTime() const {
- FILETIME Time;
- Time.dwLowDateTime = LastAccessedTimeLow;
- Time.dwHighDateTime = LastAccessedTimeHigh;
- return toTimePoint(Time);
-}
-
-TimePoint<> basic_file_status::getLastModificationTime() const {
- FILETIME Time;
- Time.dwLowDateTime = LastWriteTimeLow;
- Time.dwHighDateTime = LastWriteTimeHigh;
- return toTimePoint(Time);
-}
-
-uint32_t file_status::getLinkCount() const {
- return NumLinks;
-}
-
-std::error_code current_path(SmallVectorImpl<char> &result) {
- SmallVector<wchar_t, MAX_PATH> cur_path;
- DWORD len = MAX_PATH;
-
- do {
- cur_path.reserve(len);
- len = ::GetCurrentDirectoryW(cur_path.capacity(), cur_path.data());
-
- // A zero return value indicates a failure other than insufficient space.
- if (len == 0)
- return mapWindowsError(::GetLastError());
-
- // If there's insufficient space, the len returned is larger than the len
- // given.
- } while (len > cur_path.capacity());
-
- // On success, GetCurrentDirectoryW returns the number of characters not
- // including the null-terminator.
- cur_path.set_size(len);
- return UTF16ToUTF8(cur_path.begin(), cur_path.size(), result);
-}
-
-std::error_code set_current_path(const Twine &path) {
- // Convert to utf-16.
- SmallVector<wchar_t, 128> wide_path;
- if (std::error_code ec = widenPath(path, wide_path))
- return ec;
-
- if (!::SetCurrentDirectoryW(wide_path.begin()))
- return mapWindowsError(::GetLastError());
-
- return std::error_code();
-}
-
-std::error_code create_directory(const Twine &path, bool IgnoreExisting,
- perms Perms) {
- SmallVector<wchar_t, 128> path_utf16;
-
- if (std::error_code ec = widenPath(path, path_utf16))
- return ec;
-
- if (!::CreateDirectoryW(path_utf16.begin(), NULL)) {
- DWORD LastError = ::GetLastError();
- if (LastError != ERROR_ALREADY_EXISTS || !IgnoreExisting)
- return mapWindowsError(LastError);
- }
-
- return std::error_code();
-}
-
-// We can't use symbolic links for windows.
-std::error_code create_link(const Twine &to, const Twine &from) {
- // Convert to utf-16.
- SmallVector<wchar_t, 128> wide_from;
- SmallVector<wchar_t, 128> wide_to;
- if (std::error_code ec = widenPath(from, wide_from))
- return ec;
- if (std::error_code ec = widenPath(to, wide_to))
- return ec;
-
- if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL))
- return mapWindowsError(::GetLastError());
-
- return std::error_code();
-}
-
-std::error_code create_hard_link(const Twine &to, const Twine &from) {
- return create_link(to, from);
-}
-
-std::error_code remove(const Twine &path, bool IgnoreNonExisting) {
- SmallVector<wchar_t, 128> path_utf16;
-
- if (std::error_code ec = widenPath(path, path_utf16))
- return ec;
-
- // We don't know whether this is a file or a directory, and remove() can
- // accept both. The usual way to delete a file or directory is to use one of
- // the DeleteFile or RemoveDirectory functions, but that requires you to know
- // which one it is. We could stat() the file to determine that, but that would
- // cost us additional system calls, which can be slow in a directory
- // containing a large number of files. So instead we call CreateFile directly.
- // The important part is the FILE_FLAG_DELETE_ON_CLOSE flag, which causes the
- // file to be deleted once it is closed. We also use the flags
- // FILE_FLAG_BACKUP_SEMANTICS (which allows us to open directories), and
- // FILE_FLAG_OPEN_REPARSE_POINT (don't follow symlinks).
- ScopedFileHandle h(::CreateFileW(
- c_str(path_utf16), DELETE,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS |
- FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_DELETE_ON_CLOSE,
- NULL));
- if (!h) {
- std::error_code EC = mapWindowsError(::GetLastError());
- if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting)
- return EC;
- }
-
- return std::error_code();
-}
-
-static std::error_code is_local_internal(SmallVectorImpl<wchar_t> &Path,
- bool &Result) {
- SmallVector<wchar_t, 128> VolumePath;
- size_t Len = 128;
- while (true) {
- VolumePath.resize(Len);
- BOOL Success =
- ::GetVolumePathNameW(Path.data(), VolumePath.data(), VolumePath.size());
-
- if (Success)
- break;
-
- DWORD Err = ::GetLastError();
- if (Err != ERROR_INSUFFICIENT_BUFFER)
- return mapWindowsError(Err);
-
- Len *= 2;
- }
- // If the output buffer has exactly enough space for the path name, but not
- // the null terminator, it will leave the output unterminated. Push a null
- // terminator onto the end to ensure that this never happens.
- VolumePath.push_back(L'\0');
- VolumePath.set_size(wcslen(VolumePath.data()));
- const wchar_t *P = VolumePath.data();
-
- UINT Type = ::GetDriveTypeW(P);
- switch (Type) {
- case DRIVE_FIXED:
- Result = true;
- return std::error_code();
- case DRIVE_REMOTE:
- case DRIVE_CDROM:
- case DRIVE_RAMDISK:
- case DRIVE_REMOVABLE:
- Result = false;
- return std::error_code();
- default:
- return make_error_code(errc::no_such_file_or_directory);
- }
- llvm_unreachable("Unreachable!");
-}
-
-std::error_code is_local(const Twine &path, bool &result) {
- if (!llvm::sys::fs::exists(path) || !llvm::sys::path::has_root_path(path))
- return make_error_code(errc::no_such_file_or_directory);
-
- SmallString<128> Storage;
- StringRef P = path.toStringRef(Storage);
-
- // Convert to utf-16.
- SmallVector<wchar_t, 128> WidePath;
- if (std::error_code ec = widenPath(P, WidePath))
- return ec;
- return is_local_internal(WidePath, result);
-}
-
-static std::error_code realPathFromHandle(HANDLE H,
- SmallVectorImpl<wchar_t> &Buffer) {
- DWORD CountChars = ::GetFinalPathNameByHandleW(
- H, Buffer.begin(), Buffer.capacity() - 1, FILE_NAME_NORMALIZED);
- if (CountChars > Buffer.capacity()) {
- // The buffer wasn't big enough, try again. In this case the return value
- // *does* indicate the size of the null terminator.
- Buffer.reserve(CountChars);
- CountChars = ::GetFinalPathNameByHandleW(
- H, Buffer.data(), Buffer.capacity() - 1, FILE_NAME_NORMALIZED);
- }
- if (CountChars == 0)
- return mapWindowsError(GetLastError());
- Buffer.set_size(CountChars);
- return std::error_code();
-}
-
-static std::error_code realPathFromHandle(HANDLE H,
- SmallVectorImpl<char> &RealPath) {
- RealPath.clear();
- SmallVector<wchar_t, MAX_PATH> Buffer;
- if (std::error_code EC = realPathFromHandle(H, Buffer))
- return EC;
-
- const wchar_t *Data = Buffer.data();
- DWORD CountChars = Buffer.size();
- if (CountChars >= 4) {
- if (0 == ::memcmp(Data, L"\\\\?\\", 8)) {
- CountChars -= 4;
- Data += 4;
- }
- }
-
- // Convert the result from UTF-16 to UTF-8.
- return UTF16ToUTF8(Data, CountChars, RealPath);
-}
-
-std::error_code is_local(int FD, bool &Result) {
- SmallVector<wchar_t, 128> FinalPath;
- HANDLE Handle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
-
- if (std::error_code EC = realPathFromHandle(Handle, FinalPath))
- return EC;
-
- return is_local_internal(FinalPath, Result);
-}
-
-static std::error_code setDeleteDisposition(HANDLE Handle, bool Delete) {
- FILE_DISPOSITION_INFO Disposition;
- Disposition.DeleteFile = Delete;
- if (!SetFileInformationByHandle(Handle, FileDispositionInfo, &Disposition,
- sizeof(Disposition)))
- return mapWindowsError(::GetLastError());
- return std::error_code();
-}
-
-static std::error_code rename_internal(HANDLE FromHandle, const Twine &To,
- bool ReplaceIfExists) {
- SmallVector<wchar_t, 0> ToWide;
- if (auto EC = widenPath(To, ToWide))
- return EC;
-
- std::vector<char> RenameInfoBuf(sizeof(FILE_RENAME_INFO) - sizeof(wchar_t) +
- (ToWide.size() * sizeof(wchar_t)));
- FILE_RENAME_INFO &RenameInfo =
- *reinterpret_cast<FILE_RENAME_INFO *>(RenameInfoBuf.data());
- RenameInfo.ReplaceIfExists = ReplaceIfExists;
- RenameInfo.RootDirectory = 0;
- RenameInfo.FileNameLength = ToWide.size() * sizeof(wchar_t);
- std::copy(ToWide.begin(), ToWide.end(), &RenameInfo.FileName[0]);
-
- SetLastError(ERROR_SUCCESS);
- if (!SetFileInformationByHandle(FromHandle, FileRenameInfo, &RenameInfo,
- RenameInfoBuf.size())) {
- unsigned Error = GetLastError();
- if (Error == ERROR_SUCCESS)
- Error = ERROR_CALL_NOT_IMPLEMENTED; // Wine doesn't always set error code.
- return mapWindowsError(Error);
- }
-
- return std::error_code();
-}
-
-static std::error_code rename_handle(HANDLE FromHandle, const Twine &To) {
- SmallVector<wchar_t, 128> WideTo;
- if (std::error_code EC = widenPath(To, WideTo))
- return EC;
-
- // We normally expect this loop to succeed after a few iterations. If it
- // requires more than 200 tries, it's more likely that the failures are due to
- // a true error, so stop trying.
- for (unsigned Retry = 0; Retry != 200; ++Retry) {
- auto EC = rename_internal(FromHandle, To, true);
-
- if (EC ==
- std::error_code(ERROR_CALL_NOT_IMPLEMENTED, std::system_category())) {
- // Wine doesn't support SetFileInformationByHandle in rename_internal.
- // Fall back to MoveFileEx.
- SmallVector<wchar_t, MAX_PATH> WideFrom;
- if (std::error_code EC2 = realPathFromHandle(FromHandle, WideFrom))
- return EC2;
- if (::MoveFileExW(WideFrom.begin(), WideTo.begin(),
- MOVEFILE_REPLACE_EXISTING))
- return std::error_code();
- return mapWindowsError(GetLastError());
- }
-
- if (!EC || EC != errc::permission_denied)
- return EC;
-
- // The destination file probably exists and is currently open in another
- // process, either because the file was opened without FILE_SHARE_DELETE or
- // it is mapped into memory (e.g. using MemoryBuffer). Rename it in order to
- // move it out of the way of the source file. Use FILE_FLAG_DELETE_ON_CLOSE
- // to arrange for the destination file to be deleted when the other process
- // closes it.
- ScopedFileHandle ToHandle(
- ::CreateFileW(WideTo.begin(), GENERIC_READ | DELETE,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL));
- if (!ToHandle) {
- auto EC = mapWindowsError(GetLastError());
- // Another process might have raced with us and moved the existing file
- // out of the way before we had a chance to open it. If that happens, try
- // to rename the source file again.
- if (EC == errc::no_such_file_or_directory)
- continue;
- return EC;
- }
-
- BY_HANDLE_FILE_INFORMATION FI;
- if (!GetFileInformationByHandle(ToHandle, &FI))
- return mapWindowsError(GetLastError());
-
- // Try to find a unique new name for the destination file.
- for (unsigned UniqueId = 0; UniqueId != 200; ++UniqueId) {
- std::string TmpFilename = (To + ".tmp" + utostr(UniqueId)).str();
- if (auto EC = rename_internal(ToHandle, TmpFilename, false)) {
- if (EC == errc::file_exists || EC == errc::permission_denied) {
- // Again, another process might have raced with us and moved the file
- // before we could move it. Check whether this is the case, as it
- // might have caused the permission denied error. If that was the
- // case, we don't need to move it ourselves.
- ScopedFileHandle ToHandle2(::CreateFileW(
- WideTo.begin(), 0,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
- if (!ToHandle2) {
- auto EC = mapWindowsError(GetLastError());
- if (EC == errc::no_such_file_or_directory)
- break;
- return EC;
- }
- BY_HANDLE_FILE_INFORMATION FI2;
- if (!GetFileInformationByHandle(ToHandle2, &FI2))
- return mapWindowsError(GetLastError());
- if (FI.nFileIndexHigh != FI2.nFileIndexHigh ||
- FI.nFileIndexLow != FI2.nFileIndexLow ||
- FI.dwVolumeSerialNumber != FI2.dwVolumeSerialNumber)
- break;
- continue;
- }
- return EC;
- }
- break;
- }
-
- // Okay, the old destination file has probably been moved out of the way at
- // this point, so try to rename the source file again. Still, another
- // process might have raced with us to create and open the destination
- // file, so we need to keep doing this until we succeed.
- }
-
- // The most likely root cause.
- return errc::permission_denied;
-}
-
-static std::error_code rename_fd(int FromFD, const Twine &To) {
- HANDLE FromHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FromFD));
- return rename_handle(FromHandle, To);
-}
-
-std::error_code rename(const Twine &From, const Twine &To) {
- // Convert to utf-16.
- SmallVector<wchar_t, 128> WideFrom;
- if (std::error_code EC = widenPath(From, WideFrom))
- return EC;
-
- ScopedFileHandle FromHandle;
- // Retry this a few times to defeat badly behaved file system scanners.
- for (unsigned Retry = 0; Retry != 200; ++Retry) {
- if (Retry != 0)
- ::Sleep(10);
- FromHandle =
- ::CreateFileW(WideFrom.begin(), GENERIC_READ | DELETE,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (FromHandle)
- break;
- }
- if (!FromHandle)
- return mapWindowsError(GetLastError());
-
- return rename_handle(FromHandle, To);
-}
-
-std::error_code resize_file(int FD, uint64_t Size) {
-#ifdef HAVE__CHSIZE_S
- errno_t error = ::_chsize_s(FD, Size);
-#else
- errno_t error = ::_chsize(FD, Size);
-#endif
- return std::error_code(error, std::generic_category());
-}
-
-std::error_code access(const Twine &Path, AccessMode Mode) {
- SmallVector<wchar_t, 128> PathUtf16;
-
- if (std::error_code EC = widenPath(Path, PathUtf16))
- return EC;
-
- DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin());
-
- if (Attributes == INVALID_FILE_ATTRIBUTES) {
- // See if the file didn't actually exist.
- DWORD LastError = ::GetLastError();
- if (LastError != ERROR_FILE_NOT_FOUND &&
- LastError != ERROR_PATH_NOT_FOUND)
- return mapWindowsError(LastError);
- return errc::no_such_file_or_directory;
- }
-
- if (Mode == AccessMode::Write && (Attributes & FILE_ATTRIBUTE_READONLY))
- return errc::permission_denied;
-
- return std::error_code();
-}
-
-bool can_execute(const Twine &Path) {
- return !access(Path, AccessMode::Execute) ||
- !access(Path + ".exe", AccessMode::Execute);
-}
-
-bool equivalent(file_status A, file_status B) {
- assert(status_known(A) && status_known(B));
- return A.FileIndexHigh == B.FileIndexHigh &&
- A.FileIndexLow == B.FileIndexLow &&
- A.FileSizeHigh == B.FileSizeHigh &&
- A.FileSizeLow == B.FileSizeLow &&
- A.LastAccessedTimeHigh == B.LastAccessedTimeHigh &&
- A.LastAccessedTimeLow == B.LastAccessedTimeLow &&
- A.LastWriteTimeHigh == B.LastWriteTimeHigh &&
- A.LastWriteTimeLow == B.LastWriteTimeLow &&
- A.VolumeSerialNumber == B.VolumeSerialNumber;
-}
-
-std::error_code equivalent(const Twine &A, const Twine &B, bool &result) {
- file_status fsA, fsB;
- if (std::error_code ec = status(A, fsA))
- return ec;
- if (std::error_code ec = status(B, fsB))
- return ec;
- result = equivalent(fsA, fsB);
- return std::error_code();
-}
-
-static bool isReservedName(StringRef path) {
- // This list of reserved names comes from MSDN, at:
- // http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx
- static const char *const sReservedNames[] = { "nul", "con", "prn", "aux",
- "com1", "com2", "com3", "com4",
- "com5", "com6", "com7", "com8",
- "com9", "lpt1", "lpt2", "lpt3",
- "lpt4", "lpt5", "lpt6", "lpt7",
- "lpt8", "lpt9" };
-
- // First, check to see if this is a device namespace, which always
- // starts with \\.\, since device namespaces are not legal file paths.
- if (path.startswith("\\\\.\\"))
- return true;
-
- // Then compare against the list of ancient reserved names.
- for (size_t i = 0; i < array_lengthof(sReservedNames); ++i) {
- if (path.equals_lower(sReservedNames[i]))
- return true;
- }
-
- // The path isn't what we consider reserved.
- return false;
-}
-
-static file_type file_type_from_attrs(DWORD Attrs) {
- return (Attrs & FILE_ATTRIBUTE_DIRECTORY) ? file_type::directory_file
- : file_type::regular_file;
-}
-
-static perms perms_from_attrs(DWORD Attrs) {
- return (Attrs & FILE_ATTRIBUTE_READONLY) ? (all_read | all_exe) : all_all;
-}
-
-static std::error_code getStatus(HANDLE FileHandle, file_status &Result) {
- if (FileHandle == INVALID_HANDLE_VALUE)
- goto handle_status_error;
-
- switch (::GetFileType(FileHandle)) {
- default:
- llvm_unreachable("Don't know anything about this file type");
- case FILE_TYPE_UNKNOWN: {
- DWORD Err = ::GetLastError();
- if (Err != NO_ERROR)
- return mapWindowsError(Err);
- Result = file_status(file_type::type_unknown);
- return std::error_code();
- }
- case FILE_TYPE_DISK:
- break;
- case FILE_TYPE_CHAR:
- Result = file_status(file_type::character_file);
- return std::error_code();
- case FILE_TYPE_PIPE:
- Result = file_status(file_type::fifo_file);
- return std::error_code();
- }
-
- BY_HANDLE_FILE_INFORMATION Info;
- if (!::GetFileInformationByHandle(FileHandle, &Info))
- goto handle_status_error;
-
- Result = file_status(
- file_type_from_attrs(Info.dwFileAttributes),
- perms_from_attrs(Info.dwFileAttributes), Info.nNumberOfLinks,
- Info.ftLastAccessTime.dwHighDateTime, Info.ftLastAccessTime.dwLowDateTime,
- Info.ftLastWriteTime.dwHighDateTime, Info.ftLastWriteTime.dwLowDateTime,
- Info.dwVolumeSerialNumber, Info.nFileSizeHigh, Info.nFileSizeLow,
- Info.nFileIndexHigh, Info.nFileIndexLow);
- return std::error_code();
-
-handle_status_error:
- DWORD LastError = ::GetLastError();
- if (LastError == ERROR_FILE_NOT_FOUND ||
- LastError == ERROR_PATH_NOT_FOUND)
- Result = file_status(file_type::file_not_found);
- else if (LastError == ERROR_SHARING_VIOLATION)
- Result = file_status(file_type::type_unknown);
- else
- Result = file_status(file_type::status_error);
- return mapWindowsError(LastError);
-}
-
-std::error_code status(const Twine &path, file_status &result, bool Follow) {
- SmallString<128> path_storage;
- SmallVector<wchar_t, 128> path_utf16;
-
- StringRef path8 = path.toStringRef(path_storage);
- if (isReservedName(path8)) {
- result = file_status(file_type::character_file);
- return std::error_code();
- }
-
- if (std::error_code ec = widenPath(path8, path_utf16))
- return ec;
-
- DWORD attr = ::GetFileAttributesW(path_utf16.begin());
- if (attr == INVALID_FILE_ATTRIBUTES)
- return getStatus(INVALID_HANDLE_VALUE, result);
-
- DWORD Flags = FILE_FLAG_BACKUP_SEMANTICS;
- // Handle reparse points.
- if (!Follow && (attr & FILE_ATTRIBUTE_REPARSE_POINT))
- Flags |= FILE_FLAG_OPEN_REPARSE_POINT;
-
- ScopedFileHandle h(
- ::CreateFileW(path_utf16.begin(), 0, // Attributes only.
- FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, Flags, 0));
- if (!h)
- return getStatus(INVALID_HANDLE_VALUE, result);
-
- return getStatus(h, result);
-}
-
-std::error_code status(int FD, file_status &Result) {
- HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
- return getStatus(FileHandle, Result);
-}
-
-std::error_code setPermissions(const Twine &Path, perms Permissions) {
- SmallVector<wchar_t, 128> PathUTF16;
- if (std::error_code EC = widenPath(Path, PathUTF16))
- return EC;
-
- DWORD Attributes = ::GetFileAttributesW(PathUTF16.begin());
- if (Attributes == INVALID_FILE_ATTRIBUTES)
- return mapWindowsError(GetLastError());
-
- // There are many Windows file attributes that are not to do with the file
- // permissions (e.g. FILE_ATTRIBUTE_HIDDEN). We need to be careful to preserve
- // them.
- if (Permissions & all_write) {
- Attributes &= ~FILE_ATTRIBUTE_READONLY;
- if (Attributes == 0)
- // FILE_ATTRIBUTE_NORMAL indicates no other attributes are set.
- Attributes |= FILE_ATTRIBUTE_NORMAL;
- }
- else {
- Attributes |= FILE_ATTRIBUTE_READONLY;
- // FILE_ATTRIBUTE_NORMAL is not compatible with any other attributes, so
- // remove it, if it is present.
- Attributes &= ~FILE_ATTRIBUTE_NORMAL;
- }
-
- if (!::SetFileAttributesW(PathUTF16.begin(), Attributes))
- return mapWindowsError(GetLastError());
-
- return std::error_code();
-}
-
-std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
- TimePoint<> ModificationTime) {
- FILETIME AccessFT = toFILETIME(AccessTime);
- FILETIME ModifyFT = toFILETIME(ModificationTime);
- HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
- if (!SetFileTime(FileHandle, NULL, &AccessFT, &ModifyFT))
- return mapWindowsError(::GetLastError());
- return std::error_code();
-}
-
-std::error_code mapped_file_region::init(int FD, uint64_t Offset,
- mapmode Mode) {
- this->Mode = Mode;
- HANDLE OrigFileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
- if (OrigFileHandle == INVALID_HANDLE_VALUE)
- return make_error_code(errc::bad_file_descriptor);
-
- DWORD flprotect;
- switch (Mode) {
- case readonly: flprotect = PAGE_READONLY; break;
- case readwrite: flprotect = PAGE_READWRITE; break;
- case priv: flprotect = PAGE_WRITECOPY; break;
- }
-
- HANDLE FileMappingHandle =
- ::CreateFileMappingW(OrigFileHandle, 0, flprotect,
- Hi_32(Size),
- Lo_32(Size),
- 0);
- if (FileMappingHandle == NULL) {
- std::error_code ec = mapWindowsError(GetLastError());
- return ec;
- }
-
- DWORD dwDesiredAccess;
- switch (Mode) {
- case readonly: dwDesiredAccess = FILE_MAP_READ; break;
- case readwrite: dwDesiredAccess = FILE_MAP_WRITE; break;
- case priv: dwDesiredAccess = FILE_MAP_COPY; break;
- }
- Mapping = ::MapViewOfFile(FileMappingHandle,
- dwDesiredAccess,
- Offset >> 32,
- Offset & 0xffffffff,
- Size);
- if (Mapping == NULL) {
- std::error_code ec = mapWindowsError(GetLastError());
- ::CloseHandle(FileMappingHandle);
- return ec;
- }
-
- if (Size == 0) {
- MEMORY_BASIC_INFORMATION mbi;
- SIZE_T Result = VirtualQuery(Mapping, &mbi, sizeof(mbi));
- if (Result == 0) {
- std::error_code ec = mapWindowsError(GetLastError());
- ::UnmapViewOfFile(Mapping);
- ::CloseHandle(FileMappingHandle);
- return ec;
- }
- Size = mbi.RegionSize;
- }
-
- // Close the file mapping handle, as it's kept alive by the file mapping. But
- // neither the file mapping nor the file mapping handle keep the file handle
- // alive, so we need to keep a reference to the file in case all other handles
- // are closed and the file is deleted, which may cause invalid data to be read
- // from the file.
- ::CloseHandle(FileMappingHandle);
- if (!::DuplicateHandle(::GetCurrentProcess(), OrigFileHandle,
- ::GetCurrentProcess(), &FileHandle, 0, 0,
- DUPLICATE_SAME_ACCESS)) {
- std::error_code ec = mapWindowsError(GetLastError());
- ::UnmapViewOfFile(Mapping);
- return ec;
- }
-
- return std::error_code();
-}
-
-mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length,
- uint64_t offset, std::error_code &ec)
- : Size(length), Mapping() {
- ec = init(fd, offset, mode);
- if (ec)
- Mapping = 0;
-}
-
-static bool hasFlushBufferKernelBug() {
- static bool Ret{GetWindowsOSVersion() < llvm::VersionTuple(10, 0, 0, 17763)};
- return Ret;
-}
-
-static bool isEXE(StringRef Magic) {
- static const char PEMagic[] = {'P', 'E', '\0', '\0'};
- if (Magic.startswith(StringRef("MZ")) && Magic.size() >= 0x3c + 4) {
- uint32_t off = read32le(Magic.data() + 0x3c);
- // PE/COFF file, either EXE or DLL.
- if (Magic.substr(off).startswith(StringRef(PEMagic, sizeof(PEMagic))))
- return true;
- }
- return false;
-}
-
-mapped_file_region::~mapped_file_region() {
- if (Mapping) {
-
- bool Exe = isEXE(StringRef((char *)Mapping, Size));
-
- ::UnmapViewOfFile(Mapping);
-
- if (Mode == mapmode::readwrite && Exe && hasFlushBufferKernelBug()) {
- // There is a Windows kernel bug, the exact trigger conditions of which
- // are not well understood. When triggered, dirty pages are not properly
- // flushed and subsequent process's attempts to read a file can return
- // invalid data. Calling FlushFileBuffers on the write handle is
- // sufficient to ensure that this bug is not triggered.
- // The bug only occurs when writing an executable and executing it right
- // after, under high I/O pressure.
- ::FlushFileBuffers(FileHandle);
- }
-
- ::CloseHandle(FileHandle);
- }
-}
-
-size_t mapped_file_region::size() const {
- assert(Mapping && "Mapping failed but used anyway!");
- return Size;
-}
-
-char *mapped_file_region::data() const {
- assert(Mapping && "Mapping failed but used anyway!");
- return reinterpret_cast<char*>(Mapping);
-}
-
-const char *mapped_file_region::const_data() const {
- assert(Mapping && "Mapping failed but used anyway!");
- return reinterpret_cast<const char*>(Mapping);
-}
-
-int mapped_file_region::alignment() {
- SYSTEM_INFO SysInfo;
- ::GetSystemInfo(&SysInfo);
- return SysInfo.dwAllocationGranularity;
-}
-
-static basic_file_status status_from_find_data(WIN32_FIND_DATAW *FindData) {
- return basic_file_status(file_type_from_attrs(FindData->dwFileAttributes),
- perms_from_attrs(FindData->dwFileAttributes),
- FindData->ftLastAccessTime.dwHighDateTime,
- FindData->ftLastAccessTime.dwLowDateTime,
- FindData->ftLastWriteTime.dwHighDateTime,
- FindData->ftLastWriteTime.dwLowDateTime,
- FindData->nFileSizeHigh, FindData->nFileSizeLow);
-}
-
-std::error_code detail::directory_iterator_construct(detail::DirIterState &IT,
- StringRef Path,
- bool FollowSymlinks) {
- SmallVector<wchar_t, 128> PathUTF16;
-
- if (std::error_code EC = widenPath(Path, PathUTF16))
- return EC;
-
- // Convert path to the format that Windows is happy with.
- if (PathUTF16.size() > 0 &&
- !is_separator(PathUTF16[Path.size() - 1]) &&
- PathUTF16[Path.size() - 1] != L':') {
- PathUTF16.push_back(L'\\');
- PathUTF16.push_back(L'*');
- } else {
- PathUTF16.push_back(L'*');
- }
-
- // Get the first directory entry.
- WIN32_FIND_DATAW FirstFind;
- ScopedFindHandle FindHandle(::FindFirstFileExW(
- c_str(PathUTF16), FindExInfoBasic, &FirstFind, FindExSearchNameMatch,
- NULL, FIND_FIRST_EX_LARGE_FETCH));
- if (!FindHandle)
- return mapWindowsError(::GetLastError());
-
- size_t FilenameLen = ::wcslen(FirstFind.cFileName);
- while ((FilenameLen == 1 && FirstFind.cFileName[0] == L'.') ||
- (FilenameLen == 2 && FirstFind.cFileName[0] == L'.' &&
- FirstFind.cFileName[1] == L'.'))
- if (!::FindNextFileW(FindHandle, &FirstFind)) {
- DWORD LastError = ::GetLastError();
- // Check for end.
- if (LastError == ERROR_NO_MORE_FILES)
- return detail::directory_iterator_destruct(IT);
- return mapWindowsError(LastError);
- } else
- FilenameLen = ::wcslen(FirstFind.cFileName);
-
- // Construct the current directory entry.
- SmallString<128> DirectoryEntryNameUTF8;
- if (std::error_code EC =
- UTF16ToUTF8(FirstFind.cFileName, ::wcslen(FirstFind.cFileName),
- DirectoryEntryNameUTF8))
- return EC;
-
- IT.IterationHandle = intptr_t(FindHandle.take());
- SmallString<128> DirectoryEntryPath(Path);
- path::append(DirectoryEntryPath, DirectoryEntryNameUTF8);
- IT.CurrentEntry =
- directory_entry(DirectoryEntryPath, FollowSymlinks,
- file_type_from_attrs(FirstFind.dwFileAttributes),
- status_from_find_data(&FirstFind));
-
- return std::error_code();
-}
-
-std::error_code detail::directory_iterator_destruct(detail::DirIterState &IT) {
- if (IT.IterationHandle != 0)
- // Closes the handle if it's valid.
- ScopedFindHandle close(HANDLE(IT.IterationHandle));
- IT.IterationHandle = 0;
- IT.CurrentEntry = directory_entry();
- return std::error_code();
-}
-
-std::error_code detail::directory_iterator_increment(detail::DirIterState &IT) {
- WIN32_FIND_DATAW FindData;
- if (!::FindNextFileW(HANDLE(IT.IterationHandle), &FindData)) {
- DWORD LastError = ::GetLastError();
- // Check for end.
- if (LastError == ERROR_NO_MORE_FILES)
- return detail::directory_iterator_destruct(IT);
- return mapWindowsError(LastError);
- }
-
- size_t FilenameLen = ::wcslen(FindData.cFileName);
- if ((FilenameLen == 1 && FindData.cFileName[0] == L'.') ||
- (FilenameLen == 2 && FindData.cFileName[0] == L'.' &&
- FindData.cFileName[1] == L'.'))
- return directory_iterator_increment(IT);
-
- SmallString<128> DirectoryEntryPathUTF8;
- if (std::error_code EC =
- UTF16ToUTF8(FindData.cFileName, ::wcslen(FindData.cFileName),
- DirectoryEntryPathUTF8))
- return EC;
-
- IT.CurrentEntry.replace_filename(
- Twine(DirectoryEntryPathUTF8),
- file_type_from_attrs(FindData.dwFileAttributes),
- status_from_find_data(&FindData));
- return std::error_code();
-}
-
-ErrorOr<basic_file_status> directory_entry::status() const {
- return Status;
-}
-
-static std::error_code nativeFileToFd(Expected<HANDLE> H, int &ResultFD,
- OpenFlags Flags) {
- int CrtOpenFlags = 0;
- if (Flags & OF_Append)
- CrtOpenFlags |= _O_APPEND;
-
- if (Flags & OF_Text)
- CrtOpenFlags |= _O_TEXT;
-
- ResultFD = -1;
- if (!H)
- return errorToErrorCode(H.takeError());
-
- ResultFD = ::_open_osfhandle(intptr_t(*H), CrtOpenFlags);
- if (ResultFD == -1) {
- ::CloseHandle(*H);
- return mapWindowsError(ERROR_INVALID_HANDLE);
- }
- return std::error_code();
-}
-
-static DWORD nativeDisposition(CreationDisposition Disp, OpenFlags Flags) {
- // This is a compatibility hack. Really we should respect the creation
- // disposition, but a lot of old code relied on the implicit assumption that
- // OF_Append implied it would open an existing file. Since the disposition is
- // now explicit and defaults to CD_CreateAlways, this assumption would cause
- // any usage of OF_Append to append to a new file, even if the file already
- // existed. A better solution might have two new creation dispositions:
- // CD_AppendAlways and CD_AppendNew. This would also address the problem of
- // OF_Append being used on a read-only descriptor, which doesn't make sense.
- if (Flags & OF_Append)
- return OPEN_ALWAYS;
-
- switch (Disp) {
- case CD_CreateAlways:
- return CREATE_ALWAYS;
- case CD_CreateNew:
- return CREATE_NEW;
- case CD_OpenAlways:
- return OPEN_ALWAYS;
- case CD_OpenExisting:
- return OPEN_EXISTING;
- }
- llvm_unreachable("unreachable!");
-}
-
-static DWORD nativeAccess(FileAccess Access, OpenFlags Flags) {
- DWORD Result = 0;
- if (Access & FA_Read)
- Result |= GENERIC_READ;
- if (Access & FA_Write)
- Result |= GENERIC_WRITE;
- if (Flags & OF_Delete)
- Result |= DELETE;
- if (Flags & OF_UpdateAtime)
- Result |= FILE_WRITE_ATTRIBUTES;
- return Result;
-}
-
-static std::error_code openNativeFileInternal(const Twine &Name,
- file_t &ResultFile, DWORD Disp,
- DWORD Access, DWORD Flags,
- bool Inherit = false) {
- SmallVector<wchar_t, 128> PathUTF16;
- if (std::error_code EC = widenPath(Name, PathUTF16))
- return EC;
-
- SECURITY_ATTRIBUTES SA;
- SA.nLength = sizeof(SA);
- SA.lpSecurityDescriptor = nullptr;
- SA.bInheritHandle = Inherit;
-
- HANDLE H =
- ::CreateFileW(PathUTF16.begin(), Access,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &SA,
- Disp, Flags, NULL);
- if (H == INVALID_HANDLE_VALUE) {
- DWORD LastError = ::GetLastError();
- std::error_code EC = mapWindowsError(LastError);
- // Provide a better error message when trying to open directories.
- // This only runs if we failed to open the file, so there is probably
- // no performances issues.
- if (LastError != ERROR_ACCESS_DENIED)
- return EC;
- if (is_directory(Name))
- return make_error_code(errc::is_a_directory);
- return EC;
- }
- ResultFile = H;
- return std::error_code();
-}
-
-Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp,
- FileAccess Access, OpenFlags Flags,
- unsigned Mode) {
- // Verify that we don't have both "append" and "excl".
- assert((!(Disp == CD_CreateNew) || !(Flags & OF_Append)) &&
- "Cannot specify both 'CreateNew' and 'Append' file creation flags!");
-
- DWORD NativeDisp = nativeDisposition(Disp, Flags);
- DWORD NativeAccess = nativeAccess(Access, Flags);
-
- bool Inherit = false;
- if (Flags & OF_ChildInherit)
- Inherit = true;
-
- file_t Result;
- std::error_code EC = openNativeFileInternal(
- Name, Result, NativeDisp, NativeAccess, FILE_ATTRIBUTE_NORMAL, Inherit);
- if (EC)
- return errorCodeToError(EC);
-
- if (Flags & OF_UpdateAtime) {
- FILETIME FileTime;
- SYSTEMTIME SystemTime;
- GetSystemTime(&SystemTime);
- if (SystemTimeToFileTime(&SystemTime, &FileTime) == 0 ||
- SetFileTime(Result, NULL, &FileTime, NULL) == 0) {
- DWORD LastError = ::GetLastError();
- ::CloseHandle(Result);
- return errorCodeToError(mapWindowsError(LastError));
- }
- }
-
- if (Flags & OF_Delete) {
- if ((EC = setDeleteDisposition(Result, true))) {
- ::CloseHandle(Result);
- return errorCodeToError(EC);
- }
- }
- return Result;
-}
-
-std::error_code openFile(const Twine &Name, int &ResultFD,
- CreationDisposition Disp, FileAccess Access,
- OpenFlags Flags, unsigned int Mode) {
- Expected<file_t> Result = openNativeFile(Name, Disp, Access, Flags);
- if (!Result)
- return errorToErrorCode(Result.takeError());
-
- return nativeFileToFd(*Result, ResultFD, Flags);
-}
-
-static std::error_code directoryRealPath(const Twine &Name,
- SmallVectorImpl<char> &RealPath) {
- file_t File;
- std::error_code EC = openNativeFileInternal(
- Name, File, OPEN_EXISTING, GENERIC_READ, FILE_FLAG_BACKUP_SEMANTICS);
- if (EC)
- return EC;
-
- EC = realPathFromHandle(File, RealPath);
- ::CloseHandle(File);
- return EC;
-}
-
-std::error_code openFileForRead(const Twine &Name, int &ResultFD,
- OpenFlags Flags,
- SmallVectorImpl<char> *RealPath) {
- Expected<HANDLE> NativeFile = openNativeFileForRead(Name, Flags, RealPath);
- return nativeFileToFd(std::move(NativeFile), ResultFD, OF_None);
-}
-
-Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags,
- SmallVectorImpl<char> *RealPath) {
- Expected<file_t> Result =
- openNativeFile(Name, CD_OpenExisting, FA_Read, Flags);
-
- // Fetch the real name of the file, if the user asked
- if (Result && RealPath)
- realPathFromHandle(*Result, *RealPath);
-
- return Result;
-}
-
-void closeFile(file_t &F) {
- ::CloseHandle(F);
- F = kInvalidFile;
-}
-
-std::error_code remove_directories(const Twine &path, bool IgnoreErrors) {
- // Convert to utf-16.
- SmallVector<wchar_t, 128> Path16;
- std::error_code EC = widenPath(path, Path16);
- if (EC && !IgnoreErrors)
- return EC;
-
- // SHFileOperation() accepts a list of paths, and so must be double null-
- // terminated to indicate the end of the list. The buffer is already null
- // terminated, but since that null character is not considered part of the
- // vector's size, pushing another one will just consume that byte. So we
- // need to push 2 null terminators.
- Path16.push_back(0);
- Path16.push_back(0);
-
- SHFILEOPSTRUCTW shfos = {};
- shfos.wFunc = FO_DELETE;
- shfos.pFrom = Path16.data();
- shfos.fFlags = FOF_NO_UI;
-
- int result = ::SHFileOperationW(&shfos);
- if (result != 0 && !IgnoreErrors)
- return mapWindowsError(result);
- return std::error_code();
-}
-
-static void expandTildeExpr(SmallVectorImpl<char> &Path) {
- // Path does not begin with a tilde expression.
- if (Path.empty() || Path[0] != '~')
- return;
-
- StringRef PathStr(Path.begin(), Path.size());
- PathStr = PathStr.drop_front();
- StringRef Expr = PathStr.take_until([](char c) { return path::is_separator(c); });
-
- if (!Expr.empty()) {
- // This is probably a ~username/ expression. Don't support this on Windows.
- return;
- }
-
- SmallString<128> HomeDir;
- if (!path::home_directory(HomeDir)) {
- // For some reason we couldn't get the home directory. Just exit.
- return;
- }
-
- // Overwrite the first character and insert the rest.
- Path[0] = HomeDir[0];
- Path.insert(Path.begin() + 1, HomeDir.begin() + 1, HomeDir.end());
-}
-
-void expand_tilde(const Twine &path, SmallVectorImpl<char> &dest) {
- dest.clear();
- if (path.isTriviallyEmpty())
- return;
-
- path.toVector(dest);
- expandTildeExpr(dest);
-
- return;
-}
-
-std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest,
- bool expand_tilde) {
- dest.clear();
- if (path.isTriviallyEmpty())
- return std::error_code();
-
- if (expand_tilde) {
- SmallString<128> Storage;
- path.toVector(Storage);
- expandTildeExpr(Storage);
- return real_path(Storage, dest, false);
- }
-
- if (is_directory(path))
- return directoryRealPath(path, dest);
-
- int fd;
- if (std::error_code EC =
- llvm::sys::fs::openFileForRead(path, fd, OF_None, &dest))
- return EC;
- ::close(fd);
- return std::error_code();
-}
-
-} // end namespace fs
-
-namespace path {
-static bool getKnownFolderPath(KNOWNFOLDERID folderId,
- SmallVectorImpl<char> &result) {
- wchar_t *path = nullptr;
- if (::SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, nullptr, &path) != S_OK)
- return false;
-
- bool ok = !UTF16ToUTF8(path, ::wcslen(path), result);
- ::CoTaskMemFree(path);
- return ok;
-}
-
-bool home_directory(SmallVectorImpl<char> &result) {
- return getKnownFolderPath(FOLDERID_Profile, result);
-}
-
-static bool getTempDirEnvVar(const wchar_t *Var, SmallVectorImpl<char> &Res) {
- SmallVector<wchar_t, 1024> Buf;
- size_t Size = 1024;
- do {
- Buf.reserve(Size);
- Size = GetEnvironmentVariableW(Var, Buf.data(), Buf.capacity());
- if (Size == 0)
- return false;
-
- // Try again with larger buffer.
- } while (Size > Buf.capacity());
- Buf.set_size(Size);
-
- return !windows::UTF16ToUTF8(Buf.data(), Size, Res);
-}
-
-static bool getTempDirEnvVar(SmallVectorImpl<char> &Res) {
- const wchar_t *EnvironmentVariables[] = {L"TMP", L"TEMP", L"USERPROFILE"};
- for (auto *Env : EnvironmentVariables) {
- if (getTempDirEnvVar(Env, Res))
- return true;
- }
- return false;
-}
-
-void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) {
- (void)ErasedOnReboot;
- Result.clear();
-
- // Check whether the temporary directory is specified by an environment var.
- // This matches GetTempPath logic to some degree. GetTempPath is not used
- // directly as it cannot handle evn var longer than 130 chars on Windows 7
- // (fixed on Windows 8).
- if (getTempDirEnvVar(Result)) {
- assert(!Result.empty() && "Unexpected empty path");
- native(Result); // Some Unix-like shells use Unix path separator in $TMP.
- fs::make_absolute(Result); // Make it absolute if not already.
- return;
- }
-
- // Fall back to a system default.
- const char *DefaultResult = "C:\\Temp";
- Result.append(DefaultResult, DefaultResult + strlen(DefaultResult));
-}
-} // end namespace path
-
-namespace windows {
-std::error_code CodePageToUTF16(unsigned codepage,
- llvm::StringRef original,
- llvm::SmallVectorImpl<wchar_t> &utf16) {
- if (!original.empty()) {
- int len = ::MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, original.begin(),
- original.size(), utf16.begin(), 0);
-
- if (len == 0) {
- return mapWindowsError(::GetLastError());
- }
-
- utf16.reserve(len + 1);
- utf16.set_size(len);
-
- len = ::MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, original.begin(),
- original.size(), utf16.begin(), utf16.size());
-
- if (len == 0) {
- return mapWindowsError(::GetLastError());
- }
- }
-
- // Make utf16 null terminated.
- utf16.push_back(0);
- utf16.pop_back();
-
- return std::error_code();
-}
-
-std::error_code UTF8ToUTF16(llvm::StringRef utf8,
- llvm::SmallVectorImpl<wchar_t> &utf16) {
- return CodePageToUTF16(CP_UTF8, utf8, utf16);
-}
-
-std::error_code CurCPToUTF16(llvm::StringRef curcp,
- llvm::SmallVectorImpl<wchar_t> &utf16) {
- return CodePageToUTF16(CP_ACP, curcp, utf16);
-}
-
-static
-std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16,
- size_t utf16_len,
- llvm::SmallVectorImpl<char> &converted) {
- if (utf16_len) {
- // Get length.
- int len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, converted.begin(),
- 0, NULL, NULL);
-
- if (len == 0) {
- return mapWindowsError(::GetLastError());
- }
-
- converted.reserve(len);
- converted.set_size(len);
-
- // Now do the actual conversion.
- len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, converted.data(),
- converted.size(), NULL, NULL);
-
- if (len == 0) {
- return mapWindowsError(::GetLastError());
- }
- }
-
- // Make the new string null terminated.
- converted.push_back(0);
- converted.pop_back();
-
- return std::error_code();
-}
-
-std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
- llvm::SmallVectorImpl<char> &utf8) {
- return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8);
-}
-
-std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
- llvm::SmallVectorImpl<char> &curcp) {
- return UTF16ToCodePage(CP_ACP, utf16, utf16_len, curcp);
-}
-
-} // end namespace windows
-} // end namespace sys
-} // end namespace llvm
diff --git a/gnu/llvm/lib/Support/Windows/Process.inc b/gnu/llvm/lib/Support/Windows/Process.inc
deleted file mode 100644
index 2b2d7923143..00000000000
--- a/gnu/llvm/lib/Support/Windows/Process.inc
+++ /dev/null
@@ -1,486 +0,0 @@
-//===- Win32/Process.cpp - Win32 Process Implementation ------- -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides the Win32 specific implementation of the Process class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/StringSaver.h"
-#include "llvm/Support/WindowsError.h"
-#include <malloc.h>
-
-// The Windows.h header must be after LLVM and standard headers.
-#include "WindowsSupport.h"
-
-#include <direct.h>
-#include <io.h>
-#include <psapi.h>
-#include <shellapi.h>
-
-#if !defined(__MINGW32__)
- #pragma comment(lib, "psapi.lib")
- #pragma comment(lib, "shell32.lib")
-#endif
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only Win32 specific code
-//=== and must not be UNIX code
-//===----------------------------------------------------------------------===//
-
-#ifdef __MINGW32__
-// This ban should be lifted when MinGW 1.0+ has defined this value.
-# define _HEAPOK (-2)
-#endif
-
-using namespace llvm;
-
-// This function retrieves the page size using GetNativeSystemInfo() and is
-// present solely so it can be called once to initialize the self_process member
-// below.
-static unsigned computePageSize() {
- // GetNativeSystemInfo() provides the physical page size which may differ
- // from GetSystemInfo() in 32-bit applications running under WOW64.
- SYSTEM_INFO info;
- GetNativeSystemInfo(&info);
- // FIXME: FileOffset in MapViewOfFile() should be aligned to not dwPageSize,
- // but dwAllocationGranularity.
- return static_cast<unsigned>(info.dwPageSize);
-}
-
-unsigned Process::getPageSize() {
- static unsigned Ret = computePageSize();
- return Ret;
-}
-
-size_t
-Process::GetMallocUsage()
-{
- _HEAPINFO hinfo;
- hinfo._pentry = NULL;
-
- size_t size = 0;
-
- while (_heapwalk(&hinfo) == _HEAPOK)
- size += hinfo._size;
-
- return size;
-}
-
-void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time,
- std::chrono::nanoseconds &sys_time) {
- elapsed = std::chrono::system_clock::now();;
-
- FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
- if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
- &UserTime) == 0)
- return;
-
- user_time = toDuration(UserTime);
- sys_time = toDuration(KernelTime);
-}
-
-// Some LLVM programs such as bugpoint produce core files as a normal part of
-// their operation. To prevent the disk from filling up, this configuration
-// item does what's necessary to prevent their generation.
-void Process::PreventCoreFiles() {
- // Windows does have the concept of core files, called minidumps. However,
- // disabling minidumps for a particular application extends past the lifetime
- // of that application, which is the incorrect behavior for this API.
- // Additionally, the APIs require elevated privileges to disable and re-
- // enable minidumps, which makes this untenable. For more information, see
- // WerAddExcludedApplication and WerRemoveExcludedApplication (Vista and
- // later).
- //
- // Windows also has modal pop-up message boxes. As this method is used by
- // bugpoint, preventing these pop-ups is additionally important.
- SetErrorMode(SEM_FAILCRITICALERRORS |
- SEM_NOGPFAULTERRORBOX |
- SEM_NOOPENFILEERRORBOX);
-
- coreFilesPrevented = true;
-}
-
-/// Returns the environment variable \arg Name's value as a string encoded in
-/// UTF-8. \arg Name is assumed to be in UTF-8 encoding.
-Optional<std::string> Process::GetEnv(StringRef Name) {
- // Convert the argument to UTF-16 to pass it to _wgetenv().
- SmallVector<wchar_t, 128> NameUTF16;
- if (windows::UTF8ToUTF16(Name, NameUTF16))
- return None;
-
- // Environment variable can be encoded in non-UTF8 encoding, and there's no
- // way to know what the encoding is. The only reliable way to look up
- // multibyte environment variable is to use GetEnvironmentVariableW().
- SmallVector<wchar_t, MAX_PATH> Buf;
- size_t Size = MAX_PATH;
- do {
- Buf.reserve(Size);
- SetLastError(NO_ERROR);
- Size =
- GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity());
- if (Size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND)
- return None;
-
- // Try again with larger buffer.
- } while (Size > Buf.capacity());
- Buf.set_size(Size);
-
- // Convert the result from UTF-16 to UTF-8.
- SmallVector<char, MAX_PATH> Res;
- if (windows::UTF16ToUTF8(Buf.data(), Size, Res))
- return None;
- return std::string(Res.data());
-}
-
-/// Perform wildcard expansion of Arg, or just push it into Args if it doesn't
-/// have wildcards or doesn't match any files.
-static std::error_code WildcardExpand(StringRef Arg,
- SmallVectorImpl<const char *> &Args,
- StringSaver &Saver) {
- std::error_code EC;
-
- // Don't expand Arg if it does not contain any wildcard characters. This is
- // the common case. Also don't wildcard expand /?. Always treat it as an
- // option.
- if (Arg.find_first_of("*?") == StringRef::npos || Arg == "/?" ||
- Arg == "-?") {
- Args.push_back(Arg.data());
- return EC;
- }
-
- // Convert back to UTF-16 so we can call FindFirstFileW.
- SmallVector<wchar_t, MAX_PATH> ArgW;
- EC = windows::UTF8ToUTF16(Arg, ArgW);
- if (EC)
- return EC;
-
- // Search for matching files.
- // FIXME: This assumes the wildcard is only in the file name and not in the
- // directory portion of the file path. For example, it doesn't handle
- // "*\foo.c" nor "s?c\bar.cpp".
- WIN32_FIND_DATAW FileData;
- HANDLE FindHandle = FindFirstFileW(ArgW.data(), &FileData);
- if (FindHandle == INVALID_HANDLE_VALUE) {
- Args.push_back(Arg.data());
- return EC;
- }
-
- // Extract any directory part of the argument.
- SmallString<MAX_PATH> Dir = Arg;
- sys::path::remove_filename(Dir);
- const int DirSize = Dir.size();
-
- do {
- SmallString<MAX_PATH> FileName;
- EC = windows::UTF16ToUTF8(FileData.cFileName, wcslen(FileData.cFileName),
- FileName);
- if (EC)
- break;
-
- // Append FileName to Dir, and remove it afterwards.
- llvm::sys::path::append(Dir, FileName);
- Args.push_back(Saver.save(StringRef(Dir)).data());
- Dir.resize(DirSize);
- } while (FindNextFileW(FindHandle, &FileData));
-
- FindClose(FindHandle);
- return EC;
-}
-
-static std::error_code GetExecutableName(SmallVectorImpl<char> &Filename) {
- // The first argument may contain just the name of the executable (e.g.,
- // "clang") rather than the full path, so swap it with the full path.
- wchar_t ModuleName[MAX_PATH];
- size_t Length = ::GetModuleFileNameW(NULL, ModuleName, MAX_PATH);
- if (Length == 0 || Length == MAX_PATH) {
- return mapWindowsError(GetLastError());
- }
-
- // If the first argument is a shortened (8.3) name (which is possible even
- // if we got the module name), the driver will have trouble distinguishing it
- // (e.g., clang.exe v. clang++.exe), so expand it now.
- Length = GetLongPathNameW(ModuleName, ModuleName, MAX_PATH);
- if (Length == 0)
- return mapWindowsError(GetLastError());
- if (Length > MAX_PATH) {
- // We're not going to try to deal with paths longer than MAX_PATH, so we'll
- // treat this as an error. GetLastError() returns ERROR_SUCCESS, which
- // isn't useful, so we'll hardcode an appropriate error value.
- return mapWindowsError(ERROR_INSUFFICIENT_BUFFER);
- }
-
- std::error_code EC = windows::UTF16ToUTF8(ModuleName, Length, Filename);
- if (EC)
- return EC;
-
- StringRef Base = sys::path::filename(Filename.data());
- Filename.assign(Base.begin(), Base.end());
- return std::error_code();
-}
-
-std::error_code
-windows::GetCommandLineArguments(SmallVectorImpl<const char *> &Args,
- BumpPtrAllocator &Alloc) {
- const wchar_t *CmdW = GetCommandLineW();
- assert(CmdW);
- std::error_code EC;
- SmallString<MAX_PATH> Cmd;
- EC = windows::UTF16ToUTF8(CmdW, wcslen(CmdW), Cmd);
- if (EC)
- return EC;
-
- SmallVector<const char *, 20> TmpArgs;
- StringSaver Saver(Alloc);
- cl::TokenizeWindowsCommandLine(Cmd, Saver, TmpArgs, /*MarkEOLs=*/false);
-
- for (const char *Arg : TmpArgs) {
- EC = WildcardExpand(Arg, Args, Saver);
- if (EC)
- return EC;
- }
-
- SmallVector<char, MAX_PATH> Arg0(Args[0], Args[0] + strlen(Args[0]));
- SmallVector<char, MAX_PATH> Filename;
- sys::path::remove_filename(Arg0);
- EC = GetExecutableName(Filename);
- if (EC)
- return EC;
- sys::path::append(Arg0, Filename);
- Args[0] = Saver.save(Arg0).data();
- return std::error_code();
-}
-
-std::error_code Process::FixupStandardFileDescriptors() {
- return std::error_code();
-}
-
-std::error_code Process::SafelyCloseFileDescriptor(int FD) {
- if (::close(FD) < 0)
- return std::error_code(errno, std::generic_category());
- return std::error_code();
-}
-
-bool Process::StandardInIsUserInput() {
- return FileDescriptorIsDisplayed(0);
-}
-
-bool Process::StandardOutIsDisplayed() {
- return FileDescriptorIsDisplayed(1);
-}
-
-bool Process::StandardErrIsDisplayed() {
- return FileDescriptorIsDisplayed(2);
-}
-
-bool Process::FileDescriptorIsDisplayed(int fd) {
- DWORD Mode; // Unused
- return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
-}
-
-unsigned Process::StandardOutColumns() {
- unsigned Columns = 0;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
- Columns = csbi.dwSize.X;
- return Columns;
-}
-
-unsigned Process::StandardErrColumns() {
- unsigned Columns = 0;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi))
- Columns = csbi.dwSize.X;
- return Columns;
-}
-
-// The terminal always has colors.
-bool Process::FileDescriptorHasColors(int fd) {
- return FileDescriptorIsDisplayed(fd);
-}
-
-bool Process::StandardOutHasColors() {
- return FileDescriptorHasColors(1);
-}
-
-bool Process::StandardErrHasColors() {
- return FileDescriptorHasColors(2);
-}
-
-static bool UseANSI = false;
-void Process::UseANSIEscapeCodes(bool enable) {
-#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
- if (enable) {
- HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
- DWORD Mode;
- GetConsoleMode(Console, &Mode);
- Mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
- SetConsoleMode(Console, Mode);
- }
-#endif
- UseANSI = enable;
-}
-
-namespace {
-class DefaultColors
-{
- private:
- WORD defaultColor;
- public:
- DefaultColors()
- :defaultColor(GetCurrentColor()) {}
- static unsigned GetCurrentColor() {
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
- return csbi.wAttributes;
- return 0;
- }
- WORD operator()() const { return defaultColor; }
-};
-
-DefaultColors defaultColors;
-
-WORD fg_color(WORD color) {
- return color & (FOREGROUND_BLUE | FOREGROUND_GREEN |
- FOREGROUND_INTENSITY | FOREGROUND_RED);
-}
-
-WORD bg_color(WORD color) {
- return color & (BACKGROUND_BLUE | BACKGROUND_GREEN |
- BACKGROUND_INTENSITY | BACKGROUND_RED);
-}
-}
-
-bool Process::ColorNeedsFlush() {
- return !UseANSI;
-}
-
-const char *Process::OutputBold(bool bg) {
- if (UseANSI) return "\033[1m";
-
- WORD colors = DefaultColors::GetCurrentColor();
- if (bg)
- colors |= BACKGROUND_INTENSITY;
- else
- colors |= FOREGROUND_INTENSITY;
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
- return 0;
-}
-
-const char *Process::OutputColor(char code, bool bold, bool bg) {
- if (UseANSI) return colorcodes[bg?1:0][bold?1:0][code&7];
-
- WORD current = DefaultColors::GetCurrentColor();
- WORD colors;
- if (bg) {
- colors = ((code&1) ? BACKGROUND_RED : 0) |
- ((code&2) ? BACKGROUND_GREEN : 0 ) |
- ((code&4) ? BACKGROUND_BLUE : 0);
- if (bold)
- colors |= BACKGROUND_INTENSITY;
- colors |= fg_color(current);
- } else {
- colors = ((code&1) ? FOREGROUND_RED : 0) |
- ((code&2) ? FOREGROUND_GREEN : 0 ) |
- ((code&4) ? FOREGROUND_BLUE : 0);
- if (bold)
- colors |= FOREGROUND_INTENSITY;
- colors |= bg_color(current);
- }
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
- return 0;
-}
-
-static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) {
- CONSOLE_SCREEN_BUFFER_INFO info;
- GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
- return info.wAttributes;
-}
-
-const char *Process::OutputReverse() {
- if (UseANSI) return "\033[7m";
-
- const WORD attributes
- = GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE));
-
- const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
- FOREGROUND_RED | FOREGROUND_INTENSITY;
- const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
- BACKGROUND_RED | BACKGROUND_INTENSITY;
- const WORD color_mask = foreground_mask | background_mask;
-
- WORD new_attributes =
- ((attributes & FOREGROUND_BLUE )?BACKGROUND_BLUE :0) |
- ((attributes & FOREGROUND_GREEN )?BACKGROUND_GREEN :0) |
- ((attributes & FOREGROUND_RED )?BACKGROUND_RED :0) |
- ((attributes & FOREGROUND_INTENSITY)?BACKGROUND_INTENSITY:0) |
- ((attributes & BACKGROUND_BLUE )?FOREGROUND_BLUE :0) |
- ((attributes & BACKGROUND_GREEN )?FOREGROUND_GREEN :0) |
- ((attributes & BACKGROUND_RED )?FOREGROUND_RED :0) |
- ((attributes & BACKGROUND_INTENSITY)?FOREGROUND_INTENSITY:0) |
- 0;
- new_attributes = (attributes & ~color_mask) | (new_attributes & color_mask);
-
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), new_attributes);
- return 0;
-}
-
-const char *Process::ResetColor() {
- if (UseANSI) return "\033[0m";
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
- return 0;
-}
-
-// Include GetLastError() in a fatal error message.
-static void ReportLastErrorFatal(const char *Msg) {
- std::string ErrMsg;
- MakeErrMsg(&ErrMsg, Msg);
- report_fatal_error(ErrMsg);
-}
-
-unsigned Process::GetRandomNumber() {
- HCRYPTPROV HCPC;
- if (!::CryptAcquireContextW(&HCPC, NULL, NULL, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT))
- ReportLastErrorFatal("Could not acquire a cryptographic context");
-
- ScopedCryptContext CryptoProvider(HCPC);
- unsigned Ret;
- if (!::CryptGenRandom(CryptoProvider, sizeof(Ret),
- reinterpret_cast<BYTE *>(&Ret)))
- ReportLastErrorFatal("Could not generate a random number");
- return Ret;
-}
-
-typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
-#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-
-llvm::VersionTuple llvm::GetWindowsOSVersion() {
- HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
- if (hMod) {
- auto getVer = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
- if (getVer) {
- RTL_OSVERSIONINFOEXW info{};
- info.dwOSVersionInfoSize = sizeof(info);
- if (getVer((PRTL_OSVERSIONINFOW)&info) == STATUS_SUCCESS) {
- return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, 0,
- info.dwBuildNumber);
- }
- }
- }
- return llvm::VersionTuple(0, 0, 0, 0);
-}
-
-bool llvm::RunningWindows8OrGreater() {
- // Windows 8 is version 6.2, service pack 0.
- return GetWindowsOSVersion() >= llvm::VersionTuple(6, 2, 0, 0);
-}
diff --git a/gnu/llvm/lib/Support/Windows/Program.inc b/gnu/llvm/lib/Support/Windows/Program.inc
deleted file mode 100644
index c037956603f..00000000000
--- a/gnu/llvm/lib/Support/Windows/Program.inc
+++ /dev/null
@@ -1,524 +0,0 @@
-//===- Win32/Program.cpp - Win32 Program Implementation ------- -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides the Win32 specific implementation of the Program class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "WindowsSupport.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/WindowsError.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstdio>
-#include <fcntl.h>
-#include <io.h>
-#include <malloc.h>
-#include <numeric>
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only Win32 specific code
-//=== and must not be UNIX code
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
-
-ProcessInfo::ProcessInfo() : Pid(0), Process(0), ReturnCode(0) {}
-
-ErrorOr<std::string> sys::findProgramByName(StringRef Name,
- ArrayRef<StringRef> Paths) {
- assert(!Name.empty() && "Must have a name!");
-
- if (Name.find_first_of("/\\") != StringRef::npos)
- return std::string(Name);
-
- const wchar_t *Path = nullptr;
- std::wstring PathStorage;
- if (!Paths.empty()) {
- PathStorage.reserve(Paths.size() * MAX_PATH);
- for (unsigned i = 0; i < Paths.size(); ++i) {
- if (i)
- PathStorage.push_back(L';');
- StringRef P = Paths[i];
- SmallVector<wchar_t, MAX_PATH> TmpPath;
- if (std::error_code EC = windows::UTF8ToUTF16(P, TmpPath))
- return EC;
- PathStorage.append(TmpPath.begin(), TmpPath.end());
- }
- Path = PathStorage.c_str();
- }
-
- SmallVector<wchar_t, MAX_PATH> U16Name;
- if (std::error_code EC = windows::UTF8ToUTF16(Name, U16Name))
- return EC;
-
- SmallVector<StringRef, 12> PathExts;
- PathExts.push_back("");
- PathExts.push_back(".exe"); // FIXME: This must be in %PATHEXT%.
- if (const char *PathExtEnv = std::getenv("PATHEXT"))
- SplitString(PathExtEnv, PathExts, ";");
-
- SmallVector<wchar_t, MAX_PATH> U16Result;
- DWORD Len = MAX_PATH;
- for (StringRef Ext : PathExts) {
- SmallVector<wchar_t, MAX_PATH> U16Ext;
- if (std::error_code EC = windows::UTF8ToUTF16(Ext, U16Ext))
- return EC;
-
- do {
- U16Result.reserve(Len);
- // Lets attach the extension manually. That is needed for files
- // with a point in name like aaa.bbb. SearchPathW will not add extension
- // from its argument to such files because it thinks they already had one.
- SmallVector<wchar_t, MAX_PATH> U16NameExt;
- if (std::error_code EC =
- windows::UTF8ToUTF16(Twine(Name + Ext).str(), U16NameExt))
- return EC;
-
- Len = ::SearchPathW(Path, c_str(U16NameExt), nullptr,
- U16Result.capacity(), U16Result.data(), nullptr);
- } while (Len > U16Result.capacity());
-
- if (Len != 0)
- break; // Found it.
- }
-
- if (Len == 0)
- return mapWindowsError(::GetLastError());
-
- U16Result.set_size(Len);
-
- SmallVector<char, MAX_PATH> U8Result;
- if (std::error_code EC =
- windows::UTF16ToUTF8(U16Result.data(), U16Result.size(), U8Result))
- return EC;
-
- return std::string(U8Result.begin(), U8Result.end());
-}
-
-bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix) {
- if (!ErrMsg)
- return true;
- char *buffer = NULL;
- DWORD LastError = GetLastError();
- DWORD R = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_MAX_WIDTH_MASK,
- NULL, LastError, 0, (LPSTR)&buffer, 1, NULL);
- if (R)
- *ErrMsg = prefix + ": " + buffer;
- else
- *ErrMsg = prefix + ": Unknown error";
- *ErrMsg += " (0x" + llvm::utohexstr(LastError) + ")";
-
- LocalFree(buffer);
- return R != 0;
-}
-
-static HANDLE RedirectIO(Optional<StringRef> Path, int fd,
- std::string *ErrMsg) {
- HANDLE h;
- if (!Path) {
- if (!DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd),
- GetCurrentProcess(), &h,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- return INVALID_HANDLE_VALUE;
- return h;
- }
-
- std::string fname;
- if (Path->empty())
- fname = "NUL";
- else
- fname = *Path;
-
- SECURITY_ATTRIBUTES sa;
- sa.nLength = sizeof(sa);
- sa.lpSecurityDescriptor = 0;
- sa.bInheritHandle = TRUE;
-
- SmallVector<wchar_t, 128> fnameUnicode;
- if (Path->empty()) {
- // Don't play long-path tricks on "NUL".
- if (windows::UTF8ToUTF16(fname, fnameUnicode))
- return INVALID_HANDLE_VALUE;
- } else {
- if (path::widenPath(fname, fnameUnicode))
- return INVALID_HANDLE_VALUE;
- }
- h = CreateFileW(fnameUnicode.data(), fd ? GENERIC_WRITE : GENERIC_READ,
- FILE_SHARE_READ, &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- MakeErrMsg(ErrMsg, fname + ": Can't open file for " +
- (fd ? "input" : "output"));
- }
-
- return h;
-}
-
-}
-
-static bool Execute(ProcessInfo &PI, StringRef Program,
- ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
- ArrayRef<Optional<StringRef>> Redirects,
- unsigned MemoryLimit, std::string *ErrMsg) {
- if (!sys::fs::can_execute(Program)) {
- if (ErrMsg)
- *ErrMsg = "program not executable";
- return false;
- }
-
- // can_execute may succeed by looking at Program + ".exe". CreateProcessW
- // will implicitly add the .exe if we provide a command line without an
- // executable path, but since we use an explicit executable, we have to add
- // ".exe" ourselves.
- SmallString<64> ProgramStorage;
- if (!sys::fs::exists(Program))
- Program = Twine(Program + ".exe").toStringRef(ProgramStorage);
-
- // Windows wants a command line, not an array of args, to pass to the new
- // process. We have to concatenate them all, while quoting the args that
- // have embedded spaces (or are empty).
- std::string Command = flattenWindowsCommandLine(Args);
-
- // The pointer to the environment block for the new process.
- std::vector<wchar_t> EnvBlock;
-
- if (Env) {
- // An environment block consists of a null-terminated block of
- // null-terminated strings. Convert the array of environment variables to
- // an environment block by concatenating them.
- for (const auto E : *Env) {
- SmallVector<wchar_t, MAX_PATH> EnvString;
- if (std::error_code ec = windows::UTF8ToUTF16(E, EnvString)) {
- SetLastError(ec.value());
- MakeErrMsg(ErrMsg, "Unable to convert environment variable to UTF-16");
- return false;
- }
-
- EnvBlock.insert(EnvBlock.end(), EnvString.begin(), EnvString.end());
- EnvBlock.push_back(0);
- }
- EnvBlock.push_back(0);
- }
-
- // Create a child process.
- STARTUPINFOW si;
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(si);
- si.hStdInput = INVALID_HANDLE_VALUE;
- si.hStdOutput = INVALID_HANDLE_VALUE;
- si.hStdError = INVALID_HANDLE_VALUE;
-
- if (!Redirects.empty()) {
- si.dwFlags = STARTF_USESTDHANDLES;
-
- si.hStdInput = RedirectIO(Redirects[0], 0, ErrMsg);
- if (si.hStdInput == INVALID_HANDLE_VALUE) {
- MakeErrMsg(ErrMsg, "can't redirect stdin");
- return false;
- }
- si.hStdOutput = RedirectIO(Redirects[1], 1, ErrMsg);
- if (si.hStdOutput == INVALID_HANDLE_VALUE) {
- CloseHandle(si.hStdInput);
- MakeErrMsg(ErrMsg, "can't redirect stdout");
- return false;
- }
- if (Redirects[1] && Redirects[2] && *Redirects[1] == *Redirects[2]) {
- // If stdout and stderr should go to the same place, redirect stderr
- // to the handle already open for stdout.
- if (!DuplicateHandle(GetCurrentProcess(), si.hStdOutput,
- GetCurrentProcess(), &si.hStdError,
- 0, TRUE, DUPLICATE_SAME_ACCESS)) {
- CloseHandle(si.hStdInput);
- CloseHandle(si.hStdOutput);
- MakeErrMsg(ErrMsg, "can't dup stderr to stdout");
- return false;
- }
- } else {
- // Just redirect stderr
- si.hStdError = RedirectIO(Redirects[2], 2, ErrMsg);
- if (si.hStdError == INVALID_HANDLE_VALUE) {
- CloseHandle(si.hStdInput);
- CloseHandle(si.hStdOutput);
- MakeErrMsg(ErrMsg, "can't redirect stderr");
- return false;
- }
- }
- }
-
- PROCESS_INFORMATION pi;
- memset(&pi, 0, sizeof(pi));
-
- fflush(stdout);
- fflush(stderr);
-
- SmallVector<wchar_t, MAX_PATH> ProgramUtf16;
- if (std::error_code ec = path::widenPath(Program, ProgramUtf16)) {
- SetLastError(ec.value());
- MakeErrMsg(ErrMsg,
- std::string("Unable to convert application name to UTF-16"));
- return false;
- }
-
- SmallVector<wchar_t, MAX_PATH> CommandUtf16;
- if (std::error_code ec = windows::UTF8ToUTF16(Command, CommandUtf16)) {
- SetLastError(ec.value());
- MakeErrMsg(ErrMsg,
- std::string("Unable to convert command-line to UTF-16"));
- return false;
- }
-
- BOOL rc = CreateProcessW(ProgramUtf16.data(), CommandUtf16.data(), 0, 0,
- TRUE, CREATE_UNICODE_ENVIRONMENT,
- EnvBlock.empty() ? 0 : EnvBlock.data(), 0, &si,
- &pi);
- DWORD err = GetLastError();
-
- // Regardless of whether the process got created or not, we are done with
- // the handles we created for it to inherit.
- CloseHandle(si.hStdInput);
- CloseHandle(si.hStdOutput);
- CloseHandle(si.hStdError);
-
- // Now return an error if the process didn't get created.
- if (!rc) {
- SetLastError(err);
- MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") +
- Program.str() + "'");
- return false;
- }
-
- PI.Pid = pi.dwProcessId;
- PI.Process = pi.hProcess;
-
- // Make sure these get closed no matter what.
- ScopedCommonHandle hThread(pi.hThread);
-
- // Assign the process to a job if a memory limit is defined.
- ScopedJobHandle hJob;
- if (MemoryLimit != 0) {
- hJob = CreateJobObjectW(0, 0);
- bool success = false;
- if (hJob) {
- JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
- memset(&jeli, 0, sizeof(jeli));
- jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
- jeli.ProcessMemoryLimit = uintptr_t(MemoryLimit) * 1048576;
- if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation,
- &jeli, sizeof(jeli))) {
- if (AssignProcessToJobObject(hJob, pi.hProcess))
- success = true;
- }
- }
- if (!success) {
- SetLastError(GetLastError());
- MakeErrMsg(ErrMsg, std::string("Unable to set memory limit"));
- TerminateProcess(pi.hProcess, 1);
- WaitForSingleObject(pi.hProcess, INFINITE);
- return false;
- }
- }
-
- return true;
-}
-
-static bool argNeedsQuotes(StringRef Arg) {
- if (Arg.empty())
- return true;
- return StringRef::npos != Arg.find_first_of("\t \"&\'()*<>\\`^|\n");
-}
-
-static std::string quoteSingleArg(StringRef Arg) {
- std::string Result;
- Result.push_back('"');
-
- while (!Arg.empty()) {
- size_t FirstNonBackslash = Arg.find_first_not_of('\\');
- size_t BackslashCount = FirstNonBackslash;
- if (FirstNonBackslash == StringRef::npos) {
- // The entire remainder of the argument is backslashes. Escape all of
- // them and just early out.
- BackslashCount = Arg.size();
- Result.append(BackslashCount * 2, '\\');
- break;
- }
-
- if (Arg[FirstNonBackslash] == '\"') {
- // This is an embedded quote. Escape all preceding backslashes, then
- // add one additional backslash to escape the quote.
- Result.append(BackslashCount * 2 + 1, '\\');
- Result.push_back('\"');
- } else {
- // This is just a normal character. Don't escape any of the preceding
- // backslashes, just append them as they are and then append the
- // character.
- Result.append(BackslashCount, '\\');
- Result.push_back(Arg[FirstNonBackslash]);
- }
-
- // Drop all the backslashes, plus the following character.
- Arg = Arg.drop_front(FirstNonBackslash + 1);
- }
-
- Result.push_back('"');
- return Result;
-}
-
-namespace llvm {
-std::string sys::flattenWindowsCommandLine(ArrayRef<StringRef> Args) {
- std::string Command;
- for (StringRef Arg : Args) {
- if (argNeedsQuotes(Arg))
- Command += quoteSingleArg(Arg);
- else
- Command += Arg;
-
- Command.push_back(' ');
- }
-
- return Command;
-}
-
-ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
- bool WaitUntilChildTerminates, std::string *ErrMsg) {
- assert(PI.Pid && "invalid pid to wait on, process not started?");
- assert((PI.Process && PI.Process != INVALID_HANDLE_VALUE) &&
- "invalid process handle to wait on, process not started?");
- DWORD milliSecondsToWait = 0;
- if (WaitUntilChildTerminates)
- milliSecondsToWait = INFINITE;
- else if (SecondsToWait > 0)
- milliSecondsToWait = SecondsToWait * 1000;
-
- ProcessInfo WaitResult = PI;
- DWORD WaitStatus = WaitForSingleObject(PI.Process, milliSecondsToWait);
- if (WaitStatus == WAIT_TIMEOUT) {
- if (SecondsToWait) {
- if (!TerminateProcess(PI.Process, 1)) {
- if (ErrMsg)
- MakeErrMsg(ErrMsg, "Failed to terminate timed-out program");
-
- // -2 indicates a crash or timeout as opposed to failure to execute.
- WaitResult.ReturnCode = -2;
- CloseHandle(PI.Process);
- return WaitResult;
- }
- WaitForSingleObject(PI.Process, INFINITE);
- CloseHandle(PI.Process);
- } else {
- // Non-blocking wait.
- return ProcessInfo();
- }
- }
-
- // Get its exit status.
- DWORD status;
- BOOL rc = GetExitCodeProcess(PI.Process, &status);
- DWORD err = GetLastError();
- if (err != ERROR_INVALID_HANDLE)
- CloseHandle(PI.Process);
-
- if (!rc) {
- SetLastError(err);
- if (ErrMsg)
- MakeErrMsg(ErrMsg, "Failed getting status for program");
-
- // -2 indicates a crash or timeout as opposed to failure to execute.
- WaitResult.ReturnCode = -2;
- return WaitResult;
- }
-
- if (!status)
- return WaitResult;
-
- // Pass 10(Warning) and 11(Error) to the callee as negative value.
- if ((status & 0xBFFF0000U) == 0x80000000U)
- WaitResult.ReturnCode = static_cast<int>(status);
- else if (status & 0xFF)
- WaitResult.ReturnCode = status & 0x7FFFFFFF;
- else
- WaitResult.ReturnCode = 1;
-
- return WaitResult;
-}
-
-std::error_code sys::ChangeStdinToBinary() {
- int result = _setmode(_fileno(stdin), _O_BINARY);
- if (result == -1)
- return std::error_code(errno, std::generic_category());
- return std::error_code();
-}
-
-std::error_code sys::ChangeStdoutToBinary() {
- int result = _setmode(_fileno(stdout), _O_BINARY);
- if (result == -1)
- return std::error_code(errno, std::generic_category());
- return std::error_code();
-}
-
-std::error_code
-llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
- WindowsEncodingMethod Encoding) {
- std::error_code EC;
- llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::F_Text);
- if (EC)
- return EC;
-
- if (Encoding == WEM_UTF8) {
- OS << Contents;
- } else if (Encoding == WEM_CurrentCodePage) {
- SmallVector<wchar_t, 1> ArgsUTF16;
- SmallVector<char, 1> ArgsCurCP;
-
- if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16)))
- return EC;
-
- if ((EC = windows::UTF16ToCurCP(
- ArgsUTF16.data(), ArgsUTF16.size(), ArgsCurCP)))
- return EC;
-
- OS.write(ArgsCurCP.data(), ArgsCurCP.size());
- } else if (Encoding == WEM_UTF16) {
- SmallVector<wchar_t, 1> ArgsUTF16;
-
- if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16)))
- return EC;
-
- // Endianness guessing
- char BOM[2];
- uint16_t src = UNI_UTF16_BYTE_ORDER_MARK_NATIVE;
- memcpy(BOM, &src, 2);
- OS.write(BOM, 2);
- OS.write((char *)ArgsUTF16.data(), ArgsUTF16.size() << 1);
- } else {
- llvm_unreachable("Unknown encoding");
- }
-
- if (OS.has_error())
- return make_error_code(errc::io_error);
-
- return EC;
-}
-
-bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program,
- ArrayRef<StringRef> Args) {
- // The documented max length of the command line passed to CreateProcess.
- static const size_t MaxCommandStringLength = 32768;
- SmallVector<StringRef, 8> FullArgs;
- FullArgs.push_back(Program);
- FullArgs.append(Args.begin(), Args.end());
- std::string Result = flattenWindowsCommandLine(FullArgs);
- return (Result.size() + 1) <= MaxCommandStringLength;
-}
-}
diff --git a/gnu/llvm/lib/Support/Windows/RWMutex.inc b/gnu/llvm/lib/Support/Windows/RWMutex.inc
deleted file mode 100644
index 5eb9351eee5..00000000000
--- a/gnu/llvm/lib/Support/Windows/RWMutex.inc
+++ /dev/null
@@ -1,129 +0,0 @@
-//= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Win32 specific (non-pthread) RWMutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic Win32 code that
-//=== is guaranteed to work on *all* Win32 variants.
-//===----------------------------------------------------------------------===//
-
-#include "WindowsSupport.h"
-
-namespace llvm {
-
-// Windows has slim read-writer lock support on Vista and higher, so we
-// will attempt to load the APIs. If they exist, we will use them, and
-// if not, we will fall back on critical sections. When we drop support
-// for XP, we can stop lazy-loading these APIs and just use them directly.
-#if defined(__MINGW32__)
- // Taken from WinNT.h
- typedef struct _RTL_SRWLOCK {
- PVOID Ptr;
- } RTL_SRWLOCK, *PRTL_SRWLOCK;
-
- // Taken from WinBase.h
- typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
-#endif
-
-static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL;
-
-static bool sHasSRW = false;
-
-static bool loadSRW() {
- static bool sChecked = false;
- if (!sChecked) {
- sChecked = true;
-
- if (HMODULE hLib = ::GetModuleHandleW(L"Kernel32.dll")) {
- fpInitializeSRWLock =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "InitializeSRWLock");
- fpAcquireSRWLockExclusive =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "AcquireSRWLockExclusive");
- fpAcquireSRWLockShared =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "AcquireSRWLockShared");
- fpReleaseSRWLockExclusive =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "ReleaseSRWLockExclusive");
- fpReleaseSRWLockShared =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "ReleaseSRWLockShared");
-
- if (fpInitializeSRWLock != NULL) {
- sHasSRW = true;
- }
- }
- }
- return sHasSRW;
-}
-
-sys::RWMutexImpl::RWMutexImpl() {
- if (loadSRW()) {
- data_ = safe_calloc(1, sizeof(SRWLOCK));
- fpInitializeSRWLock(static_cast<PSRWLOCK>(data_));
- } else {
- data_ = safe_calloc(1, sizeof(CRITICAL_SECTION));
- InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
-}
-
-sys::RWMutexImpl::~RWMutexImpl() {
- if (!sHasSRW)
- DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- // Nothing to do in the case of slim reader/writers except free the memory.
- free(data_);
-}
-
-bool sys::RWMutexImpl::reader_acquire() {
- if (sHasSRW) {
- fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_));
- } else {
- EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-bool sys::RWMutexImpl::reader_release() {
- if (sHasSRW) {
- fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_));
- } else {
- LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-bool sys::RWMutexImpl::writer_acquire() {
- if (sHasSRW) {
- fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_));
- } else {
- EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-bool sys::RWMutexImpl::writer_release() {
- if (sHasSRW) {
- fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_));
- } else {
- LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-
-}
diff --git a/gnu/llvm/lib/Support/Windows/Signals.inc b/gnu/llvm/lib/Support/Windows/Signals.inc
deleted file mode 100644
index 41eb5e593aa..00000000000
--- a/gnu/llvm/lib/Support/Windows/Signals.inc
+++ /dev/null
@@ -1,871 +0,0 @@
-//===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides the Win32 specific implementation of the Signals class.
-//
-//===----------------------------------------------------------------------===//
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/WindowsError.h"
-#include <algorithm>
-#include <io.h>
-#include <signal.h>
-#include <stdio.h>
-
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-
-// The Windows.h header must be after LLVM and standard headers.
-#include "WindowsSupport.h"
-
-#ifdef __MINGW32__
- #include <imagehlp.h>
-#else
- #include <crtdbg.h>
- #include <dbghelp.h>
-#endif
-#include <psapi.h>
-
-#ifdef _MSC_VER
- #pragma comment(lib, "psapi.lib")
-#elif __MINGW32__
- // The version of g++ that comes with MinGW does *not* properly understand
- // the ll format specifier for printf. However, MinGW passes the format
- // specifiers on to the MSVCRT entirely, and the CRT understands the ll
- // specifier. So these warnings are spurious in this case. Since we compile
- // with -Wall, this will generate these warnings which should be ignored. So
- // we will turn off the warnings for this just file. However, MinGW also does
- // not support push and pop for diagnostics, so we have to manually turn it
- // back on at the end of the file.
- #pragma GCC diagnostic ignored "-Wformat"
- #pragma GCC diagnostic ignored "-Wformat-extra-args"
-
- #if !defined(__MINGW64_VERSION_MAJOR)
- // MinGW.org does not have updated support for the 64-bit versions of the
- // DebugHlp APIs. So we will have to load them manually. The structures and
- // method signatures were pulled from DbgHelp.h in the Windows Platform SDK,
- // and adjusted for brevity.
- typedef struct _IMAGEHLP_LINE64 {
- DWORD SizeOfStruct;
- PVOID Key;
- DWORD LineNumber;
- PCHAR FileName;
- DWORD64 Address;
- } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
-
- typedef struct _IMAGEHLP_SYMBOL64 {
- DWORD SizeOfStruct;
- DWORD64 Address;
- DWORD Size;
- DWORD Flags;
- DWORD MaxNameLength;
- CHAR Name[1];
- } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;
-
- typedef struct _tagADDRESS64 {
- DWORD64 Offset;
- WORD Segment;
- ADDRESS_MODE Mode;
- } ADDRESS64, *LPADDRESS64;
-
- typedef struct _KDHELP64 {
- DWORD64 Thread;
- DWORD ThCallbackStack;
- DWORD ThCallbackBStore;
- DWORD NextCallback;
- DWORD FramePointer;
- DWORD64 KiCallUserMode;
- DWORD64 KeUserCallbackDispatcher;
- DWORD64 SystemRangeStart;
- DWORD64 KiUserExceptionDispatcher;
- DWORD64 StackBase;
- DWORD64 StackLimit;
- DWORD64 Reserved[5];
- } KDHELP64, *PKDHELP64;
-
- typedef struct _tagSTACKFRAME64 {
- ADDRESS64 AddrPC;
- ADDRESS64 AddrReturn;
- ADDRESS64 AddrFrame;
- ADDRESS64 AddrStack;
- ADDRESS64 AddrBStore;
- PVOID FuncTableEntry;
- DWORD64 Params[4];
- BOOL Far;
- BOOL Virtual;
- DWORD64 Reserved[3];
- KDHELP64 KdHelp;
- } STACKFRAME64, *LPSTACKFRAME64;
- #endif // !defined(__MINGW64_VERSION_MAJOR)
-#endif // __MINGW32__
-
-typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess,
- DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize,
- LPDWORD lpNumberOfBytesRead);
-
-typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess,
- DWORD64 AddrBase);
-
-typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,
- DWORD64 Address);
-
-typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,
- HANDLE hThread, LPADDRESS64 lpaddr);
-
-typedef BOOL(WINAPI *fpMiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
- PMINIDUMP_EXCEPTION_INFORMATION,
- PMINIDUMP_USER_STREAM_INFORMATION,
- PMINIDUMP_CALLBACK_INFORMATION);
-static fpMiniDumpWriteDump fMiniDumpWriteDump;
-
-typedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64,
- PVOID, PREAD_PROCESS_MEMORY_ROUTINE64,
- PFUNCTION_TABLE_ACCESS_ROUTINE64,
- PGET_MODULE_BASE_ROUTINE64,
- PTRANSLATE_ADDRESS_ROUTINE64);
-static fpStackWalk64 fStackWalk64;
-
-typedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64);
-static fpSymGetModuleBase64 fSymGetModuleBase64;
-
-typedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64,
- PDWORD64, PIMAGEHLP_SYMBOL64);
-static fpSymGetSymFromAddr64 fSymGetSymFromAddr64;
-
-typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64,
- PDWORD, PIMAGEHLP_LINE64);
-static fpSymGetLineFromAddr64 fSymGetLineFromAddr64;
-
-typedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64 dwAddr,
- PIMAGEHLP_MODULE64 ModuleInfo);
-static fpSymGetModuleInfo64 fSymGetModuleInfo64;
-
-typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64);
-static fpSymFunctionTableAccess64 fSymFunctionTableAccess64;
-
-typedef DWORD (WINAPI *fpSymSetOptions)(DWORD);
-static fpSymSetOptions fSymSetOptions;
-
-typedef BOOL (WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL);
-static fpSymInitialize fSymInitialize;
-
-typedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID);
-static fpEnumerateLoadedModules fEnumerateLoadedModules;
-
-static bool load64BitDebugHelp(void) {
- HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
- if (hLib) {
- fMiniDumpWriteDump = (fpMiniDumpWriteDump)
- ::GetProcAddress(hLib, "MiniDumpWriteDump");
- fStackWalk64 = (fpStackWalk64)
- ::GetProcAddress(hLib, "StackWalk64");
- fSymGetModuleBase64 = (fpSymGetModuleBase64)
- ::GetProcAddress(hLib, "SymGetModuleBase64");
- fSymGetSymFromAddr64 = (fpSymGetSymFromAddr64)
- ::GetProcAddress(hLib, "SymGetSymFromAddr64");
- fSymGetLineFromAddr64 = (fpSymGetLineFromAddr64)
- ::GetProcAddress(hLib, "SymGetLineFromAddr64");
- fSymGetModuleInfo64 = (fpSymGetModuleInfo64)
- ::GetProcAddress(hLib, "SymGetModuleInfo64");
- fSymFunctionTableAccess64 = (fpSymFunctionTableAccess64)
- ::GetProcAddress(hLib, "SymFunctionTableAccess64");
- fSymSetOptions = (fpSymSetOptions)::GetProcAddress(hLib, "SymSetOptions");
- fSymInitialize = (fpSymInitialize)::GetProcAddress(hLib, "SymInitialize");
- fEnumerateLoadedModules = (fpEnumerateLoadedModules)
- ::GetProcAddress(hLib, "EnumerateLoadedModules64");
- }
- return fStackWalk64 && fSymInitialize && fSymSetOptions && fMiniDumpWriteDump;
-}
-
-using namespace llvm;
-
-// Forward declare.
-static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
-static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType);
-
-// The function to call if ctrl-c is pressed.
-static void (*InterruptFunction)() = 0;
-
-static std::vector<std::string> *FilesToRemove = NULL;
-static bool RegisteredUnhandledExceptionFilter = false;
-static bool CleanupExecuted = false;
-static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;
-
-// Windows creates a new thread to execute the console handler when an event
-// (such as CTRL/C) occurs. This causes concurrency issues with the above
-// globals which this critical section addresses.
-static CRITICAL_SECTION CriticalSection;
-static bool CriticalSectionInitialized = false;
-
-static StringRef Argv0;
-
-enum {
-#if defined(_M_X64)
- NativeMachineType = IMAGE_FILE_MACHINE_AMD64
-#elif defined(_M_ARM64)
- NativeMachineType = IMAGE_FILE_MACHINE_ARM64
-#elif defined(_M_IX86)
- NativeMachineType = IMAGE_FILE_MACHINE_I386
-#elif defined(_M_ARM)
- NativeMachineType = IMAGE_FILE_MACHINE_ARMNT
-#else
- NativeMachineType = IMAGE_FILE_MACHINE_UNKNOWN
-#endif
-};
-
-static bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS,
- HANDLE hProcess, HANDLE hThread,
- STACKFRAME64 &StackFrameOrig,
- CONTEXT *ContextOrig) {
- // StackWalk64 modifies the incoming stack frame and context, so copy them.
- STACKFRAME64 StackFrame = StackFrameOrig;
-
- // Copy the register context so that we don't modify it while we unwind. We
- // could use InitializeContext + CopyContext, but that's only required to get
- // at AVX registers, which typically aren't needed by StackWalk64. Reduce the
- // flag set to indicate that there's less data.
- CONTEXT Context = *ContextOrig;
- Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
-
- static void *StackTrace[256];
- size_t Depth = 0;
- while (fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
- &Context, 0, fSymFunctionTableAccess64,
- fSymGetModuleBase64, 0)) {
- if (StackFrame.AddrFrame.Offset == 0)
- break;
- StackTrace[Depth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset;
- if (Depth >= array_lengthof(StackTrace))
- break;
- }
-
- return printSymbolizedStackTrace(Argv0, &StackTrace[0], Depth, OS);
-}
-
-namespace {
-struct FindModuleData {
- void **StackTrace;
- int Depth;
- const char **Modules;
- intptr_t *Offsets;
- StringSaver *StrPool;
-};
-}
-
-static BOOL CALLBACK findModuleCallback(PCSTR ModuleName,
- DWORD64 ModuleBase, ULONG ModuleSize,
- void *VoidData) {
- FindModuleData *Data = (FindModuleData*)VoidData;
- intptr_t Beg = ModuleBase;
- intptr_t End = Beg + ModuleSize;
- for (int I = 0; I < Data->Depth; I++) {
- if (Data->Modules[I])
- continue;
- intptr_t Addr = (intptr_t)Data->StackTrace[I];
- if (Beg <= Addr && Addr < End) {
- Data->Modules[I] = Data->StrPool->save(ModuleName).data();
- Data->Offsets[I] = Addr - Beg;
- }
- }
- return TRUE;
-}
-
-static bool findModulesAndOffsets(void **StackTrace, int Depth,
- const char **Modules, intptr_t *Offsets,
- const char *MainExecutableName,
- StringSaver &StrPool) {
- if (!fEnumerateLoadedModules)
- return false;
- FindModuleData Data;
- Data.StackTrace = StackTrace;
- Data.Depth = Depth;
- Data.Modules = Modules;
- Data.Offsets = Offsets;
- Data.StrPool = &StrPool;
- fEnumerateLoadedModules(GetCurrentProcess(), findModuleCallback, &Data);
- return true;
-}
-
-static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess,
- HANDLE hThread, STACKFRAME64 &StackFrame,
- CONTEXT *Context) {
- // Initialize the symbol handler.
- fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
- fSymInitialize(hProcess, NULL, TRUE);
-
- // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with both PDBs
- // and DWARF, so it should do a good job regardless of what debug info or
- // linker is in use.
- if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread, StackFrame,
- Context)) {
- return;
- }
-
- while (true) {
- if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
- Context, 0, fSymFunctionTableAccess64,
- fSymGetModuleBase64, 0)) {
- break;
- }
-
- if (StackFrame.AddrFrame.Offset == 0)
- break;
-
- using namespace llvm;
- // Print the PC in hexadecimal.
- DWORD64 PC = StackFrame.AddrPC.Offset;
-#if defined(_M_X64) || defined(_M_ARM64)
- OS << format("0x%016llX", PC);
-#elif defined(_M_IX86) || defined(_M_ARM)
- OS << format("0x%08lX", static_cast<DWORD>(PC));
-#endif
-
-// Print the parameters. Assume there are four.
-#if defined(_M_X64) || defined(_M_ARM64)
- OS << format(" (0x%016llX 0x%016llX 0x%016llX 0x%016llX)",
- StackFrame.Params[0], StackFrame.Params[1], StackFrame.Params[2],
- StackFrame.Params[3]);
-#elif defined(_M_IX86) || defined(_M_ARM)
- OS << format(" (0x%08lX 0x%08lX 0x%08lX 0x%08lX)",
- static_cast<DWORD>(StackFrame.Params[0]),
- static_cast<DWORD>(StackFrame.Params[1]),
- static_cast<DWORD>(StackFrame.Params[2]),
- static_cast<DWORD>(StackFrame.Params[3]));
-#endif
- // Verify the PC belongs to a module in this process.
- if (!fSymGetModuleBase64(hProcess, PC)) {
- OS << " <unknown module>\n";
- continue;
- }
-
- // Print the symbol name.
- char buffer[512];
- IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer);
- memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64));
- symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
- symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64);
-
- DWORD64 dwDisp;
- if (!fSymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) {
- OS << '\n';
- continue;
- }
-
- buffer[511] = 0;
- if (dwDisp > 0)
- OS << format(", %s() + 0x%llX bytes(s)", (const char*)symbol->Name,
- dwDisp);
- else
- OS << format(", %s", (const char*)symbol->Name);
-
- // Print the source file and line number information.
- IMAGEHLP_LINE64 line = {};
- DWORD dwLineDisp;
- line.SizeOfStruct = sizeof(line);
- if (fSymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) {
- OS << format(", %s, line %lu", line.FileName, line.LineNumber);
- if (dwLineDisp > 0)
- OS << format(" + 0x%lX byte(s)", dwLineDisp);
- }
-
- OS << '\n';
- }
-}
-
-namespace llvm {
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only Win32 specific code
-//=== and must not be UNIX code
-//===----------------------------------------------------------------------===//
-
-#ifdef _MSC_VER
-/// Emulates hitting "retry" from an "abort, retry, ignore" CRT debug report
-/// dialog. "retry" raises an exception which ultimately triggers our stack
-/// dumper.
-static LLVM_ATTRIBUTE_UNUSED int
-AvoidMessageBoxHook(int ReportType, char *Message, int *Return) {
- // Set *Return to the retry code for the return value of _CrtDbgReport:
- // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx
- // This may also trigger just-in-time debugging via DebugBreak().
- if (Return)
- *Return = 1;
- // Don't call _CrtDbgReport.
- return TRUE;
-}
-
-#endif
-
-extern "C" void HandleAbort(int Sig) {
- if (Sig == SIGABRT) {
- LLVM_BUILTIN_TRAP;
- }
-}
-
-static void InitializeThreading() {
- if (CriticalSectionInitialized)
- return;
-
- // Now's the time to create the critical section. This is the first time
- // through here, and there's only one thread.
- InitializeCriticalSection(&CriticalSection);
- CriticalSectionInitialized = true;
-}
-
-static void RegisterHandler() {
- // If we cannot load up the APIs (which would be unexpected as they should
- // exist on every version of Windows we support), we will bail out since
- // there would be nothing to report.
- if (!load64BitDebugHelp()) {
- assert(false && "These APIs should always be available");
- return;
- }
-
- if (RegisteredUnhandledExceptionFilter) {
- EnterCriticalSection(&CriticalSection);
- return;
- }
-
- InitializeThreading();
-
- // Enter it immediately. Now if someone hits CTRL/C, the console handler
- // can't proceed until the globals are updated.
- EnterCriticalSection(&CriticalSection);
-
- RegisteredUnhandledExceptionFilter = true;
- OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter);
- SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE);
-
- // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or
- // else multi-threading problems will ensue.
-}
-
-// The public API
-bool sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) {
- RegisterHandler();
-
- if (CleanupExecuted) {
- if (ErrMsg)
- *ErrMsg = "Process terminating -- cannot register for removal";
- return true;
- }
-
- if (FilesToRemove == NULL)
- FilesToRemove = new std::vector<std::string>;
-
- FilesToRemove->push_back(Filename);
-
- LeaveCriticalSection(&CriticalSection);
- return false;
-}
-
-// The public API
-void sys::DontRemoveFileOnSignal(StringRef Filename) {
- if (FilesToRemove == NULL)
- return;
-
- RegisterHandler();
-
- std::vector<std::string>::reverse_iterator I =
- find(reverse(*FilesToRemove), Filename);
- if (I != FilesToRemove->rend())
- FilesToRemove->erase(I.base()-1);
-
- LeaveCriticalSection(&CriticalSection);
-}
-
-void sys::DisableSystemDialogsOnCrash() {
- // Crash to stack trace handler on abort.
- signal(SIGABRT, HandleAbort);
-
- // The following functions are not reliably accessible on MinGW.
-#ifdef _MSC_VER
- // We're already handling writing a "something went wrong" message.
- _set_abort_behavior(0, _WRITE_ABORT_MSG);
- // Disable Dr. Watson.
- _set_abort_behavior(0, _CALL_REPORTFAULT);
- _CrtSetReportHook(AvoidMessageBoxHook);
-#endif
-
- // Disable standard error dialog box.
- SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
- SEM_NOOPENFILEERRORBOX);
- _set_error_mode(_OUT_TO_STDERR);
-}
-
-/// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
-/// process, print a stack trace and then exit.
-void sys::PrintStackTraceOnErrorSignal(StringRef Argv0,
- bool DisableCrashReporting) {
- ::Argv0 = Argv0;
-
- if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT"))
- Process::PreventCoreFiles();
-
- DisableSystemDialogsOnCrash();
- RegisterHandler();
- LeaveCriticalSection(&CriticalSection);
-}
-}
-
-#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
-// Provide a prototype for RtlCaptureContext, mingw32 from mingw.org is
-// missing it but mingw-w64 has it.
-extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord);
-#endif
-
-void llvm::sys::PrintStackTrace(raw_ostream &OS) {
- STACKFRAME64 StackFrame = {};
- CONTEXT Context = {};
- ::RtlCaptureContext(&Context);
-#if defined(_M_X64)
- StackFrame.AddrPC.Offset = Context.Rip;
- StackFrame.AddrStack.Offset = Context.Rsp;
- StackFrame.AddrFrame.Offset = Context.Rbp;
-#elif defined(_M_IX86)
- StackFrame.AddrPC.Offset = Context.Eip;
- StackFrame.AddrStack.Offset = Context.Esp;
- StackFrame.AddrFrame.Offset = Context.Ebp;
-#elif defined(_M_ARM64)
- StackFrame.AddrPC.Offset = Context.Pc;
- StackFrame.AddrStack.Offset = Context.Sp;
- StackFrame.AddrFrame.Offset = Context.Fp;
-#elif defined(_M_ARM)
- StackFrame.AddrPC.Offset = Context.Pc;
- StackFrame.AddrStack.Offset = Context.Sp;
- StackFrame.AddrFrame.Offset = Context.R11;
-#endif
- StackFrame.AddrPC.Mode = AddrModeFlat;
- StackFrame.AddrStack.Mode = AddrModeFlat;
- StackFrame.AddrFrame.Mode = AddrModeFlat;
- PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(),
- StackFrame, &Context);
-}
-
-
-void llvm::sys::SetInterruptFunction(void (*IF)()) {
- RegisterHandler();
- InterruptFunction = IF;
- LeaveCriticalSection(&CriticalSection);
-}
-
-
-/// Add a function to be called when a signal is delivered to the process. The
-/// handler can have a cookie passed to it to identify what instance of the
-/// handler it is.
-void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr,
- void *Cookie) {
- insertSignalHandler(FnPtr, Cookie);
- RegisterHandler();
- LeaveCriticalSection(&CriticalSection);
-}
-
-static void Cleanup() {
- if (CleanupExecuted)
- return;
-
- EnterCriticalSection(&CriticalSection);
-
- // Prevent other thread from registering new files and directories for
- // removal, should we be executing because of the console handler callback.
- CleanupExecuted = true;
-
- // FIXME: open files cannot be deleted.
- if (FilesToRemove != NULL)
- while (!FilesToRemove->empty()) {
- llvm::sys::fs::remove(FilesToRemove->back());
- FilesToRemove->pop_back();
- }
- llvm::sys::RunSignalHandlers();
- LeaveCriticalSection(&CriticalSection);
-}
-
-void llvm::sys::RunInterruptHandlers() {
- // The interrupt handler may be called from an interrupt, but it may also be
- // called manually (such as the case of report_fatal_error with no registered
- // error handler). We must ensure that the critical section is properly
- // initialized.
- InitializeThreading();
- Cleanup();
-}
-
-/// Find the Windows Registry Key for a given location.
-///
-/// \returns a valid HKEY if the location exists, else NULL.
-static HKEY FindWERKey(const llvm::Twine &RegistryLocation) {
- HKEY Key;
- if (ERROR_SUCCESS != ::RegOpenKeyExA(HKEY_LOCAL_MACHINE,
- RegistryLocation.str().c_str(), 0,
- KEY_QUERY_VALUE | KEY_READ, &Key))
- return NULL;
-
- return Key;
-}
-
-/// Populate ResultDirectory with the value for "DumpFolder" for a given
-/// Windows Registry key.
-///
-/// \returns true if a valid value for DumpFolder exists, false otherwise.
-static bool GetDumpFolder(HKEY Key,
- llvm::SmallVectorImpl<char> &ResultDirectory) {
- using llvm::sys::windows::UTF16ToUTF8;
-
- if (!Key)
- return false;
-
- DWORD BufferLengthBytes = 0;
-
- if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ,
- NULL, NULL, &BufferLengthBytes))
- return false;
-
- SmallVector<wchar_t, MAX_PATH> Buffer(BufferLengthBytes);
-
- if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ,
- NULL, Buffer.data(), &BufferLengthBytes))
- return false;
-
- DWORD ExpandBufferSize = ::ExpandEnvironmentStringsW(Buffer.data(), NULL, 0);
-
- if (!ExpandBufferSize)
- return false;
-
- SmallVector<wchar_t, MAX_PATH> ExpandBuffer(ExpandBufferSize);
-
- if (ExpandBufferSize != ::ExpandEnvironmentStringsW(Buffer.data(),
- ExpandBuffer.data(),
- ExpandBufferSize))
- return false;
-
- if (UTF16ToUTF8(ExpandBuffer.data(), ExpandBufferSize - 1, ResultDirectory))
- return false;
-
- return true;
-}
-
-/// Populate ResultType with a valid MINIDUMP_TYPE based on the value of
-/// "DumpType" for a given Windows Registry key.
-///
-/// According to
-/// https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181(v=vs.85).aspx
-/// valid values for DumpType are:
-/// * 0: Custom dump
-/// * 1: Mini dump
-/// * 2: Full dump
-/// If "Custom dump" is specified then the "CustomDumpFlags" field is read
-/// containing a bitwise combination of MINIDUMP_TYPE values.
-///
-/// \returns true if a valid value for ResultType can be set, false otherwise.
-static bool GetDumpType(HKEY Key, MINIDUMP_TYPE &ResultType) {
- if (!Key)
- return false;
-
- DWORD DumpType;
- DWORD TypeSize = sizeof(DumpType);
- if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"DumpType", RRF_RT_REG_DWORD,
- NULL, &DumpType,
- &TypeSize))
- return false;
-
- switch (DumpType) {
- case 0: {
- DWORD Flags = 0;
- if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"CustomDumpFlags",
- RRF_RT_REG_DWORD, NULL, &Flags,
- &TypeSize))
- return false;
-
- ResultType = static_cast<MINIDUMP_TYPE>(Flags);
- break;
- }
- case 1:
- ResultType = MiniDumpNormal;
- break;
- case 2:
- ResultType = MiniDumpWithFullMemory;
- break;
- default:
- return false;
- }
- return true;
-}
-
-/// Write a Windows dump file containing process information that can be
-/// used for post-mortem debugging.
-///
-/// \returns zero error code if a mini dump created, actual error code
-/// otherwise.
-static std::error_code WINAPI
-WriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) {
- using namespace llvm;
- using namespace llvm::sys;
-
- std::string MainExecutableName = fs::getMainExecutable(nullptr, nullptr);
- StringRef ProgramName;
-
- if (MainExecutableName.empty()) {
- // If we can't get the executable filename,
- // things are in worse shape than we realize
- // and we should just bail out.
- return mapWindowsError(::GetLastError());
- }
-
- ProgramName = path::filename(MainExecutableName.c_str());
-
- // The Windows Registry location as specified at
- // https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181%28v=vs.85%29.aspx
- // "Collecting User-Mode Dumps" that may optionally be set to collect crash
- // dumps in a specified location.
- StringRef LocalDumpsRegistryLocation =
- "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps";
-
- // The key pointing to the Registry location that may contain global crash
- // dump settings. This will be NULL if the location can not be found.
- ScopedRegHandle DefaultLocalDumpsKey(FindWERKey(LocalDumpsRegistryLocation));
-
- // The key pointing to the Registry location that may contain
- // application-specific crash dump settings. This will be NULL if the
- // location can not be found.
- ScopedRegHandle AppSpecificKey(
- FindWERKey(Twine(LocalDumpsRegistryLocation) + "\\" + ProgramName));
-
- // Look to see if a dump type is specified in the registry; first with the
- // app-specific key and failing that with the global key. If none are found
- // default to a normal dump (GetDumpType will return false either if the key
- // is NULL or if there is no valid DumpType value at its location).
- MINIDUMP_TYPE DumpType;
- if (!GetDumpType(AppSpecificKey, DumpType))
- if (!GetDumpType(DefaultLocalDumpsKey, DumpType))
- DumpType = MiniDumpNormal;
-
- // Look to see if a dump location is specified in the registry; first with the
- // app-specific key and failing that with the global key. If none are found
- // we'll just create the dump file in the default temporary file location
- // (GetDumpFolder will return false either if the key is NULL or if there is
- // no valid DumpFolder value at its location).
- bool ExplicitDumpDirectorySet = true;
- SmallString<MAX_PATH> DumpDirectory;
- if (!GetDumpFolder(AppSpecificKey, DumpDirectory))
- if (!GetDumpFolder(DefaultLocalDumpsKey, DumpDirectory))
- ExplicitDumpDirectorySet = false;
-
- int FD;
- SmallString<MAX_PATH> DumpPath;
-
- if (ExplicitDumpDirectorySet) {
- if (std::error_code EC = fs::create_directories(DumpDirectory))
- return EC;
- if (std::error_code EC = fs::createUniqueFile(
- Twine(DumpDirectory) + "\\" + ProgramName + ".%%%%%%.dmp", FD,
- DumpPath))
- return EC;
- } else if (std::error_code EC =
- fs::createTemporaryFile(ProgramName, "dmp", FD, DumpPath))
- return EC;
-
- // Our support functions return a file descriptor but Windows wants a handle.
- ScopedCommonHandle FileHandle(reinterpret_cast<HANDLE>(_get_osfhandle(FD)));
-
- if (!fMiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(),
- FileHandle, DumpType, ExceptionInfo, NULL, NULL))
- return mapWindowsError(::GetLastError());
-
- llvm::errs() << "Wrote crash dump file \"" << DumpPath << "\"\n";
- return std::error_code();
-}
-
-static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
- Cleanup();
-
- // We'll automatically write a Minidump file here to help diagnose
- // the nasty sorts of crashes that aren't 100% reproducible from a set of
- // inputs (or in the event that the user is unable or unwilling to provide a
- // reproducible case).
- if (!llvm::sys::Process::AreCoreFilesPrevented()) {
- MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo;
- ExceptionInfo.ThreadId = ::GetCurrentThreadId();
- ExceptionInfo.ExceptionPointers = ep;
- ExceptionInfo.ClientPointers = FALSE;
-
- if (std::error_code EC = WriteWindowsDumpFile(&ExceptionInfo))
- llvm::errs() << "Could not write crash dump file: " << EC.message()
- << "\n";
- }
-
- // Initialize the STACKFRAME structure.
- STACKFRAME64 StackFrame = {};
-
-#if defined(_M_X64)
- StackFrame.AddrPC.Offset = ep->ContextRecord->Rip;
- StackFrame.AddrPC.Mode = AddrModeFlat;
- StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp;
- StackFrame.AddrStack.Mode = AddrModeFlat;
- StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp;
- StackFrame.AddrFrame.Mode = AddrModeFlat;
-#elif defined(_M_IX86)
- StackFrame.AddrPC.Offset = ep->ContextRecord->Eip;
- StackFrame.AddrPC.Mode = AddrModeFlat;
- StackFrame.AddrStack.Offset = ep->ContextRecord->Esp;
- StackFrame.AddrStack.Mode = AddrModeFlat;
- StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp;
- StackFrame.AddrFrame.Mode = AddrModeFlat;
-#elif defined(_M_ARM64) || defined(_M_ARM)
- StackFrame.AddrPC.Offset = ep->ContextRecord->Pc;
- StackFrame.AddrPC.Mode = AddrModeFlat;
- StackFrame.AddrStack.Offset = ep->ContextRecord->Sp;
- StackFrame.AddrStack.Mode = AddrModeFlat;
-#if defined(_M_ARM64)
- StackFrame.AddrFrame.Offset = ep->ContextRecord->Fp;
-#else
- StackFrame.AddrFrame.Offset = ep->ContextRecord->R11;
-#endif
- StackFrame.AddrFrame.Mode = AddrModeFlat;
-#endif
-
- HANDLE hProcess = GetCurrentProcess();
- HANDLE hThread = GetCurrentThread();
- PrintStackTraceForThread(llvm::errs(), hProcess, hThread, StackFrame,
- ep->ContextRecord);
-
- _exit(ep->ExceptionRecord->ExceptionCode);
-}
-
-static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
- // We are running in our very own thread, courtesy of Windows.
- EnterCriticalSection(&CriticalSection);
- Cleanup();
-
- // If an interrupt function has been set, go and run one it; otherwise,
- // the process dies.
- void (*IF)() = InterruptFunction;
- InterruptFunction = 0; // Don't run it on another CTRL-C.
-
- if (IF) {
- // Note: if the interrupt function throws an exception, there is nothing
- // to catch it in this thread so it will kill the process.
- IF(); // Run it now.
- LeaveCriticalSection(&CriticalSection);
- return TRUE; // Don't kill the process.
- }
-
- // Allow normal processing to take place; i.e., the process dies.
- LeaveCriticalSection(&CriticalSection);
- return FALSE;
-}
-
-#if __MINGW32__
- // We turned these warnings off for this file so that MinGW-g++ doesn't
- // complain about the ll format specifiers used. Now we are turning the
- // warnings back on. If MinGW starts to support diagnostic stacks, we can
- // replace this with a pop.
- #pragma GCC diagnostic warning "-Wformat"
- #pragma GCC diagnostic warning "-Wformat-extra-args"
-#endif
diff --git a/gnu/llvm/lib/Support/Windows/ThreadLocal.inc b/gnu/llvm/lib/Support/Windows/ThreadLocal.inc
deleted file mode 100644
index 8be1c3ecfbb..00000000000
--- a/gnu/llvm/lib/Support/Windows/ThreadLocal.inc
+++ /dev/null
@@ -1,52 +0,0 @@
-//= llvm/Support/Win32/ThreadLocal.inc - Win32 Thread Local Data -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the Win32 specific (non-pthread) ThreadLocal class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic Win32 code that
-//=== is guaranteed to work on *all* Win32 variants.
-//===----------------------------------------------------------------------===//
-
-#include "WindowsSupport.h"
-#include "llvm/Support/ThreadLocal.h"
-
-namespace llvm {
-
-sys::ThreadLocalImpl::ThreadLocalImpl() : data() {
- static_assert(sizeof(DWORD) <= sizeof(data), "size too big");
- DWORD* tls = reinterpret_cast<DWORD*>(&data);
- *tls = TlsAlloc();
- assert(*tls != TLS_OUT_OF_INDEXES);
-}
-
-sys::ThreadLocalImpl::~ThreadLocalImpl() {
- DWORD* tls = reinterpret_cast<DWORD*>(&data);
- TlsFree(*tls);
-}
-
-void *sys::ThreadLocalImpl::getInstance() {
- DWORD* tls = reinterpret_cast<DWORD*>(&data);
- return TlsGetValue(*tls);
-}
-
-void sys::ThreadLocalImpl::setInstance(const void* d){
- DWORD* tls = reinterpret_cast<DWORD*>(&data);
- int errorcode = TlsSetValue(*tls, const_cast<void*>(d));
- assert(errorcode != 0);
- (void)errorcode;
-}
-
-void sys::ThreadLocalImpl::removeInstance() {
- setInstance(0);
-}
-
-}
diff --git a/gnu/llvm/lib/Support/Windows/Threading.inc b/gnu/llvm/lib/Support/Windows/Threading.inc
deleted file mode 100644
index 0bd92f66c6b..00000000000
--- a/gnu/llvm/lib/Support/Windows/Threading.inc
+++ /dev/null
@@ -1,109 +0,0 @@
-//===- Windows/Threading.inc - Win32 Threading Implementation - -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides the Win32 specific implementation of Threading functions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/Twine.h"
-
-#include "WindowsSupport.h"
-#include <process.h>
-
-// Windows will at times define MemoryFence.
-#ifdef MemoryFence
-#undef MemoryFence
-#endif
-
-namespace {
- struct ThreadInfo {
- void(*func)(void*);
- void *param;
- };
-}
-
-static unsigned __stdcall ThreadCallback(void *param) {
- struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
- info->func(info->param);
-
- return 0;
-}
-
-void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData,
- unsigned RequestedStackSize) {
- struct ThreadInfo param = { Fn, UserData };
-
- HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
- RequestedStackSize, ThreadCallback,
- &param, 0, NULL);
-
- if (hThread) {
- // We actually don't care whether the wait succeeds or fails, in
- // the same way we don't care whether the pthread_join call succeeds
- // or fails. There's not much we could do if this were to fail. But
- // on success, this call will wait until the thread finishes executing
- // before returning.
- (void)::WaitForSingleObject(hThread, INFINITE);
- ::CloseHandle(hThread);
- }
-}
-
-uint64_t llvm::get_threadid() {
- return uint64_t(::GetCurrentThreadId());
-}
-
-uint32_t llvm::get_max_thread_name_length() { return 0; }
-
-#if defined(_MSC_VER)
-static void SetThreadName(DWORD Id, LPCSTR Name) {
- constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
-
-#pragma pack(push, 8)
- struct THREADNAME_INFO {
- DWORD dwType; // Must be 0x1000.
- LPCSTR szName; // Pointer to thread name
- DWORD dwThreadId; // Thread ID (-1 == current thread)
- DWORD dwFlags; // Reserved. Do not use.
- };
-#pragma pack(pop)
-
- THREADNAME_INFO info;
- info.dwType = 0x1000;
- info.szName = Name;
- info.dwThreadId = Id;
- info.dwFlags = 0;
-
- __try {
- ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
- (ULONG_PTR *)&info);
- }
- __except (EXCEPTION_EXECUTE_HANDLER) {
- }
-}
-#endif
-
-void llvm::set_thread_name(const Twine &Name) {
-#if defined(_MSC_VER)
- // Make sure the input is null terminated.
- SmallString<64> Storage;
- StringRef NameStr = Name.toNullTerminatedStringRef(Storage);
- SetThreadName(::GetCurrentThreadId(), NameStr.data());
-#endif
-}
-
-void llvm::get_thread_name(SmallVectorImpl<char> &Name) {
- // "Name" is not an inherent property of a thread on Windows. In fact, when
- // you "set" the name, you are only firing a one-time message to a debugger
- // which it interprets as a program setting its threads' name. We may be
- // able to get fancy by creating a TLS entry when someone calls
- // set_thread_name so that subsequent calls to get_thread_name return this
- // value.
- Name.clear();
-}
diff --git a/gnu/llvm/lib/Support/Windows/Watchdog.inc b/gnu/llvm/lib/Support/Windows/Watchdog.inc
deleted file mode 100644
index fab2bdf2a94..00000000000
--- a/gnu/llvm/lib/Support/Windows/Watchdog.inc
+++ /dev/null
@@ -1,24 +0,0 @@
-//===--- Windows/Watchdog.inc - Windows Watchdog Implementation -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides the generic Windows implementation of the Watchdog class.
-//
-//===----------------------------------------------------------------------===//
-
-// TODO: implement.
-// Currently this is only used by PrettyStackTrace which is also unimplemented
-// on Windows. Roughly, a Windows implementation would use CreateWaitableTimer
-// and a second thread to run the TimerAPCProc.
-
-namespace llvm {
- namespace sys {
- Watchdog::Watchdog(unsigned int seconds) {}
- Watchdog::~Watchdog() {}
- }
-}
diff --git a/gnu/llvm/lib/Support/Windows/WindowsSupport.h b/gnu/llvm/lib/Support/Windows/WindowsSupport.h
deleted file mode 100644
index 979cc5d0139..00000000000
--- a/gnu/llvm/lib/Support/Windows/WindowsSupport.h
+++ /dev/null
@@ -1,235 +0,0 @@
-//===- WindowsSupport.h - Common Windows Include File -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// 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/Chrono.h"
-#include "llvm/Support/Compiler.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);
-
-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);
-} // end namespace windows
-} // end namespace sys
-} // end namespace llvm.
-
-#endif
diff --git a/gnu/llvm/lib/Support/Windows/explicit_symbols.inc b/gnu/llvm/lib/Support/Windows/explicit_symbols.inc
deleted file mode 100644
index bbbf7ea6a77..00000000000
--- a/gnu/llvm/lib/Support/Windows/explicit_symbols.inc
+++ /dev/null
@@ -1,102 +0,0 @@
-/* in libgcc.a */
-
-#ifdef HAVE__ALLOCA
- EXPLICIT_SYMBOL(_alloca)
- EXPLICIT_SYMBOL2(alloca, _alloca)
-#endif
-#ifdef HAVE___ALLOCA
- EXPLICIT_SYMBOL(__alloca)
-#endif
-#ifdef HAVE___CHKSTK
- EXPLICIT_SYMBOL(__chkstk)
-#endif
-#ifdef HAVE___CHKSTK_MS
- EXPLICIT_SYMBOL(__chkstk_ms)
-#endif
-#ifdef HAVE____CHKSTK
- EXPLICIT_SYMBOL(___chkstk)
-#endif
-#ifdef HAVE____CHKSTK_MS
- EXPLICIT_SYMBOL(___chkstk_ms)
-#endif
-#ifdef HAVE___MAIN
- EXPLICIT_SYMBOL(__main) // FIXME: Don't call it.
-#endif
-
-#ifdef HAVE___ASHLDI3
- EXPLICIT_SYMBOL(__ashldi3)
-#endif
-#ifdef HAVE___ASHRDI3
- EXPLICIT_SYMBOL(__ashrdi3)
-#endif
-#ifdef HAVE___CMPDI2 // FIXME: unused
- EXPLICIT_SYMBOL(__cmpdi2)
-#endif
-#ifdef HAVE___DIVDI3
- EXPLICIT_SYMBOL(__divdi3)
-#endif
-#ifdef HAVE___FIXDFDI
- EXPLICIT_SYMBOL(__fixdfdi)
-#endif
-#ifdef HAVE___FIXSFDI
- EXPLICIT_SYMBOL(__fixsfdi)
-#endif
-#ifdef HAVE___FIXUNSDFDI
- EXPLICIT_SYMBOL(__fixunsdfdi)
-#endif
-#ifdef HAVE___FIXUNSSFDI
- EXPLICIT_SYMBOL(__fixunssfdi)
-#endif
-#ifdef HAVE___FLOATDIDF
- EXPLICIT_SYMBOL(__floatdidf)
-#endif
-#ifdef HAVE___FLOATDISF
- EXPLICIT_SYMBOL(__floatdisf)
-#endif
-#ifdef HAVE___LSHRDI3
- EXPLICIT_SYMBOL(__lshrdi3)
-#endif
-#ifdef HAVE___MODDI3
- EXPLICIT_SYMBOL(__moddi3)
-#endif
-#ifdef HAVE___UDIVDI3
- EXPLICIT_SYMBOL(__udivdi3)
-#endif
-#ifdef HAVE___UMODDI3
- EXPLICIT_SYMBOL(__umoddi3)
-#endif
-
-/* msvcrt */
-#if defined(_MSC_VER)
- EXPLICIT_SYMBOL2(alloca, _alloca_probe)
-
-#ifdef _M_IX86
-#define INLINE_DEF_FLOAT_SYMBOL(SYM, ARGC) INLINE_DEF_SYMBOL##ARGC(float, SYM)
- INLINE_DEF_FLOAT_SYMBOL(acosf, 1)
- INLINE_DEF_FLOAT_SYMBOL(asinf, 1)
- INLINE_DEF_FLOAT_SYMBOL(atanf, 1)
- INLINE_DEF_FLOAT_SYMBOL(atan2f, 2)
- INLINE_DEF_FLOAT_SYMBOL(ceilf, 1)
- INLINE_DEF_FLOAT_SYMBOL(cosf, 1)
- INLINE_DEF_FLOAT_SYMBOL(coshf, 1)
- INLINE_DEF_FLOAT_SYMBOL(expf, 1)
- INLINE_DEF_FLOAT_SYMBOL(floorf, 1)
- INLINE_DEF_FLOAT_SYMBOL(fmodf, 2)
- INLINE_DEF_FLOAT_SYMBOL(logf, 1)
- INLINE_DEF_FLOAT_SYMBOL(powf, 2)
- INLINE_DEF_FLOAT_SYMBOL(sinf, 1)
- INLINE_DEF_FLOAT_SYMBOL(sinhf, 1)
- INLINE_DEF_FLOAT_SYMBOL(sqrtf, 1)
- INLINE_DEF_FLOAT_SYMBOL(tanf, 1)
- INLINE_DEF_FLOAT_SYMBOL(tanhf, 1)
-
- // These were added in VS 2013.
-#if (1800 <= _MSC_VER && _MSC_VER < 1900)
- INLINE_DEF_FLOAT_SYMBOL(copysignf, 2)
- INLINE_DEF_FLOAT_SYMBOL(fminf, 2)
- INLINE_DEF_FLOAT_SYMBOL(fmaxf, 2)
-#endif
-#undef INLINE_DEF_FLOAT_SYMBOL
-#endif
-
-#endif
diff --git a/gnu/llvm/lib/Support/WithColor.cpp b/gnu/llvm/lib/Support/WithColor.cpp
deleted file mode 100644
index cf4c10956f2..00000000000
--- a/gnu/llvm/lib/Support/WithColor.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-//===- WithColor.cpp ------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-cl::OptionCategory llvm::ColorCategory("Color Options");
-
-static cl::opt<cl::boolOrDefault>
- UseColor("color", cl::cat(ColorCategory),
- cl::desc("Use colors in output (default=autodetect)"),
- cl::init(cl::BOU_UNSET));
-
-WithColor::WithColor(raw_ostream &OS, HighlightColor Color, bool DisableColors)
- : OS(OS), DisableColors(DisableColors) {
- // Detect color from terminal type unless the user passed the --color option.
- if (colorsEnabled()) {
- switch (Color) {
- case HighlightColor::Address:
- OS.changeColor(raw_ostream::YELLOW);
- break;
- case HighlightColor::String:
- OS.changeColor(raw_ostream::GREEN);
- break;
- case HighlightColor::Tag:
- OS.changeColor(raw_ostream::BLUE);
- break;
- case HighlightColor::Attribute:
- OS.changeColor(raw_ostream::CYAN);
- break;
- case HighlightColor::Enumerator:
- OS.changeColor(raw_ostream::MAGENTA);
- break;
- case HighlightColor::Macro:
- OS.changeColor(raw_ostream::RED);
- break;
- case HighlightColor::Error:
- OS.changeColor(raw_ostream::RED, true);
- break;
- case HighlightColor::Warning:
- OS.changeColor(raw_ostream::MAGENTA, true);
- break;
- case HighlightColor::Note:
- OS.changeColor(raw_ostream::BLACK, true);
- break;
- case HighlightColor::Remark:
- OS.changeColor(raw_ostream::BLUE, true);
- break;
- }
- }
-}
-
-raw_ostream &WithColor::error() { return error(errs()); }
-
-raw_ostream &WithColor::warning() { return warning(errs()); }
-
-raw_ostream &WithColor::note() { return note(errs()); }
-
-raw_ostream &WithColor::remark() { return remark(errs()); }
-
-raw_ostream &WithColor::error(raw_ostream &OS, StringRef Prefix,
- bool DisableColors) {
- if (!Prefix.empty())
- OS << Prefix << ": ";
- return WithColor(OS, HighlightColor::Error, DisableColors).get()
- << "error: ";
-}
-
-raw_ostream &WithColor::warning(raw_ostream &OS, StringRef Prefix,
- bool DisableColors) {
- if (!Prefix.empty())
- OS << Prefix << ": ";
- return WithColor(OS, HighlightColor::Warning, DisableColors).get()
- << "warning: ";
-}
-
-raw_ostream &WithColor::note(raw_ostream &OS, StringRef Prefix,
- bool DisableColors) {
- if (!Prefix.empty())
- OS << Prefix << ": ";
- return WithColor(OS, HighlightColor::Note, DisableColors).get() << "note: ";
-}
-
-raw_ostream &WithColor::remark(raw_ostream &OS, StringRef Prefix,
- bool DisableColors) {
- if (!Prefix.empty())
- OS << Prefix << ": ";
- return WithColor(OS, HighlightColor::Remark, DisableColors).get()
- << "remark: ";
-}
-
-bool WithColor::colorsEnabled() {
- if (DisableColors)
- return false;
- if (UseColor == cl::BOU_UNSET)
- return OS.has_colors();
- return UseColor == cl::BOU_TRUE;
-}
-
-WithColor &WithColor::changeColor(raw_ostream::Colors Color, bool Bold,
- bool BG) {
- if (colorsEnabled())
- OS.changeColor(Color, Bold, BG);
- return *this;
-}
-
-WithColor &WithColor::resetColor() {
- if (colorsEnabled())
- OS.resetColor();
- return *this;
-}
-
-WithColor::~WithColor() { resetColor(); }
diff --git a/gnu/llvm/lib/Support/YAMLParser.cpp b/gnu/llvm/lib/Support/YAMLParser.cpp
deleted file mode 100644
index 9ef1410b99a..00000000000
--- a/gnu/llvm/lib/Support/YAMLParser.cpp
+++ /dev/null
@@ -1,2443 +0,0 @@
-//===- YAMLParser.cpp - Simple YAML parser --------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a YAML parser.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/YAMLParser.h"
-#include "llvm/ADT/AllocatorList.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SMLoc.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/Unicode.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <map>
-#include <memory>
-#include <string>
-#include <system_error>
-#include <utility>
-
-using namespace llvm;
-using namespace yaml;
-
-enum UnicodeEncodingForm {
- UEF_UTF32_LE, ///< UTF-32 Little Endian
- UEF_UTF32_BE, ///< UTF-32 Big Endian
- UEF_UTF16_LE, ///< UTF-16 Little Endian
- UEF_UTF16_BE, ///< UTF-16 Big Endian
- UEF_UTF8, ///< UTF-8 or ascii.
- UEF_Unknown ///< Not a valid Unicode encoding.
-};
-
-/// EncodingInfo - Holds the encoding type and length of the byte order mark if
-/// it exists. Length is in {0, 2, 3, 4}.
-using EncodingInfo = std::pair<UnicodeEncodingForm, unsigned>;
-
-/// getUnicodeEncoding - Reads up to the first 4 bytes to determine the Unicode
-/// encoding form of \a Input.
-///
-/// @param Input A string of length 0 or more.
-/// @returns An EncodingInfo indicating the Unicode encoding form of the input
-/// and how long the byte order mark is if one exists.
-static EncodingInfo getUnicodeEncoding(StringRef Input) {
- if (Input.empty())
- return std::make_pair(UEF_Unknown, 0);
-
- switch (uint8_t(Input[0])) {
- case 0x00:
- if (Input.size() >= 4) {
- if ( Input[1] == 0
- && uint8_t(Input[2]) == 0xFE
- && uint8_t(Input[3]) == 0xFF)
- return std::make_pair(UEF_UTF32_BE, 4);
- if (Input[1] == 0 && Input[2] == 0 && Input[3] != 0)
- return std::make_pair(UEF_UTF32_BE, 0);
- }
-
- if (Input.size() >= 2 && Input[1] != 0)
- return std::make_pair(UEF_UTF16_BE, 0);
- return std::make_pair(UEF_Unknown, 0);
- case 0xFF:
- if ( Input.size() >= 4
- && uint8_t(Input[1]) == 0xFE
- && Input[2] == 0
- && Input[3] == 0)
- return std::make_pair(UEF_UTF32_LE, 4);
-
- if (Input.size() >= 2 && uint8_t(Input[1]) == 0xFE)
- return std::make_pair(UEF_UTF16_LE, 2);
- return std::make_pair(UEF_Unknown, 0);
- case 0xFE:
- if (Input.size() >= 2 && uint8_t(Input[1]) == 0xFF)
- return std::make_pair(UEF_UTF16_BE, 2);
- return std::make_pair(UEF_Unknown, 0);
- case 0xEF:
- if ( Input.size() >= 3
- && uint8_t(Input[1]) == 0xBB
- && uint8_t(Input[2]) == 0xBF)
- return std::make_pair(UEF_UTF8, 3);
- return std::make_pair(UEF_Unknown, 0);
- }
-
- // It could still be utf-32 or utf-16.
- if (Input.size() >= 4 && Input[1] == 0 && Input[2] == 0 && Input[3] == 0)
- return std::make_pair(UEF_UTF32_LE, 0);
-
- if (Input.size() >= 2 && Input[1] == 0)
- return std::make_pair(UEF_UTF16_LE, 0);
-
- return std::make_pair(UEF_UTF8, 0);
-}
-
-/// Pin the vtables to this file.
-void Node::anchor() {}
-void NullNode::anchor() {}
-void ScalarNode::anchor() {}
-void BlockScalarNode::anchor() {}
-void KeyValueNode::anchor() {}
-void MappingNode::anchor() {}
-void SequenceNode::anchor() {}
-void AliasNode::anchor() {}
-
-namespace llvm {
-namespace yaml {
-
-/// Token - A single YAML token.
-struct Token {
- enum TokenKind {
- TK_Error, // Uninitialized token.
- TK_StreamStart,
- TK_StreamEnd,
- TK_VersionDirective,
- TK_TagDirective,
- TK_DocumentStart,
- TK_DocumentEnd,
- TK_BlockEntry,
- TK_BlockEnd,
- TK_BlockSequenceStart,
- TK_BlockMappingStart,
- TK_FlowEntry,
- TK_FlowSequenceStart,
- TK_FlowSequenceEnd,
- TK_FlowMappingStart,
- TK_FlowMappingEnd,
- TK_Key,
- TK_Value,
- TK_Scalar,
- TK_BlockScalar,
- TK_Alias,
- TK_Anchor,
- TK_Tag
- } Kind = TK_Error;
-
- /// A string of length 0 or more whose begin() points to the logical location
- /// of the token in the input.
- StringRef Range;
-
- /// The value of a block scalar node.
- std::string Value;
-
- Token() = default;
-};
-
-} // end namespace yaml
-} // end namespace llvm
-
-using TokenQueueT = BumpPtrList<Token>;
-
-namespace {
-
-/// This struct is used to track simple keys.
-///
-/// Simple keys are handled by creating an entry in SimpleKeys for each Token
-/// which could legally be the start of a simple key. When peekNext is called,
-/// if the Token To be returned is referenced by a SimpleKey, we continue
-/// tokenizing until that potential simple key has either been found to not be
-/// a simple key (we moved on to the next line or went further than 1024 chars).
-/// Or when we run into a Value, and then insert a Key token (and possibly
-/// others) before the SimpleKey's Tok.
-struct SimpleKey {
- TokenQueueT::iterator Tok;
- unsigned Column;
- unsigned Line;
- unsigned FlowLevel;
- bool IsRequired;
-
- bool operator ==(const SimpleKey &Other) {
- return Tok == Other.Tok;
- }
-};
-
-} // end anonymous namespace
-
-/// The Unicode scalar value of a UTF-8 minimal well-formed code unit
-/// subsequence and the subsequence's length in code units (uint8_t).
-/// A length of 0 represents an error.
-using UTF8Decoded = std::pair<uint32_t, unsigned>;
-
-static UTF8Decoded decodeUTF8(StringRef Range) {
- StringRef::iterator Position= Range.begin();
- StringRef::iterator End = Range.end();
- // 1 byte: [0x00, 0x7f]
- // Bit pattern: 0xxxxxxx
- if ((*Position & 0x80) == 0) {
- return std::make_pair(*Position, 1);
- }
- // 2 bytes: [0x80, 0x7ff]
- // Bit pattern: 110xxxxx 10xxxxxx
- if (Position + 1 != End &&
- ((*Position & 0xE0) == 0xC0) &&
- ((*(Position + 1) & 0xC0) == 0x80)) {
- uint32_t codepoint = ((*Position & 0x1F) << 6) |
- (*(Position + 1) & 0x3F);
- if (codepoint >= 0x80)
- return std::make_pair(codepoint, 2);
- }
- // 3 bytes: [0x8000, 0xffff]
- // Bit pattern: 1110xxxx 10xxxxxx 10xxxxxx
- if (Position + 2 != End &&
- ((*Position & 0xF0) == 0xE0) &&
- ((*(Position + 1) & 0xC0) == 0x80) &&
- ((*(Position + 2) & 0xC0) == 0x80)) {
- uint32_t codepoint = ((*Position & 0x0F) << 12) |
- ((*(Position + 1) & 0x3F) << 6) |
- (*(Position + 2) & 0x3F);
- // Codepoints between 0xD800 and 0xDFFF are invalid, as
- // they are high / low surrogate halves used by UTF-16.
- if (codepoint >= 0x800 &&
- (codepoint < 0xD800 || codepoint > 0xDFFF))
- return std::make_pair(codepoint, 3);
- }
- // 4 bytes: [0x10000, 0x10FFFF]
- // Bit pattern: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- if (Position + 3 != End &&
- ((*Position & 0xF8) == 0xF0) &&
- ((*(Position + 1) & 0xC0) == 0x80) &&
- ((*(Position + 2) & 0xC0) == 0x80) &&
- ((*(Position + 3) & 0xC0) == 0x80)) {
- uint32_t codepoint = ((*Position & 0x07) << 18) |
- ((*(Position + 1) & 0x3F) << 12) |
- ((*(Position + 2) & 0x3F) << 6) |
- (*(Position + 3) & 0x3F);
- if (codepoint >= 0x10000 && codepoint <= 0x10FFFF)
- return std::make_pair(codepoint, 4);
- }
- return std::make_pair(0, 0);
-}
-
-namespace llvm {
-namespace yaml {
-
-/// Scans YAML tokens from a MemoryBuffer.
-class Scanner {
-public:
- Scanner(StringRef Input, SourceMgr &SM, bool ShowColors = true,
- std::error_code *EC = nullptr);
- Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors = true,
- std::error_code *EC = nullptr);
-
- /// Parse the next token and return it without popping it.
- Token &peekNext();
-
- /// Parse the next token and pop it from the queue.
- Token getNext();
-
- void printError(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Message,
- ArrayRef<SMRange> Ranges = None) {
- SM.PrintMessage(Loc, Kind, Message, Ranges, /* FixIts= */ None, ShowColors);
- }
-
- void setError(const Twine &Message, StringRef::iterator Position) {
- if (Current >= End)
- Current = End - 1;
-
- // propagate the error if possible
- if (EC)
- *EC = make_error_code(std::errc::invalid_argument);
-
- // Don't print out more errors after the first one we encounter. The rest
- // are just the result of the first, and have no meaning.
- if (!Failed)
- printError(SMLoc::getFromPointer(Current), SourceMgr::DK_Error, Message);
- Failed = true;
- }
-
- void setError(const Twine &Message) {
- setError(Message, Current);
- }
-
- /// Returns true if an error occurred while parsing.
- bool failed() {
- return Failed;
- }
-
-private:
- void init(MemoryBufferRef Buffer);
-
- StringRef currentInput() {
- return StringRef(Current, End - Current);
- }
-
- /// Decode a UTF-8 minimal well-formed code unit subsequence starting
- /// at \a Position.
- ///
- /// If the UTF-8 code units starting at Position do not form a well-formed
- /// code unit subsequence, then the Unicode scalar value is 0, and the length
- /// is 0.
- UTF8Decoded decodeUTF8(StringRef::iterator Position) {
- return ::decodeUTF8(StringRef(Position, End - Position));
- }
-
- // The following functions are based on the gramar rules in the YAML spec. The
- // style of the function names it meant to closely match how they are written
- // in the spec. The number within the [] is the number of the grammar rule in
- // the spec.
- //
- // See 4.2 [Production Naming Conventions] for the meaning of the prefixes.
- //
- // c-
- // A production starting and ending with a special character.
- // b-
- // A production matching a single line break.
- // nb-
- // A production starting and ending with a non-break character.
- // s-
- // A production starting and ending with a white space character.
- // ns-
- // A production starting and ending with a non-space character.
- // l-
- // A production matching complete line(s).
-
- /// Skip a single nb-char[27] starting at Position.
- ///
- /// A nb-char is 0x9 | [0x20-0x7E] | 0x85 | [0xA0-0xD7FF] | [0xE000-0xFEFE]
- /// | [0xFF00-0xFFFD] | [0x10000-0x10FFFF]
- ///
- /// @returns The code unit after the nb-char, or Position if it's not an
- /// nb-char.
- StringRef::iterator skip_nb_char(StringRef::iterator Position);
-
- /// Skip a single b-break[28] starting at Position.
- ///
- /// A b-break is 0xD 0xA | 0xD | 0xA
- ///
- /// @returns The code unit after the b-break, or Position if it's not a
- /// b-break.
- StringRef::iterator skip_b_break(StringRef::iterator Position);
-
- /// Skip a single s-space[31] starting at Position.
- ///
- /// An s-space is 0x20
- ///
- /// @returns The code unit after the s-space, or Position if it's not a
- /// s-space.
- StringRef::iterator skip_s_space(StringRef::iterator Position);
-
- /// Skip a single s-white[33] starting at Position.
- ///
- /// A s-white is 0x20 | 0x9
- ///
- /// @returns The code unit after the s-white, or Position if it's not a
- /// s-white.
- StringRef::iterator skip_s_white(StringRef::iterator Position);
-
- /// Skip a single ns-char[34] starting at Position.
- ///
- /// A ns-char is nb-char - s-white
- ///
- /// @returns The code unit after the ns-char, or Position if it's not a
- /// ns-char.
- StringRef::iterator skip_ns_char(StringRef::iterator Position);
-
- using SkipWhileFunc = StringRef::iterator (Scanner::*)(StringRef::iterator);
-
- /// Skip minimal well-formed code unit subsequences until Func
- /// returns its input.
- ///
- /// @returns The code unit after the last minimal well-formed code unit
- /// subsequence that Func accepted.
- StringRef::iterator skip_while( SkipWhileFunc Func
- , StringRef::iterator Position);
-
- /// Skip minimal well-formed code unit subsequences until Func returns its
- /// input.
- void advanceWhile(SkipWhileFunc Func);
-
- /// Scan ns-uri-char[39]s starting at Cur.
- ///
- /// This updates Cur and Column while scanning.
- void scan_ns_uri_char();
-
- /// Consume a minimal well-formed code unit subsequence starting at
- /// \a Cur. Return false if it is not the same Unicode scalar value as
- /// \a Expected. This updates \a Column.
- bool consume(uint32_t Expected);
-
- /// Skip \a Distance UTF-8 code units. Updates \a Cur and \a Column.
- void skip(uint32_t Distance);
-
- /// Return true if the minimal well-formed code unit subsequence at
- /// Pos is whitespace or a new line
- bool isBlankOrBreak(StringRef::iterator Position);
-
- /// Consume a single b-break[28] if it's present at the current position.
- ///
- /// Return false if the code unit at the current position isn't a line break.
- bool consumeLineBreakIfPresent();
-
- /// If IsSimpleKeyAllowed, create and push_back a new SimpleKey.
- void saveSimpleKeyCandidate( TokenQueueT::iterator Tok
- , unsigned AtColumn
- , bool IsRequired);
-
- /// Remove simple keys that can no longer be valid simple keys.
- ///
- /// Invalid simple keys are not on the current line or are further than 1024
- /// columns back.
- void removeStaleSimpleKeyCandidates();
-
- /// Remove all simple keys on FlowLevel \a Level.
- void removeSimpleKeyCandidatesOnFlowLevel(unsigned Level);
-
- /// Unroll indentation in \a Indents back to \a Col. Creates BlockEnd
- /// tokens if needed.
- bool unrollIndent(int ToColumn);
-
- /// Increase indent to \a Col. Creates \a Kind token at \a InsertPoint
- /// if needed.
- bool rollIndent( int ToColumn
- , Token::TokenKind Kind
- , TokenQueueT::iterator InsertPoint);
-
- /// Skip a single-line comment when the comment starts at the current
- /// position of the scanner.
- void skipComment();
-
- /// Skip whitespace and comments until the start of the next token.
- void scanToNextToken();
-
- /// Must be the first token generated.
- bool scanStreamStart();
-
- /// Generate tokens needed to close out the stream.
- bool scanStreamEnd();
-
- /// Scan a %BLAH directive.
- bool scanDirective();
-
- /// Scan a ... or ---.
- bool scanDocumentIndicator(bool IsStart);
-
- /// Scan a [ or { and generate the proper flow collection start token.
- bool scanFlowCollectionStart(bool IsSequence);
-
- /// Scan a ] or } and generate the proper flow collection end token.
- bool scanFlowCollectionEnd(bool IsSequence);
-
- /// Scan the , that separates entries in a flow collection.
- bool scanFlowEntry();
-
- /// Scan the - that starts block sequence entries.
- bool scanBlockEntry();
-
- /// Scan an explicit ? indicating a key.
- bool scanKey();
-
- /// Scan an explicit : indicating a value.
- bool scanValue();
-
- /// Scan a quoted scalar.
- bool scanFlowScalar(bool IsDoubleQuoted);
-
- /// Scan an unquoted scalar.
- bool scanPlainScalar();
-
- /// Scan an Alias or Anchor starting with * or &.
- bool scanAliasOrAnchor(bool IsAlias);
-
- /// Scan a block scalar starting with | or >.
- bool scanBlockScalar(bool IsLiteral);
-
- /// Scan a chomping indicator in a block scalar header.
- char scanBlockChompingIndicator();
-
- /// Scan an indentation indicator in a block scalar header.
- unsigned scanBlockIndentationIndicator();
-
- /// Scan a block scalar header.
- ///
- /// Return false if an error occurred.
- bool scanBlockScalarHeader(char &ChompingIndicator, unsigned &IndentIndicator,
- bool &IsDone);
-
- /// Look for the indentation level of a block scalar.
- ///
- /// Return false if an error occurred.
- bool findBlockScalarIndent(unsigned &BlockIndent, unsigned BlockExitIndent,
- unsigned &LineBreaks, bool &IsDone);
-
- /// Scan the indentation of a text line in a block scalar.
- ///
- /// Return false if an error occurred.
- bool scanBlockScalarIndent(unsigned BlockIndent, unsigned BlockExitIndent,
- bool &IsDone);
-
- /// Scan a tag of the form !stuff.
- bool scanTag();
-
- /// Dispatch to the next scanning function based on \a *Cur.
- bool fetchMoreTokens();
-
- /// The SourceMgr used for diagnostics and buffer management.
- SourceMgr &SM;
-
- /// The original input.
- MemoryBufferRef InputBuffer;
-
- /// The current position of the scanner.
- StringRef::iterator Current;
-
- /// The end of the input (one past the last character).
- StringRef::iterator End;
-
- /// Current YAML indentation level in spaces.
- int Indent;
-
- /// Current column number in Unicode code points.
- unsigned Column;
-
- /// Current line number.
- unsigned Line;
-
- /// How deep we are in flow style containers. 0 Means at block level.
- unsigned FlowLevel;
-
- /// Are we at the start of the stream?
- bool IsStartOfStream;
-
- /// Can the next token be the start of a simple key?
- bool IsSimpleKeyAllowed;
-
- /// True if an error has occurred.
- bool Failed;
-
- /// Should colors be used when printing out the diagnostic messages?
- bool ShowColors;
-
- /// Queue of tokens. This is required to queue up tokens while looking
- /// for the end of a simple key. And for cases where a single character
- /// can produce multiple tokens (e.g. BlockEnd).
- TokenQueueT TokenQueue;
-
- /// Indentation levels.
- SmallVector<int, 4> Indents;
-
- /// Potential simple keys.
- SmallVector<SimpleKey, 4> SimpleKeys;
-
- std::error_code *EC;
-};
-
-} // end namespace yaml
-} // end namespace llvm
-
-/// encodeUTF8 - Encode \a UnicodeScalarValue in UTF-8 and append it to result.
-static void encodeUTF8( uint32_t UnicodeScalarValue
- , SmallVectorImpl<char> &Result) {
- if (UnicodeScalarValue <= 0x7F) {
- Result.push_back(UnicodeScalarValue & 0x7F);
- } else if (UnicodeScalarValue <= 0x7FF) {
- uint8_t FirstByte = 0xC0 | ((UnicodeScalarValue & 0x7C0) >> 6);
- uint8_t SecondByte = 0x80 | (UnicodeScalarValue & 0x3F);
- Result.push_back(FirstByte);
- Result.push_back(SecondByte);
- } else if (UnicodeScalarValue <= 0xFFFF) {
- uint8_t FirstByte = 0xE0 | ((UnicodeScalarValue & 0xF000) >> 12);
- uint8_t SecondByte = 0x80 | ((UnicodeScalarValue & 0xFC0) >> 6);
- uint8_t ThirdByte = 0x80 | (UnicodeScalarValue & 0x3F);
- Result.push_back(FirstByte);
- Result.push_back(SecondByte);
- Result.push_back(ThirdByte);
- } else if (UnicodeScalarValue <= 0x10FFFF) {
- uint8_t FirstByte = 0xF0 | ((UnicodeScalarValue & 0x1F0000) >> 18);
- uint8_t SecondByte = 0x80 | ((UnicodeScalarValue & 0x3F000) >> 12);
- uint8_t ThirdByte = 0x80 | ((UnicodeScalarValue & 0xFC0) >> 6);
- uint8_t FourthByte = 0x80 | (UnicodeScalarValue & 0x3F);
- Result.push_back(FirstByte);
- Result.push_back(SecondByte);
- Result.push_back(ThirdByte);
- Result.push_back(FourthByte);
- }
-}
-
-bool yaml::dumpTokens(StringRef Input, raw_ostream &OS) {
- SourceMgr SM;
- Scanner scanner(Input, SM);
- while (true) {
- Token T = scanner.getNext();
- switch (T.Kind) {
- case Token::TK_StreamStart:
- OS << "Stream-Start: ";
- break;
- case Token::TK_StreamEnd:
- OS << "Stream-End: ";
- break;
- case Token::TK_VersionDirective:
- OS << "Version-Directive: ";
- break;
- case Token::TK_TagDirective:
- OS << "Tag-Directive: ";
- break;
- case Token::TK_DocumentStart:
- OS << "Document-Start: ";
- break;
- case Token::TK_DocumentEnd:
- OS << "Document-End: ";
- break;
- case Token::TK_BlockEntry:
- OS << "Block-Entry: ";
- break;
- case Token::TK_BlockEnd:
- OS << "Block-End: ";
- break;
- case Token::TK_BlockSequenceStart:
- OS << "Block-Sequence-Start: ";
- break;
- case Token::TK_BlockMappingStart:
- OS << "Block-Mapping-Start: ";
- break;
- case Token::TK_FlowEntry:
- OS << "Flow-Entry: ";
- break;
- case Token::TK_FlowSequenceStart:
- OS << "Flow-Sequence-Start: ";
- break;
- case Token::TK_FlowSequenceEnd:
- OS << "Flow-Sequence-End: ";
- break;
- case Token::TK_FlowMappingStart:
- OS << "Flow-Mapping-Start: ";
- break;
- case Token::TK_FlowMappingEnd:
- OS << "Flow-Mapping-End: ";
- break;
- case Token::TK_Key:
- OS << "Key: ";
- break;
- case Token::TK_Value:
- OS << "Value: ";
- break;
- case Token::TK_Scalar:
- OS << "Scalar: ";
- break;
- case Token::TK_BlockScalar:
- OS << "Block Scalar: ";
- break;
- case Token::TK_Alias:
- OS << "Alias: ";
- break;
- case Token::TK_Anchor:
- OS << "Anchor: ";
- break;
- case Token::TK_Tag:
- OS << "Tag: ";
- break;
- case Token::TK_Error:
- break;
- }
- OS << T.Range << "\n";
- if (T.Kind == Token::TK_StreamEnd)
- break;
- else if (T.Kind == Token::TK_Error)
- return false;
- }
- return true;
-}
-
-bool yaml::scanTokens(StringRef Input) {
- SourceMgr SM;
- Scanner scanner(Input, SM);
- while (true) {
- Token T = scanner.getNext();
- if (T.Kind == Token::TK_StreamEnd)
- break;
- else if (T.Kind == Token::TK_Error)
- return false;
- }
- return true;
-}
-
-std::string yaml::escape(StringRef Input, bool EscapePrintable) {
- std::string EscapedInput;
- for (StringRef::iterator i = Input.begin(), e = Input.end(); i != e; ++i) {
- if (*i == '\\')
- EscapedInput += "\\\\";
- else if (*i == '"')
- EscapedInput += "\\\"";
- else if (*i == 0)
- EscapedInput += "\\0";
- else if (*i == 0x07)
- EscapedInput += "\\a";
- else if (*i == 0x08)
- EscapedInput += "\\b";
- else if (*i == 0x09)
- EscapedInput += "\\t";
- else if (*i == 0x0A)
- EscapedInput += "\\n";
- else if (*i == 0x0B)
- EscapedInput += "\\v";
- else if (*i == 0x0C)
- EscapedInput += "\\f";
- else if (*i == 0x0D)
- EscapedInput += "\\r";
- else if (*i == 0x1B)
- EscapedInput += "\\e";
- else if ((unsigned char)*i < 0x20) { // Control characters not handled above.
- std::string HexStr = utohexstr(*i);
- EscapedInput += "\\x" + std::string(2 - HexStr.size(), '0') + HexStr;
- } else if (*i & 0x80) { // UTF-8 multiple code unit subsequence.
- UTF8Decoded UnicodeScalarValue
- = decodeUTF8(StringRef(i, Input.end() - i));
- if (UnicodeScalarValue.second == 0) {
- // Found invalid char.
- SmallString<4> Val;
- encodeUTF8(0xFFFD, Val);
- EscapedInput.insert(EscapedInput.end(), Val.begin(), Val.end());
- // FIXME: Error reporting.
- return EscapedInput;
- }
- if (UnicodeScalarValue.first == 0x85)
- EscapedInput += "\\N";
- else if (UnicodeScalarValue.first == 0xA0)
- EscapedInput += "\\_";
- else if (UnicodeScalarValue.first == 0x2028)
- EscapedInput += "\\L";
- else if (UnicodeScalarValue.first == 0x2029)
- EscapedInput += "\\P";
- else if (!EscapePrintable &&
- sys::unicode::isPrintable(UnicodeScalarValue.first))
- EscapedInput += StringRef(i, UnicodeScalarValue.second);
- else {
- std::string HexStr = utohexstr(UnicodeScalarValue.first);
- if (HexStr.size() <= 2)
- EscapedInput += "\\x" + std::string(2 - HexStr.size(), '0') + HexStr;
- else if (HexStr.size() <= 4)
- EscapedInput += "\\u" + std::string(4 - HexStr.size(), '0') + HexStr;
- else if (HexStr.size() <= 8)
- EscapedInput += "\\U" + std::string(8 - HexStr.size(), '0') + HexStr;
- }
- i += UnicodeScalarValue.second - 1;
- } else
- EscapedInput.push_back(*i);
- }
- return EscapedInput;
-}
-
-Scanner::Scanner(StringRef Input, SourceMgr &sm, bool ShowColors,
- std::error_code *EC)
- : SM(sm), ShowColors(ShowColors), EC(EC) {
- init(MemoryBufferRef(Input, "YAML"));
-}
-
-Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors,
- std::error_code *EC)
- : SM(SM_), ShowColors(ShowColors), EC(EC) {
- init(Buffer);
-}
-
-void Scanner::init(MemoryBufferRef Buffer) {
- InputBuffer = Buffer;
- Current = InputBuffer.getBufferStart();
- End = InputBuffer.getBufferEnd();
- Indent = -1;
- Column = 0;
- Line = 0;
- FlowLevel = 0;
- IsStartOfStream = true;
- IsSimpleKeyAllowed = true;
- Failed = false;
- std::unique_ptr<MemoryBuffer> InputBufferOwner =
- MemoryBuffer::getMemBuffer(Buffer);
- SM.AddNewSourceBuffer(std::move(InputBufferOwner), SMLoc());
-}
-
-Token &Scanner::peekNext() {
- // If the current token is a possible simple key, keep parsing until we
- // can confirm.
- bool NeedMore = false;
- while (true) {
- if (TokenQueue.empty() || NeedMore) {
- if (!fetchMoreTokens()) {
- TokenQueue.clear();
- TokenQueue.push_back(Token());
- return TokenQueue.front();
- }
- }
- assert(!TokenQueue.empty() &&
- "fetchMoreTokens lied about getting tokens!");
-
- removeStaleSimpleKeyCandidates();
- SimpleKey SK;
- SK.Tok = TokenQueue.begin();
- if (!is_contained(SimpleKeys, SK))
- break;
- else
- NeedMore = true;
- }
- return TokenQueue.front();
-}
-
-Token Scanner::getNext() {
- Token Ret = peekNext();
- // TokenQueue can be empty if there was an error getting the next token.
- if (!TokenQueue.empty())
- TokenQueue.pop_front();
-
- // There cannot be any referenced Token's if the TokenQueue is empty. So do a
- // quick deallocation of them all.
- if (TokenQueue.empty())
- TokenQueue.resetAlloc();
-
- return Ret;
-}
-
-StringRef::iterator Scanner::skip_nb_char(StringRef::iterator Position) {
- if (Position == End)
- return Position;
- // Check 7 bit c-printable - b-char.
- if ( *Position == 0x09
- || (*Position >= 0x20 && *Position <= 0x7E))
- return Position + 1;
-
- // Check for valid UTF-8.
- if (uint8_t(*Position) & 0x80) {
- UTF8Decoded u8d = decodeUTF8(Position);
- if ( u8d.second != 0
- && u8d.first != 0xFEFF
- && ( u8d.first == 0x85
- || ( u8d.first >= 0xA0
- && u8d.first <= 0xD7FF)
- || ( u8d.first >= 0xE000
- && u8d.first <= 0xFFFD)
- || ( u8d.first >= 0x10000
- && u8d.first <= 0x10FFFF)))
- return Position + u8d.second;
- }
- return Position;
-}
-
-StringRef::iterator Scanner::skip_b_break(StringRef::iterator Position) {
- if (Position == End)
- return Position;
- if (*Position == 0x0D) {
- if (Position + 1 != End && *(Position + 1) == 0x0A)
- return Position + 2;
- return Position + 1;
- }
-
- if (*Position == 0x0A)
- return Position + 1;
- return Position;
-}
-
-StringRef::iterator Scanner::skip_s_space(StringRef::iterator Position) {
- if (Position == End)
- return Position;
- if (*Position == ' ')
- return Position + 1;
- return Position;
-}
-
-StringRef::iterator Scanner::skip_s_white(StringRef::iterator Position) {
- if (Position == End)
- return Position;
- if (*Position == ' ' || *Position == '\t')
- return Position + 1;
- return Position;
-}
-
-StringRef::iterator Scanner::skip_ns_char(StringRef::iterator Position) {
- if (Position == End)
- return Position;
- if (*Position == ' ' || *Position == '\t')
- return Position;
- return skip_nb_char(Position);
-}
-
-StringRef::iterator Scanner::skip_while( SkipWhileFunc Func
- , StringRef::iterator Position) {
- while (true) {
- StringRef::iterator i = (this->*Func)(Position);
- if (i == Position)
- break;
- Position = i;
- }
- return Position;
-}
-
-void Scanner::advanceWhile(SkipWhileFunc Func) {
- auto Final = skip_while(Func, Current);
- Column += Final - Current;
- Current = Final;
-}
-
-static bool is_ns_hex_digit(const char C) {
- return (C >= '0' && C <= '9')
- || (C >= 'a' && C <= 'z')
- || (C >= 'A' && C <= 'Z');
-}
-
-static bool is_ns_word_char(const char C) {
- return C == '-'
- || (C >= 'a' && C <= 'z')
- || (C >= 'A' && C <= 'Z');
-}
-
-void Scanner::scan_ns_uri_char() {
- while (true) {
- if (Current == End)
- break;
- if (( *Current == '%'
- && Current + 2 < End
- && is_ns_hex_digit(*(Current + 1))
- && is_ns_hex_digit(*(Current + 2)))
- || is_ns_word_char(*Current)
- || StringRef(Current, 1).find_first_of("#;/?:@&=+$,_.!~*'()[]")
- != StringRef::npos) {
- ++Current;
- ++Column;
- } else
- break;
- }
-}
-
-bool Scanner::consume(uint32_t Expected) {
- if (Expected >= 0x80)
- report_fatal_error("Not dealing with this yet");
- if (Current == End)
- return false;
- if (uint8_t(*Current) >= 0x80)
- report_fatal_error("Not dealing with this yet");
- if (uint8_t(*Current) == Expected) {
- ++Current;
- ++Column;
- return true;
- }
- return false;
-}
-
-void Scanner::skip(uint32_t Distance) {
- Current += Distance;
- Column += Distance;
- assert(Current <= End && "Skipped past the end");
-}
-
-bool Scanner::isBlankOrBreak(StringRef::iterator Position) {
- if (Position == End)
- return false;
- return *Position == ' ' || *Position == '\t' || *Position == '\r' ||
- *Position == '\n';
-}
-
-bool Scanner::consumeLineBreakIfPresent() {
- auto Next = skip_b_break(Current);
- if (Next == Current)
- return false;
- Column = 0;
- ++Line;
- Current = Next;
- return true;
-}
-
-void Scanner::saveSimpleKeyCandidate( TokenQueueT::iterator Tok
- , unsigned AtColumn
- , bool IsRequired) {
- if (IsSimpleKeyAllowed) {
- SimpleKey SK;
- SK.Tok = Tok;
- SK.Line = Line;
- SK.Column = AtColumn;
- SK.IsRequired = IsRequired;
- SK.FlowLevel = FlowLevel;
- SimpleKeys.push_back(SK);
- }
-}
-
-void Scanner::removeStaleSimpleKeyCandidates() {
- for (SmallVectorImpl<SimpleKey>::iterator i = SimpleKeys.begin();
- i != SimpleKeys.end();) {
- if (i->Line != Line || i->Column + 1024 < Column) {
- if (i->IsRequired)
- setError( "Could not find expected : for simple key"
- , i->Tok->Range.begin());
- i = SimpleKeys.erase(i);
- } else
- ++i;
- }
-}
-
-void Scanner::removeSimpleKeyCandidatesOnFlowLevel(unsigned Level) {
- if (!SimpleKeys.empty() && (SimpleKeys.end() - 1)->FlowLevel == Level)
- SimpleKeys.pop_back();
-}
-
-bool Scanner::unrollIndent(int ToColumn) {
- Token T;
- // Indentation is ignored in flow.
- if (FlowLevel != 0)
- return true;
-
- while (Indent > ToColumn) {
- T.Kind = Token::TK_BlockEnd;
- T.Range = StringRef(Current, 1);
- TokenQueue.push_back(T);
- Indent = Indents.pop_back_val();
- }
-
- return true;
-}
-
-bool Scanner::rollIndent( int ToColumn
- , Token::TokenKind Kind
- , TokenQueueT::iterator InsertPoint) {
- if (FlowLevel)
- return true;
- if (Indent < ToColumn) {
- Indents.push_back(Indent);
- Indent = ToColumn;
-
- Token T;
- T.Kind = Kind;
- T.Range = StringRef(Current, 0);
- TokenQueue.insert(InsertPoint, T);
- }
- return true;
-}
-
-void Scanner::skipComment() {
- if (*Current != '#')
- return;
- while (true) {
- // This may skip more than one byte, thus Column is only incremented
- // for code points.
- StringRef::iterator I = skip_nb_char(Current);
- if (I == Current)
- break;
- Current = I;
- ++Column;
- }
-}
-
-void Scanner::scanToNextToken() {
- while (true) {
- while (*Current == ' ' || *Current == '\t') {
- skip(1);
- }
-
- skipComment();
-
- // Skip EOL.
- StringRef::iterator i = skip_b_break(Current);
- if (i == Current)
- break;
- Current = i;
- ++Line;
- Column = 0;
- // New lines may start a simple key.
- if (!FlowLevel)
- IsSimpleKeyAllowed = true;
- }
-}
-
-bool Scanner::scanStreamStart() {
- IsStartOfStream = false;
-
- EncodingInfo EI = getUnicodeEncoding(currentInput());
-
- Token T;
- T.Kind = Token::TK_StreamStart;
- T.Range = StringRef(Current, EI.second);
- TokenQueue.push_back(T);
- Current += EI.second;
- return true;
-}
-
-bool Scanner::scanStreamEnd() {
- // Force an ending new line if one isn't present.
- if (Column != 0) {
- Column = 0;
- ++Line;
- }
-
- unrollIndent(-1);
- SimpleKeys.clear();
- IsSimpleKeyAllowed = false;
-
- Token T;
- T.Kind = Token::TK_StreamEnd;
- T.Range = StringRef(Current, 0);
- TokenQueue.push_back(T);
- return true;
-}
-
-bool Scanner::scanDirective() {
- // Reset the indentation level.
- unrollIndent(-1);
- SimpleKeys.clear();
- IsSimpleKeyAllowed = false;
-
- StringRef::iterator Start = Current;
- consume('%');
- StringRef::iterator NameStart = Current;
- Current = skip_while(&Scanner::skip_ns_char, Current);
- StringRef Name(NameStart, Current - NameStart);
- Current = skip_while(&Scanner::skip_s_white, Current);
-
- Token T;
- if (Name == "YAML") {
- Current = skip_while(&Scanner::skip_ns_char, Current);
- T.Kind = Token::TK_VersionDirective;
- T.Range = StringRef(Start, Current - Start);
- TokenQueue.push_back(T);
- return true;
- } else if(Name == "TAG") {
- Current = skip_while(&Scanner::skip_ns_char, Current);
- Current = skip_while(&Scanner::skip_s_white, Current);
- Current = skip_while(&Scanner::skip_ns_char, Current);
- T.Kind = Token::TK_TagDirective;
- T.Range = StringRef(Start, Current - Start);
- TokenQueue.push_back(T);
- return true;
- }
- return false;
-}
-
-bool Scanner::scanDocumentIndicator(bool IsStart) {
- unrollIndent(-1);
- SimpleKeys.clear();
- IsSimpleKeyAllowed = false;
-
- Token T;
- T.Kind = IsStart ? Token::TK_DocumentStart : Token::TK_DocumentEnd;
- T.Range = StringRef(Current, 3);
- skip(3);
- TokenQueue.push_back(T);
- return true;
-}
-
-bool Scanner::scanFlowCollectionStart(bool IsSequence) {
- Token T;
- T.Kind = IsSequence ? Token::TK_FlowSequenceStart
- : Token::TK_FlowMappingStart;
- T.Range = StringRef(Current, 1);
- skip(1);
- TokenQueue.push_back(T);
-
- // [ and { may begin a simple key.
- saveSimpleKeyCandidate(--TokenQueue.end(), Column - 1, false);
-
- // And may also be followed by a simple key.
- IsSimpleKeyAllowed = true;
- ++FlowLevel;
- return true;
-}
-
-bool Scanner::scanFlowCollectionEnd(bool IsSequence) {
- removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
- IsSimpleKeyAllowed = false;
- Token T;
- T.Kind = IsSequence ? Token::TK_FlowSequenceEnd
- : Token::TK_FlowMappingEnd;
- T.Range = StringRef(Current, 1);
- skip(1);
- TokenQueue.push_back(T);
- if (FlowLevel)
- --FlowLevel;
- return true;
-}
-
-bool Scanner::scanFlowEntry() {
- removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
- IsSimpleKeyAllowed = true;
- Token T;
- T.Kind = Token::TK_FlowEntry;
- T.Range = StringRef(Current, 1);
- skip(1);
- TokenQueue.push_back(T);
- return true;
-}
-
-bool Scanner::scanBlockEntry() {
- rollIndent(Column, Token::TK_BlockSequenceStart, TokenQueue.end());
- removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
- IsSimpleKeyAllowed = true;
- Token T;
- T.Kind = Token::TK_BlockEntry;
- T.Range = StringRef(Current, 1);
- skip(1);
- TokenQueue.push_back(T);
- return true;
-}
-
-bool Scanner::scanKey() {
- if (!FlowLevel)
- rollIndent(Column, Token::TK_BlockMappingStart, TokenQueue.end());
-
- removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
- IsSimpleKeyAllowed = !FlowLevel;
-
- Token T;
- T.Kind = Token::TK_Key;
- T.Range = StringRef(Current, 1);
- skip(1);
- TokenQueue.push_back(T);
- return true;
-}
-
-bool Scanner::scanValue() {
- // If the previous token could have been a simple key, insert the key token
- // into the token queue.
- if (!SimpleKeys.empty()) {
- SimpleKey SK = SimpleKeys.pop_back_val();
- Token T;
- T.Kind = Token::TK_Key;
- T.Range = SK.Tok->Range;
- TokenQueueT::iterator i, e;
- for (i = TokenQueue.begin(), e = TokenQueue.end(); i != e; ++i) {
- if (i == SK.Tok)
- break;
- }
- assert(i != e && "SimpleKey not in token queue!");
- i = TokenQueue.insert(i, T);
-
- // We may also need to add a Block-Mapping-Start token.
- rollIndent(SK.Column, Token::TK_BlockMappingStart, i);
-
- IsSimpleKeyAllowed = false;
- } else {
- if (!FlowLevel)
- rollIndent(Column, Token::TK_BlockMappingStart, TokenQueue.end());
- IsSimpleKeyAllowed = !FlowLevel;
- }
-
- Token T;
- T.Kind = Token::TK_Value;
- T.Range = StringRef(Current, 1);
- skip(1);
- TokenQueue.push_back(T);
- return true;
-}
-
-// Forbidding inlining improves performance by roughly 20%.
-// FIXME: Remove once llvm optimizes this to the faster version without hints.
-LLVM_ATTRIBUTE_NOINLINE static bool
-wasEscaped(StringRef::iterator First, StringRef::iterator Position);
-
-// Returns whether a character at 'Position' was escaped with a leading '\'.
-// 'First' specifies the position of the first character in the string.
-static bool wasEscaped(StringRef::iterator First,
- StringRef::iterator Position) {
- assert(Position - 1 >= First);
- StringRef::iterator I = Position - 1;
- // We calculate the number of consecutive '\'s before the current position
- // by iterating backwards through our string.
- while (I >= First && *I == '\\') --I;
- // (Position - 1 - I) now contains the number of '\'s before the current
- // position. If it is odd, the character at 'Position' was escaped.
- return (Position - 1 - I) % 2 == 1;
-}
-
-bool Scanner::scanFlowScalar(bool IsDoubleQuoted) {
- StringRef::iterator Start = Current;
- unsigned ColStart = Column;
- if (IsDoubleQuoted) {
- do {
- ++Current;
- while (Current != End && *Current != '"')
- ++Current;
- // Repeat until the previous character was not a '\' or was an escaped
- // backslash.
- } while ( Current != End
- && *(Current - 1) == '\\'
- && wasEscaped(Start + 1, Current));
- } else {
- skip(1);
- while (true) {
- // Skip a ' followed by another '.
- if (Current + 1 < End && *Current == '\'' && *(Current + 1) == '\'') {
- skip(2);
- continue;
- } else if (*Current == '\'')
- break;
- StringRef::iterator i = skip_nb_char(Current);
- if (i == Current) {
- i = skip_b_break(Current);
- if (i == Current)
- break;
- Current = i;
- Column = 0;
- ++Line;
- } else {
- if (i == End)
- break;
- Current = i;
- ++Column;
- }
- }
- }
-
- if (Current == End) {
- setError("Expected quote at end of scalar", Current);
- return false;
- }
-
- skip(1); // Skip ending quote.
- Token T;
- T.Kind = Token::TK_Scalar;
- T.Range = StringRef(Start, Current - Start);
- TokenQueue.push_back(T);
-
- saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
-
- IsSimpleKeyAllowed = false;
-
- return true;
-}
-
-bool Scanner::scanPlainScalar() {
- StringRef::iterator Start = Current;
- unsigned ColStart = Column;
- unsigned LeadingBlanks = 0;
- assert(Indent >= -1 && "Indent must be >= -1 !");
- unsigned indent = static_cast<unsigned>(Indent + 1);
- while (true) {
- if (*Current == '#')
- break;
-
- while (!isBlankOrBreak(Current)) {
- if ( FlowLevel && *Current == ':'
- && !(isBlankOrBreak(Current + 1) || *(Current + 1) == ',')) {
- setError("Found unexpected ':' while scanning a plain scalar", Current);
- return false;
- }
-
- // Check for the end of the plain scalar.
- if ( (*Current == ':' && isBlankOrBreak(Current + 1))
- || ( FlowLevel
- && (StringRef(Current, 1).find_first_of(",:?[]{}")
- != StringRef::npos)))
- break;
-
- StringRef::iterator i = skip_nb_char(Current);
- if (i == Current)
- break;
- Current = i;
- ++Column;
- }
-
- // Are we at the end?
- if (!isBlankOrBreak(Current))
- break;
-
- // Eat blanks.
- StringRef::iterator Tmp = Current;
- while (isBlankOrBreak(Tmp)) {
- StringRef::iterator i = skip_s_white(Tmp);
- if (i != Tmp) {
- if (LeadingBlanks && (Column < indent) && *Tmp == '\t') {
- setError("Found invalid tab character in indentation", Tmp);
- return false;
- }
- Tmp = i;
- ++Column;
- } else {
- i = skip_b_break(Tmp);
- if (!LeadingBlanks)
- LeadingBlanks = 1;
- Tmp = i;
- Column = 0;
- ++Line;
- }
- }
-
- if (!FlowLevel && Column < indent)
- break;
-
- Current = Tmp;
- }
- if (Start == Current) {
- setError("Got empty plain scalar", Start);
- return false;
- }
- Token T;
- T.Kind = Token::TK_Scalar;
- T.Range = StringRef(Start, Current - Start);
- TokenQueue.push_back(T);
-
- // Plain scalars can be simple keys.
- saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
-
- IsSimpleKeyAllowed = false;
-
- return true;
-}
-
-bool Scanner::scanAliasOrAnchor(bool IsAlias) {
- StringRef::iterator Start = Current;
- unsigned ColStart = Column;
- skip(1);
- while(true) {
- if ( *Current == '[' || *Current == ']'
- || *Current == '{' || *Current == '}'
- || *Current == ','
- || *Current == ':')
- break;
- StringRef::iterator i = skip_ns_char(Current);
- if (i == Current)
- break;
- Current = i;
- ++Column;
- }
-
- if (Start == Current) {
- setError("Got empty alias or anchor", Start);
- return false;
- }
-
- Token T;
- T.Kind = IsAlias ? Token::TK_Alias : Token::TK_Anchor;
- T.Range = StringRef(Start, Current - Start);
- TokenQueue.push_back(T);
-
- // Alias and anchors can be simple keys.
- saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
-
- IsSimpleKeyAllowed = false;
-
- return true;
-}
-
-char Scanner::scanBlockChompingIndicator() {
- char Indicator = ' ';
- if (Current != End && (*Current == '+' || *Current == '-')) {
- Indicator = *Current;
- skip(1);
- }
- return Indicator;
-}
-
-/// Get the number of line breaks after chomping.
-///
-/// Return the number of trailing line breaks to emit, depending on
-/// \p ChompingIndicator.
-static unsigned getChompedLineBreaks(char ChompingIndicator,
- unsigned LineBreaks, StringRef Str) {
- if (ChompingIndicator == '-') // Strip all line breaks.
- return 0;
- if (ChompingIndicator == '+') // Keep all line breaks.
- return LineBreaks;
- // Clip trailing lines.
- return Str.empty() ? 0 : 1;
-}
-
-unsigned Scanner::scanBlockIndentationIndicator() {
- unsigned Indent = 0;
- if (Current != End && (*Current >= '1' && *Current <= '9')) {
- Indent = unsigned(*Current - '0');
- skip(1);
- }
- return Indent;
-}
-
-bool Scanner::scanBlockScalarHeader(char &ChompingIndicator,
- unsigned &IndentIndicator, bool &IsDone) {
- auto Start = Current;
-
- ChompingIndicator = scanBlockChompingIndicator();
- IndentIndicator = scanBlockIndentationIndicator();
- // Check for the chomping indicator once again.
- if (ChompingIndicator == ' ')
- ChompingIndicator = scanBlockChompingIndicator();
- Current = skip_while(&Scanner::skip_s_white, Current);
- skipComment();
-
- if (Current == End) { // EOF, we have an empty scalar.
- Token T;
- T.Kind = Token::TK_BlockScalar;
- T.Range = StringRef(Start, Current - Start);
- TokenQueue.push_back(T);
- IsDone = true;
- return true;
- }
-
- if (!consumeLineBreakIfPresent()) {
- setError("Expected a line break after block scalar header", Current);
- return false;
- }
- return true;
-}
-
-bool Scanner::findBlockScalarIndent(unsigned &BlockIndent,
- unsigned BlockExitIndent,
- unsigned &LineBreaks, bool &IsDone) {
- unsigned MaxAllSpaceLineCharacters = 0;
- StringRef::iterator LongestAllSpaceLine;
-
- while (true) {
- advanceWhile(&Scanner::skip_s_space);
- if (skip_nb_char(Current) != Current) {
- // This line isn't empty, so try and find the indentation.
- if (Column <= BlockExitIndent) { // End of the block literal.
- IsDone = true;
- return true;
- }
- // We found the block's indentation.
- BlockIndent = Column;
- if (MaxAllSpaceLineCharacters > BlockIndent) {
- setError(
- "Leading all-spaces line must be smaller than the block indent",
- LongestAllSpaceLine);
- return false;
- }
- return true;
- }
- if (skip_b_break(Current) != Current &&
- Column > MaxAllSpaceLineCharacters) {
- // Record the longest all-space line in case it's longer than the
- // discovered block indent.
- MaxAllSpaceLineCharacters = Column;
- LongestAllSpaceLine = Current;
- }
-
- // Check for EOF.
- if (Current == End) {
- IsDone = true;
- return true;
- }
-
- if (!consumeLineBreakIfPresent()) {
- IsDone = true;
- return true;
- }
- ++LineBreaks;
- }
- return true;
-}
-
-bool Scanner::scanBlockScalarIndent(unsigned BlockIndent,
- unsigned BlockExitIndent, bool &IsDone) {
- // Skip the indentation.
- while (Column < BlockIndent) {
- auto I = skip_s_space(Current);
- if (I == Current)
- break;
- Current = I;
- ++Column;
- }
-
- if (skip_nb_char(Current) == Current)
- return true;
-
- if (Column <= BlockExitIndent) { // End of the block literal.
- IsDone = true;
- return true;
- }
-
- if (Column < BlockIndent) {
- if (Current != End && *Current == '#') { // Trailing comment.
- IsDone = true;
- return true;
- }
- setError("A text line is less indented than the block scalar", Current);
- return false;
- }
- return true; // A normal text line.
-}
-
-bool Scanner::scanBlockScalar(bool IsLiteral) {
- // Eat '|' or '>'
- assert(*Current == '|' || *Current == '>');
- skip(1);
-
- char ChompingIndicator;
- unsigned BlockIndent;
- bool IsDone = false;
- if (!scanBlockScalarHeader(ChompingIndicator, BlockIndent, IsDone))
- return false;
- if (IsDone)
- return true;
-
- auto Start = Current;
- unsigned BlockExitIndent = Indent < 0 ? 0 : (unsigned)Indent;
- unsigned LineBreaks = 0;
- if (BlockIndent == 0) {
- if (!findBlockScalarIndent(BlockIndent, BlockExitIndent, LineBreaks,
- IsDone))
- return false;
- }
-
- // Scan the block's scalars body.
- SmallString<256> Str;
- while (!IsDone) {
- if (!scanBlockScalarIndent(BlockIndent, BlockExitIndent, IsDone))
- return false;
- if (IsDone)
- break;
-
- // Parse the current line.
- auto LineStart = Current;
- advanceWhile(&Scanner::skip_nb_char);
- if (LineStart != Current) {
- Str.append(LineBreaks, '\n');
- Str.append(StringRef(LineStart, Current - LineStart));
- LineBreaks = 0;
- }
-
- // Check for EOF.
- if (Current == End)
- break;
-
- if (!consumeLineBreakIfPresent())
- break;
- ++LineBreaks;
- }
-
- if (Current == End && !LineBreaks)
- // Ensure that there is at least one line break before the end of file.
- LineBreaks = 1;
- Str.append(getChompedLineBreaks(ChompingIndicator, LineBreaks, Str), '\n');
-
- // New lines may start a simple key.
- if (!FlowLevel)
- IsSimpleKeyAllowed = true;
-
- Token T;
- T.Kind = Token::TK_BlockScalar;
- T.Range = StringRef(Start, Current - Start);
- T.Value = Str.str().str();
- TokenQueue.push_back(T);
- return true;
-}
-
-bool Scanner::scanTag() {
- StringRef::iterator Start = Current;
- unsigned ColStart = Column;
- skip(1); // Eat !.
- if (Current == End || isBlankOrBreak(Current)); // An empty tag.
- else if (*Current == '<') {
- skip(1);
- scan_ns_uri_char();
- if (!consume('>'))
- return false;
- } else {
- // FIXME: Actually parse the c-ns-shorthand-tag rule.
- Current = skip_while(&Scanner::skip_ns_char, Current);
- }
-
- Token T;
- T.Kind = Token::TK_Tag;
- T.Range = StringRef(Start, Current - Start);
- TokenQueue.push_back(T);
-
- // Tags can be simple keys.
- saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
-
- IsSimpleKeyAllowed = false;
-
- return true;
-}
-
-bool Scanner::fetchMoreTokens() {
- if (IsStartOfStream)
- return scanStreamStart();
-
- scanToNextToken();
-
- if (Current == End)
- return scanStreamEnd();
-
- removeStaleSimpleKeyCandidates();
-
- unrollIndent(Column);
-
- if (Column == 0 && *Current == '%')
- return scanDirective();
-
- if (Column == 0 && Current + 4 <= End
- && *Current == '-'
- && *(Current + 1) == '-'
- && *(Current + 2) == '-'
- && (Current + 3 == End || isBlankOrBreak(Current + 3)))
- return scanDocumentIndicator(true);
-
- if (Column == 0 && Current + 4 <= End
- && *Current == '.'
- && *(Current + 1) == '.'
- && *(Current + 2) == '.'
- && (Current + 3 == End || isBlankOrBreak(Current + 3)))
- return scanDocumentIndicator(false);
-
- if (*Current == '[')
- return scanFlowCollectionStart(true);
-
- if (*Current == '{')
- return scanFlowCollectionStart(false);
-
- if (*Current == ']')
- return scanFlowCollectionEnd(true);
-
- if (*Current == '}')
- return scanFlowCollectionEnd(false);
-
- if (*Current == ',')
- return scanFlowEntry();
-
- if (*Current == '-' && isBlankOrBreak(Current + 1))
- return scanBlockEntry();
-
- if (*Current == '?' && (FlowLevel || isBlankOrBreak(Current + 1)))
- return scanKey();
-
- if (*Current == ':' && (FlowLevel || isBlankOrBreak(Current + 1)))
- return scanValue();
-
- if (*Current == '*')
- return scanAliasOrAnchor(true);
-
- if (*Current == '&')
- return scanAliasOrAnchor(false);
-
- if (*Current == '!')
- return scanTag();
-
- if (*Current == '|' && !FlowLevel)
- return scanBlockScalar(true);
-
- if (*Current == '>' && !FlowLevel)
- return scanBlockScalar(false);
-
- if (*Current == '\'')
- return scanFlowScalar(false);
-
- if (*Current == '"')
- return scanFlowScalar(true);
-
- // Get a plain scalar.
- StringRef FirstChar(Current, 1);
- if (!(isBlankOrBreak(Current)
- || FirstChar.find_first_of("-?:,[]{}#&*!|>'\"%@`") != StringRef::npos)
- || (*Current == '-' && !isBlankOrBreak(Current + 1))
- || (!FlowLevel && (*Current == '?' || *Current == ':')
- && isBlankOrBreak(Current + 1))
- || (!FlowLevel && *Current == ':'
- && Current + 2 < End
- && *(Current + 1) == ':'
- && !isBlankOrBreak(Current + 2)))
- return scanPlainScalar();
-
- setError("Unrecognized character while tokenizing.");
- return false;
-}
-
-Stream::Stream(StringRef Input, SourceMgr &SM, bool ShowColors,
- std::error_code *EC)
- : scanner(new Scanner(Input, SM, ShowColors, EC)), CurrentDoc() {}
-
-Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM, bool ShowColors,
- std::error_code *EC)
- : scanner(new Scanner(InputBuffer, SM, ShowColors, EC)), CurrentDoc() {}
-
-Stream::~Stream() = default;
-
-bool Stream::failed() { return scanner->failed(); }
-
-void Stream::printError(Node *N, const Twine &Msg) {
- scanner->printError( N->getSourceRange().Start
- , SourceMgr::DK_Error
- , Msg
- , N->getSourceRange());
-}
-
-document_iterator Stream::begin() {
- if (CurrentDoc)
- report_fatal_error("Can only iterate over the stream once");
-
- // Skip Stream-Start.
- scanner->getNext();
-
- CurrentDoc.reset(new Document(*this));
- return document_iterator(CurrentDoc);
-}
-
-document_iterator Stream::end() {
- return document_iterator();
-}
-
-void Stream::skip() {
- for (document_iterator i = begin(), e = end(); i != e; ++i)
- i->skip();
-}
-
-Node::Node(unsigned int Type, std::unique_ptr<Document> &D, StringRef A,
- StringRef T)
- : Doc(D), TypeID(Type), Anchor(A), Tag(T) {
- SMLoc Start = SMLoc::getFromPointer(peekNext().Range.begin());
- SourceRange = SMRange(Start, Start);
-}
-
-std::string Node::getVerbatimTag() const {
- StringRef Raw = getRawTag();
- if (!Raw.empty() && Raw != "!") {
- std::string Ret;
- if (Raw.find_last_of('!') == 0) {
- Ret = Doc->getTagMap().find("!")->second;
- Ret += Raw.substr(1);
- return Ret;
- } else if (Raw.startswith("!!")) {
- Ret = Doc->getTagMap().find("!!")->second;
- Ret += Raw.substr(2);
- return Ret;
- } else {
- StringRef TagHandle = Raw.substr(0, Raw.find_last_of('!') + 1);
- std::map<StringRef, StringRef>::const_iterator It =
- Doc->getTagMap().find(TagHandle);
- if (It != Doc->getTagMap().end())
- Ret = It->second;
- else {
- Token T;
- T.Kind = Token::TK_Tag;
- T.Range = TagHandle;
- setError(Twine("Unknown tag handle ") + TagHandle, T);
- }
- Ret += Raw.substr(Raw.find_last_of('!') + 1);
- return Ret;
- }
- }
-
- switch (getType()) {
- case NK_Null:
- return "tag:yaml.org,2002:null";
- case NK_Scalar:
- case NK_BlockScalar:
- // TODO: Tag resolution.
- return "tag:yaml.org,2002:str";
- case NK_Mapping:
- return "tag:yaml.org,2002:map";
- case NK_Sequence:
- return "tag:yaml.org,2002:seq";
- }
-
- return "";
-}
-
-Token &Node::peekNext() {
- return Doc->peekNext();
-}
-
-Token Node::getNext() {
- return Doc->getNext();
-}
-
-Node *Node::parseBlockNode() {
- return Doc->parseBlockNode();
-}
-
-BumpPtrAllocator &Node::getAllocator() {
- return Doc->NodeAllocator;
-}
-
-void Node::setError(const Twine &Msg, Token &Tok) const {
- Doc->setError(Msg, Tok);
-}
-
-bool Node::failed() const {
- return Doc->failed();
-}
-
-StringRef ScalarNode::getValue(SmallVectorImpl<char> &Storage) const {
- // TODO: Handle newlines properly. We need to remove leading whitespace.
- if (Value[0] == '"') { // Double quoted.
- // Pull off the leading and trailing "s.
- StringRef UnquotedValue = Value.substr(1, Value.size() - 2);
- // Search for characters that would require unescaping the value.
- StringRef::size_type i = UnquotedValue.find_first_of("\\\r\n");
- if (i != StringRef::npos)
- return unescapeDoubleQuoted(UnquotedValue, i, Storage);
- return UnquotedValue;
- } else if (Value[0] == '\'') { // Single quoted.
- // Pull off the leading and trailing 's.
- StringRef UnquotedValue = Value.substr(1, Value.size() - 2);
- StringRef::size_type i = UnquotedValue.find('\'');
- if (i != StringRef::npos) {
- // We're going to need Storage.
- Storage.clear();
- Storage.reserve(UnquotedValue.size());
- for (; i != StringRef::npos; i = UnquotedValue.find('\'')) {
- StringRef Valid(UnquotedValue.begin(), i);
- Storage.insert(Storage.end(), Valid.begin(), Valid.end());
- Storage.push_back('\'');
- UnquotedValue = UnquotedValue.substr(i + 2);
- }
- Storage.insert(Storage.end(), UnquotedValue.begin(), UnquotedValue.end());
- return StringRef(Storage.begin(), Storage.size());
- }
- return UnquotedValue;
- }
- // Plain or block.
- return Value.rtrim(' ');
-}
-
-StringRef ScalarNode::unescapeDoubleQuoted( StringRef UnquotedValue
- , StringRef::size_type i
- , SmallVectorImpl<char> &Storage)
- const {
- // Use Storage to build proper value.
- Storage.clear();
- Storage.reserve(UnquotedValue.size());
- for (; i != StringRef::npos; i = UnquotedValue.find_first_of("\\\r\n")) {
- // Insert all previous chars into Storage.
- StringRef Valid(UnquotedValue.begin(), i);
- Storage.insert(Storage.end(), Valid.begin(), Valid.end());
- // Chop off inserted chars.
- UnquotedValue = UnquotedValue.substr(i);
-
- assert(!UnquotedValue.empty() && "Can't be empty!");
-
- // Parse escape or line break.
- switch (UnquotedValue[0]) {
- case '\r':
- case '\n':
- Storage.push_back('\n');
- if ( UnquotedValue.size() > 1
- && (UnquotedValue[1] == '\r' || UnquotedValue[1] == '\n'))
- UnquotedValue = UnquotedValue.substr(1);
- UnquotedValue = UnquotedValue.substr(1);
- break;
- default:
- if (UnquotedValue.size() == 1)
- // TODO: Report error.
- break;
- UnquotedValue = UnquotedValue.substr(1);
- switch (UnquotedValue[0]) {
- default: {
- Token T;
- T.Range = StringRef(UnquotedValue.begin(), 1);
- setError("Unrecognized escape code!", T);
- return "";
- }
- case '\r':
- case '\n':
- // Remove the new line.
- if ( UnquotedValue.size() > 1
- && (UnquotedValue[1] == '\r' || UnquotedValue[1] == '\n'))
- UnquotedValue = UnquotedValue.substr(1);
- // If this was just a single byte newline, it will get skipped
- // below.
- break;
- case '0':
- Storage.push_back(0x00);
- break;
- case 'a':
- Storage.push_back(0x07);
- break;
- case 'b':
- Storage.push_back(0x08);
- break;
- case 't':
- case 0x09:
- Storage.push_back(0x09);
- break;
- case 'n':
- Storage.push_back(0x0A);
- break;
- case 'v':
- Storage.push_back(0x0B);
- break;
- case 'f':
- Storage.push_back(0x0C);
- break;
- case 'r':
- Storage.push_back(0x0D);
- break;
- case 'e':
- Storage.push_back(0x1B);
- break;
- case ' ':
- Storage.push_back(0x20);
- break;
- case '"':
- Storage.push_back(0x22);
- break;
- case '/':
- Storage.push_back(0x2F);
- break;
- case '\\':
- Storage.push_back(0x5C);
- break;
- case 'N':
- encodeUTF8(0x85, Storage);
- break;
- case '_':
- encodeUTF8(0xA0, Storage);
- break;
- case 'L':
- encodeUTF8(0x2028, Storage);
- break;
- case 'P':
- encodeUTF8(0x2029, Storage);
- break;
- case 'x': {
- if (UnquotedValue.size() < 3)
- // TODO: Report error.
- break;
- unsigned int UnicodeScalarValue;
- if (UnquotedValue.substr(1, 2).getAsInteger(16, UnicodeScalarValue))
- // TODO: Report error.
- UnicodeScalarValue = 0xFFFD;
- encodeUTF8(UnicodeScalarValue, Storage);
- UnquotedValue = UnquotedValue.substr(2);
- break;
- }
- case 'u': {
- if (UnquotedValue.size() < 5)
- // TODO: Report error.
- break;
- unsigned int UnicodeScalarValue;
- if (UnquotedValue.substr(1, 4).getAsInteger(16, UnicodeScalarValue))
- // TODO: Report error.
- UnicodeScalarValue = 0xFFFD;
- encodeUTF8(UnicodeScalarValue, Storage);
- UnquotedValue = UnquotedValue.substr(4);
- break;
- }
- case 'U': {
- if (UnquotedValue.size() < 9)
- // TODO: Report error.
- break;
- unsigned int UnicodeScalarValue;
- if (UnquotedValue.substr(1, 8).getAsInteger(16, UnicodeScalarValue))
- // TODO: Report error.
- UnicodeScalarValue = 0xFFFD;
- encodeUTF8(UnicodeScalarValue, Storage);
- UnquotedValue = UnquotedValue.substr(8);
- break;
- }
- }
- UnquotedValue = UnquotedValue.substr(1);
- }
- }
- Storage.insert(Storage.end(), UnquotedValue.begin(), UnquotedValue.end());
- return StringRef(Storage.begin(), Storage.size());
-}
-
-Node *KeyValueNode::getKey() {
- if (Key)
- return Key;
- // Handle implicit null keys.
- {
- Token &t = peekNext();
- if ( t.Kind == Token::TK_BlockEnd
- || t.Kind == Token::TK_Value
- || t.Kind == Token::TK_Error) {
- return Key = new (getAllocator()) NullNode(Doc);
- }
- if (t.Kind == Token::TK_Key)
- getNext(); // skip TK_Key.
- }
-
- // Handle explicit null keys.
- Token &t = peekNext();
- if (t.Kind == Token::TK_BlockEnd || t.Kind == Token::TK_Value) {
- return Key = new (getAllocator()) NullNode(Doc);
- }
-
- // We've got a normal key.
- return Key = parseBlockNode();
-}
-
-Node *KeyValueNode::getValue() {
- if (Value)
- return Value;
- getKey()->skip();
- if (failed())
- return Value = new (getAllocator()) NullNode(Doc);
-
- // Handle implicit null values.
- {
- Token &t = peekNext();
- if ( t.Kind == Token::TK_BlockEnd
- || t.Kind == Token::TK_FlowMappingEnd
- || t.Kind == Token::TK_Key
- || t.Kind == Token::TK_FlowEntry
- || t.Kind == Token::TK_Error) {
- return Value = new (getAllocator()) NullNode(Doc);
- }
-
- if (t.Kind != Token::TK_Value) {
- setError("Unexpected token in Key Value.", t);
- return Value = new (getAllocator()) NullNode(Doc);
- }
- getNext(); // skip TK_Value.
- }
-
- // Handle explicit null values.
- Token &t = peekNext();
- if (t.Kind == Token::TK_BlockEnd || t.Kind == Token::TK_Key) {
- return Value = new (getAllocator()) NullNode(Doc);
- }
-
- // We got a normal value.
- return Value = parseBlockNode();
-}
-
-void MappingNode::increment() {
- if (failed()) {
- IsAtEnd = true;
- CurrentEntry = nullptr;
- return;
- }
- if (CurrentEntry) {
- CurrentEntry->skip();
- if (Type == MT_Inline) {
- IsAtEnd = true;
- CurrentEntry = nullptr;
- return;
- }
- }
- Token T = peekNext();
- if (T.Kind == Token::TK_Key || T.Kind == Token::TK_Scalar) {
- // KeyValueNode eats the TK_Key. That way it can detect null keys.
- CurrentEntry = new (getAllocator()) KeyValueNode(Doc);
- } else if (Type == MT_Block) {
- switch (T.Kind) {
- case Token::TK_BlockEnd:
- getNext();
- IsAtEnd = true;
- CurrentEntry = nullptr;
- break;
- default:
- setError("Unexpected token. Expected Key or Block End", T);
- LLVM_FALLTHROUGH;
- case Token::TK_Error:
- IsAtEnd = true;
- CurrentEntry = nullptr;
- }
- } else {
- switch (T.Kind) {
- case Token::TK_FlowEntry:
- // Eat the flow entry and recurse.
- getNext();
- return increment();
- case Token::TK_FlowMappingEnd:
- getNext();
- LLVM_FALLTHROUGH;
- case Token::TK_Error:
- // Set this to end iterator.
- IsAtEnd = true;
- CurrentEntry = nullptr;
- break;
- default:
- setError( "Unexpected token. Expected Key, Flow Entry, or Flow "
- "Mapping End."
- , T);
- IsAtEnd = true;
- CurrentEntry = nullptr;
- }
- }
-}
-
-void SequenceNode::increment() {
- if (failed()) {
- IsAtEnd = true;
- CurrentEntry = nullptr;
- return;
- }
- if (CurrentEntry)
- CurrentEntry->skip();
- Token T = peekNext();
- if (SeqType == ST_Block) {
- switch (T.Kind) {
- case Token::TK_BlockEntry:
- getNext();
- CurrentEntry = parseBlockNode();
- if (!CurrentEntry) { // An error occurred.
- IsAtEnd = true;
- CurrentEntry = nullptr;
- }
- break;
- case Token::TK_BlockEnd:
- getNext();
- IsAtEnd = true;
- CurrentEntry = nullptr;
- break;
- default:
- setError( "Unexpected token. Expected Block Entry or Block End."
- , T);
- LLVM_FALLTHROUGH;
- case Token::TK_Error:
- IsAtEnd = true;
- CurrentEntry = nullptr;
- }
- } else if (SeqType == ST_Indentless) {
- switch (T.Kind) {
- case Token::TK_BlockEntry:
- getNext();
- CurrentEntry = parseBlockNode();
- if (!CurrentEntry) { // An error occurred.
- IsAtEnd = true;
- CurrentEntry = nullptr;
- }
- break;
- default:
- case Token::TK_Error:
- IsAtEnd = true;
- CurrentEntry = nullptr;
- }
- } else if (SeqType == ST_Flow) {
- switch (T.Kind) {
- case Token::TK_FlowEntry:
- // Eat the flow entry and recurse.
- getNext();
- WasPreviousTokenFlowEntry = true;
- return increment();
- case Token::TK_FlowSequenceEnd:
- getNext();
- LLVM_FALLTHROUGH;
- case Token::TK_Error:
- // Set this to end iterator.
- IsAtEnd = true;
- CurrentEntry = nullptr;
- break;
- case Token::TK_StreamEnd:
- case Token::TK_DocumentEnd:
- case Token::TK_DocumentStart:
- setError("Could not find closing ]!", T);
- // Set this to end iterator.
- IsAtEnd = true;
- CurrentEntry = nullptr;
- break;
- default:
- if (!WasPreviousTokenFlowEntry) {
- setError("Expected , between entries!", T);
- IsAtEnd = true;
- CurrentEntry = nullptr;
- break;
- }
- // Otherwise it must be a flow entry.
- CurrentEntry = parseBlockNode();
- if (!CurrentEntry) {
- IsAtEnd = true;
- }
- WasPreviousTokenFlowEntry = false;
- break;
- }
- }
-}
-
-Document::Document(Stream &S) : stream(S), Root(nullptr) {
- // Tag maps starts with two default mappings.
- TagMap["!"] = "!";
- TagMap["!!"] = "tag:yaml.org,2002:";
-
- if (parseDirectives())
- expectToken(Token::TK_DocumentStart);
- Token &T = peekNext();
- if (T.Kind == Token::TK_DocumentStart)
- getNext();
-}
-
-bool Document::skip() {
- if (stream.scanner->failed())
- return false;
- if (!Root)
- getRoot();
- Root->skip();
- Token &T = peekNext();
- if (T.Kind == Token::TK_StreamEnd)
- return false;
- if (T.Kind == Token::TK_DocumentEnd) {
- getNext();
- return skip();
- }
- return true;
-}
-
-Token &Document::peekNext() {
- return stream.scanner->peekNext();
-}
-
-Token Document::getNext() {
- return stream.scanner->getNext();
-}
-
-void Document::setError(const Twine &Message, Token &Location) const {
- stream.scanner->setError(Message, Location.Range.begin());
-}
-
-bool Document::failed() const {
- return stream.scanner->failed();
-}
-
-Node *Document::parseBlockNode() {
- Token T = peekNext();
- // Handle properties.
- Token AnchorInfo;
- Token TagInfo;
-parse_property:
- switch (T.Kind) {
- case Token::TK_Alias:
- getNext();
- return new (NodeAllocator) AliasNode(stream.CurrentDoc, T.Range.substr(1));
- case Token::TK_Anchor:
- if (AnchorInfo.Kind == Token::TK_Anchor) {
- setError("Already encountered an anchor for this node!", T);
- return nullptr;
- }
- AnchorInfo = getNext(); // Consume TK_Anchor.
- T = peekNext();
- goto parse_property;
- case Token::TK_Tag:
- if (TagInfo.Kind == Token::TK_Tag) {
- setError("Already encountered a tag for this node!", T);
- return nullptr;
- }
- TagInfo = getNext(); // Consume TK_Tag.
- T = peekNext();
- goto parse_property;
- default:
- break;
- }
-
- switch (T.Kind) {
- case Token::TK_BlockEntry:
- // We got an unindented BlockEntry sequence. This is not terminated with
- // a BlockEnd.
- // Don't eat the TK_BlockEntry, SequenceNode needs it.
- return new (NodeAllocator) SequenceNode( stream.CurrentDoc
- , AnchorInfo.Range.substr(1)
- , TagInfo.Range
- , SequenceNode::ST_Indentless);
- case Token::TK_BlockSequenceStart:
- getNext();
- return new (NodeAllocator)
- SequenceNode( stream.CurrentDoc
- , AnchorInfo.Range.substr(1)
- , TagInfo.Range
- , SequenceNode::ST_Block);
- case Token::TK_BlockMappingStart:
- getNext();
- return new (NodeAllocator)
- MappingNode( stream.CurrentDoc
- , AnchorInfo.Range.substr(1)
- , TagInfo.Range
- , MappingNode::MT_Block);
- case Token::TK_FlowSequenceStart:
- getNext();
- return new (NodeAllocator)
- SequenceNode( stream.CurrentDoc
- , AnchorInfo.Range.substr(1)
- , TagInfo.Range
- , SequenceNode::ST_Flow);
- case Token::TK_FlowMappingStart:
- getNext();
- return new (NodeAllocator)
- MappingNode( stream.CurrentDoc
- , AnchorInfo.Range.substr(1)
- , TagInfo.Range
- , MappingNode::MT_Flow);
- case Token::TK_Scalar:
- getNext();
- return new (NodeAllocator)
- ScalarNode( stream.CurrentDoc
- , AnchorInfo.Range.substr(1)
- , TagInfo.Range
- , T.Range);
- case Token::TK_BlockScalar: {
- getNext();
- StringRef NullTerminatedStr(T.Value.c_str(), T.Value.length() + 1);
- StringRef StrCopy = NullTerminatedStr.copy(NodeAllocator).drop_back();
- return new (NodeAllocator)
- BlockScalarNode(stream.CurrentDoc, AnchorInfo.Range.substr(1),
- TagInfo.Range, StrCopy, T.Range);
- }
- case Token::TK_Key:
- // Don't eat the TK_Key, KeyValueNode expects it.
- return new (NodeAllocator)
- MappingNode( stream.CurrentDoc
- , AnchorInfo.Range.substr(1)
- , TagInfo.Range
- , MappingNode::MT_Inline);
- case Token::TK_DocumentStart:
- case Token::TK_DocumentEnd:
- case Token::TK_StreamEnd:
- default:
- // TODO: Properly handle tags. "[!!str ]" should resolve to !!str "", not
- // !!null null.
- return new (NodeAllocator) NullNode(stream.CurrentDoc);
- case Token::TK_Error:
- return nullptr;
- }
- llvm_unreachable("Control flow shouldn't reach here.");
- return nullptr;
-}
-
-bool Document::parseDirectives() {
- bool isDirective = false;
- while (true) {
- Token T = peekNext();
- if (T.Kind == Token::TK_TagDirective) {
- parseTAGDirective();
- isDirective = true;
- } else if (T.Kind == Token::TK_VersionDirective) {
- parseYAMLDirective();
- isDirective = true;
- } else
- break;
- }
- return isDirective;
-}
-
-void Document::parseYAMLDirective() {
- getNext(); // Eat %YAML <version>
-}
-
-void Document::parseTAGDirective() {
- Token Tag = getNext(); // %TAG <handle> <prefix>
- StringRef T = Tag.Range;
- // Strip %TAG
- T = T.substr(T.find_first_of(" \t")).ltrim(" \t");
- std::size_t HandleEnd = T.find_first_of(" \t");
- StringRef TagHandle = T.substr(0, HandleEnd);
- StringRef TagPrefix = T.substr(HandleEnd).ltrim(" \t");
- TagMap[TagHandle] = TagPrefix;
-}
-
-bool Document::expectToken(int TK) {
- Token T = getNext();
- if (T.Kind != TK) {
- setError("Unexpected token", T);
- return false;
- }
- return true;
-}
diff --git a/gnu/llvm/lib/Support/YAMLTraits.cpp b/gnu/llvm/lib/Support/YAMLTraits.cpp
deleted file mode 100644
index b9bbee7883c..00000000000
--- a/gnu/llvm/lib/Support/YAMLTraits.cpp
+++ /dev/null
@@ -1,1072 +0,0 @@
-//===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/LineIterator.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Unicode.h"
-#include "llvm/Support/YAMLParser.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <cstdlib>
-#include <cstring>
-#include <string>
-#include <vector>
-
-using namespace llvm;
-using namespace yaml;
-
-//===----------------------------------------------------------------------===//
-// IO
-//===----------------------------------------------------------------------===//
-
-IO::IO(void *Context) : Ctxt(Context) {}
-
-IO::~IO() = default;
-
-void *IO::getContext() {
- return Ctxt;
-}
-
-void IO::setContext(void *Context) {
- Ctxt = Context;
-}
-
-//===----------------------------------------------------------------------===//
-// Input
-//===----------------------------------------------------------------------===//
-
-Input::Input(StringRef InputContent, void *Ctxt,
- SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt)
- : IO(Ctxt), Strm(new Stream(InputContent, SrcMgr, false, &EC)) {
- if (DiagHandler)
- SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
- DocIterator = Strm->begin();
-}
-
-Input::Input(MemoryBufferRef Input, void *Ctxt,
- SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt)
- : IO(Ctxt), Strm(new Stream(Input, SrcMgr, false, &EC)) {
- if (DiagHandler)
- SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
- DocIterator = Strm->begin();
-}
-
-Input::~Input() = default;
-
-std::error_code Input::error() { return EC; }
-
-// Pin the vtables to this file.
-void Input::HNode::anchor() {}
-void Input::EmptyHNode::anchor() {}
-void Input::ScalarHNode::anchor() {}
-void Input::MapHNode::anchor() {}
-void Input::SequenceHNode::anchor() {}
-
-bool Input::outputting() {
- return false;
-}
-
-bool Input::setCurrentDocument() {
- if (DocIterator != Strm->end()) {
- Node *N = DocIterator->getRoot();
- if (!N) {
- assert(Strm->failed() && "Root is NULL iff parsing failed");
- EC = make_error_code(errc::invalid_argument);
- return false;
- }
-
- if (isa<NullNode>(N)) {
- // Empty files are allowed and ignored
- ++DocIterator;
- return setCurrentDocument();
- }
- TopNode = createHNodes(N);
- CurrentNode = TopNode.get();
- return true;
- }
- return false;
-}
-
-bool Input::nextDocument() {
- return ++DocIterator != Strm->end();
-}
-
-const Node *Input::getCurrentNode() const {
- return CurrentNode ? CurrentNode->_node : nullptr;
-}
-
-bool Input::mapTag(StringRef Tag, bool Default) {
- std::string foundTag = CurrentNode->_node->getVerbatimTag();
- if (foundTag.empty()) {
- // If no tag found and 'Tag' is the default, say it was found.
- return Default;
- }
- // Return true iff found tag matches supplied tag.
- return Tag.equals(foundTag);
-}
-
-void Input::beginMapping() {
- if (EC)
- return;
- // CurrentNode can be null if the document is empty.
- MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
- if (MN) {
- MN->ValidKeys.clear();
- }
-}
-
-std::vector<StringRef> Input::keys() {
- MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
- std::vector<StringRef> Ret;
- if (!MN) {
- setError(CurrentNode, "not a mapping");
- return Ret;
- }
- for (auto &P : MN->Mapping)
- Ret.push_back(P.first());
- return Ret;
-}
-
-bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault,
- void *&SaveInfo) {
- UseDefault = false;
- if (EC)
- return false;
-
- // CurrentNode is null for empty documents, which is an error in case required
- // nodes are present.
- if (!CurrentNode) {
- if (Required)
- EC = make_error_code(errc::invalid_argument);
- return false;
- }
-
- MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
- if (!MN) {
- if (Required || !isa<EmptyHNode>(CurrentNode))
- setError(CurrentNode, "not a mapping");
- return false;
- }
- MN->ValidKeys.push_back(Key);
- HNode *Value = MN->Mapping[Key].get();
- if (!Value) {
- if (Required)
- setError(CurrentNode, Twine("missing required key '") + Key + "'");
- else
- UseDefault = true;
- return false;
- }
- SaveInfo = CurrentNode;
- CurrentNode = Value;
- return true;
-}
-
-void Input::postflightKey(void *saveInfo) {
- CurrentNode = reinterpret_cast<HNode *>(saveInfo);
-}
-
-void Input::endMapping() {
- if (EC)
- return;
- // CurrentNode can be null if the document is empty.
- MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
- if (!MN)
- return;
- for (const auto &NN : MN->Mapping) {
- if (!is_contained(MN->ValidKeys, NN.first())) {
- setError(NN.second.get(), Twine("unknown key '") + NN.first() + "'");
- break;
- }
- }
-}
-
-void Input::beginFlowMapping() { beginMapping(); }
-
-void Input::endFlowMapping() { endMapping(); }
-
-unsigned Input::beginSequence() {
- if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode))
- return SQ->Entries.size();
- if (isa<EmptyHNode>(CurrentNode))
- return 0;
- // Treat case where there's a scalar "null" value as an empty sequence.
- if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
- if (isNull(SN->value()))
- return 0;
- }
- // Any other type of HNode is an error.
- setError(CurrentNode, "not a sequence");
- return 0;
-}
-
-void Input::endSequence() {
-}
-
-bool Input::preflightElement(unsigned Index, void *&SaveInfo) {
- if (EC)
- return false;
- if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
- SaveInfo = CurrentNode;
- CurrentNode = SQ->Entries[Index].get();
- return true;
- }
- return false;
-}
-
-void Input::postflightElement(void *SaveInfo) {
- CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
-}
-
-unsigned Input::beginFlowSequence() { return beginSequence(); }
-
-bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
- if (EC)
- return false;
- if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
- SaveInfo = CurrentNode;
- CurrentNode = SQ->Entries[index].get();
- return true;
- }
- return false;
-}
-
-void Input::postflightFlowElement(void *SaveInfo) {
- CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
-}
-
-void Input::endFlowSequence() {
-}
-
-void Input::beginEnumScalar() {
- ScalarMatchFound = false;
-}
-
-bool Input::matchEnumScalar(const char *Str, bool) {
- if (ScalarMatchFound)
- return false;
- if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
- if (SN->value().equals(Str)) {
- ScalarMatchFound = true;
- return true;
- }
- }
- return false;
-}
-
-bool Input::matchEnumFallback() {
- if (ScalarMatchFound)
- return false;
- ScalarMatchFound = true;
- return true;
-}
-
-void Input::endEnumScalar() {
- if (!ScalarMatchFound) {
- setError(CurrentNode, "unknown enumerated scalar");
- }
-}
-
-bool Input::beginBitSetScalar(bool &DoClear) {
- BitValuesUsed.clear();
- if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
- BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false);
- } else {
- setError(CurrentNode, "expected sequence of bit values");
- }
- DoClear = true;
- return true;
-}
-
-bool Input::bitSetMatch(const char *Str, bool) {
- if (EC)
- return false;
- if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
- unsigned Index = 0;
- for (auto &N : SQ->Entries) {
- if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N.get())) {
- if (SN->value().equals(Str)) {
- BitValuesUsed[Index] = true;
- return true;
- }
- } else {
- setError(CurrentNode, "unexpected scalar in sequence of bit values");
- }
- ++Index;
- }
- } else {
- setError(CurrentNode, "expected sequence of bit values");
- }
- return false;
-}
-
-void Input::endBitSetScalar() {
- if (EC)
- return;
- if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
- assert(BitValuesUsed.size() == SQ->Entries.size());
- for (unsigned i = 0; i < SQ->Entries.size(); ++i) {
- if (!BitValuesUsed[i]) {
- setError(SQ->Entries[i].get(), "unknown bit value");
- return;
- }
- }
- }
-}
-
-void Input::scalarString(StringRef &S, QuotingType) {
- if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
- S = SN->value();
- } else {
- setError(CurrentNode, "unexpected scalar");
- }
-}
-
-void Input::blockScalarString(StringRef &S) { scalarString(S, QuotingType::None); }
-
-void Input::scalarTag(std::string &Tag) {
- Tag = CurrentNode->_node->getVerbatimTag();
-}
-
-void Input::setError(HNode *hnode, const Twine &message) {
- assert(hnode && "HNode must not be NULL");
- setError(hnode->_node, message);
-}
-
-NodeKind Input::getNodeKind() {
- if (isa<ScalarHNode>(CurrentNode))
- return NodeKind::Scalar;
- else if (isa<MapHNode>(CurrentNode))
- return NodeKind::Map;
- else if (isa<SequenceHNode>(CurrentNode))
- return NodeKind::Sequence;
- llvm_unreachable("Unsupported node kind");
-}
-
-void Input::setError(Node *node, const Twine &message) {
- Strm->printError(node, message);
- EC = make_error_code(errc::invalid_argument);
-}
-
-std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) {
- SmallString<128> StringStorage;
- if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) {
- StringRef KeyStr = SN->getValue(StringStorage);
- if (!StringStorage.empty()) {
- // Copy string to permanent storage
- KeyStr = StringStorage.str().copy(StringAllocator);
- }
- return llvm::make_unique<ScalarHNode>(N, KeyStr);
- } else if (BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N)) {
- StringRef ValueCopy = BSN->getValue().copy(StringAllocator);
- return llvm::make_unique<ScalarHNode>(N, ValueCopy);
- } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) {
- auto SQHNode = llvm::make_unique<SequenceHNode>(N);
- for (Node &SN : *SQ) {
- auto Entry = createHNodes(&SN);
- if (EC)
- break;
- SQHNode->Entries.push_back(std::move(Entry));
- }
- return std::move(SQHNode);
- } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) {
- auto mapHNode = llvm::make_unique<MapHNode>(N);
- for (KeyValueNode &KVN : *Map) {
- Node *KeyNode = KVN.getKey();
- ScalarNode *Key = dyn_cast<ScalarNode>(KeyNode);
- Node *Value = KVN.getValue();
- if (!Key || !Value) {
- if (!Key)
- setError(KeyNode, "Map key must be a scalar");
- if (!Value)
- setError(KeyNode, "Map value must not be empty");
- break;
- }
- StringStorage.clear();
- StringRef KeyStr = Key->getValue(StringStorage);
- if (!StringStorage.empty()) {
- // Copy string to permanent storage
- KeyStr = StringStorage.str().copy(StringAllocator);
- }
- auto ValueHNode = createHNodes(Value);
- if (EC)
- break;
- mapHNode->Mapping[KeyStr] = std::move(ValueHNode);
- }
- return std::move(mapHNode);
- } else if (isa<NullNode>(N)) {
- return llvm::make_unique<EmptyHNode>(N);
- } else {
- setError(N, "unknown node kind");
- return nullptr;
- }
-}
-
-void Input::setError(const Twine &Message) {
- setError(CurrentNode, Message);
-}
-
-bool Input::canElideEmptySequence() {
- return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Output
-//===----------------------------------------------------------------------===//
-
-Output::Output(raw_ostream &yout, void *context, int WrapColumn)
- : IO(context), Out(yout), WrapColumn(WrapColumn) {}
-
-Output::~Output() = default;
-
-bool Output::outputting() {
- return true;
-}
-
-void Output::beginMapping() {
- StateStack.push_back(inMapFirstKey);
- NeedsNewLine = true;
-}
-
-bool Output::mapTag(StringRef Tag, bool Use) {
- if (Use) {
- // If this tag is being written inside a sequence we should write the start
- // of the sequence before writing the tag, otherwise the tag won't be
- // attached to the element in the sequence, but rather the sequence itself.
- bool SequenceElement = false;
- if (StateStack.size() > 1) {
- auto &E = StateStack[StateStack.size() - 2];
- SequenceElement = inSeqAnyElement(E) || inFlowSeqAnyElement(E);
- }
- if (SequenceElement && StateStack.back() == inMapFirstKey) {
- newLineCheck();
- } else {
- output(" ");
- }
- output(Tag);
- if (SequenceElement) {
- // If we're writing the tag during the first element of a map, the tag
- // takes the place of the first element in the sequence.
- if (StateStack.back() == inMapFirstKey) {
- StateStack.pop_back();
- StateStack.push_back(inMapOtherKey);
- }
- // Tags inside maps in sequences should act as keys in the map from a
- // formatting perspective, so we always want a newline in a sequence.
- NeedsNewLine = true;
- }
- }
- return Use;
-}
-
-void Output::endMapping() {
- // If we did not map anything, we should explicitly emit an empty map
- if (StateStack.back() == inMapFirstKey)
- output("{}");
- StateStack.pop_back();
-}
-
-std::vector<StringRef> Output::keys() {
- report_fatal_error("invalid call");
-}
-
-bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
- bool &UseDefault, void *&) {
- UseDefault = false;
- if (Required || !SameAsDefault || WriteDefaultValues) {
- auto State = StateStack.back();
- if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) {
- flowKey(Key);
- } else {
- newLineCheck();
- paddedKey(Key);
- }
- return true;
- }
- return false;
-}
-
-void Output::postflightKey(void *) {
- if (StateStack.back() == inMapFirstKey) {
- StateStack.pop_back();
- StateStack.push_back(inMapOtherKey);
- } else if (StateStack.back() == inFlowMapFirstKey) {
- StateStack.pop_back();
- StateStack.push_back(inFlowMapOtherKey);
- }
-}
-
-void Output::beginFlowMapping() {
- StateStack.push_back(inFlowMapFirstKey);
- newLineCheck();
- ColumnAtMapFlowStart = Column;
- output("{ ");
-}
-
-void Output::endFlowMapping() {
- StateStack.pop_back();
- outputUpToEndOfLine(" }");
-}
-
-void Output::beginDocuments() {
- outputUpToEndOfLine("---");
-}
-
-bool Output::preflightDocument(unsigned index) {
- if (index > 0)
- outputUpToEndOfLine("\n---");
- return true;
-}
-
-void Output::postflightDocument() {
-}
-
-void Output::endDocuments() {
- output("\n...\n");
-}
-
-unsigned Output::beginSequence() {
- StateStack.push_back(inSeqFirstElement);
- NeedsNewLine = true;
- return 0;
-}
-
-void Output::endSequence() {
- // If we did not emit anything, we should explicitly emit an empty sequence
- if (StateStack.back() == inSeqFirstElement)
- output("[]");
- StateStack.pop_back();
-}
-
-bool Output::preflightElement(unsigned, void *&) {
- return true;
-}
-
-void Output::postflightElement(void *) {
- if (StateStack.back() == inSeqFirstElement) {
- StateStack.pop_back();
- StateStack.push_back(inSeqOtherElement);
- } else if (StateStack.back() == inFlowSeqFirstElement) {
- StateStack.pop_back();
- StateStack.push_back(inFlowSeqOtherElement);
- }
-}
-
-unsigned Output::beginFlowSequence() {
- StateStack.push_back(inFlowSeqFirstElement);
- newLineCheck();
- ColumnAtFlowStart = Column;
- output("[ ");
- NeedFlowSequenceComma = false;
- return 0;
-}
-
-void Output::endFlowSequence() {
- StateStack.pop_back();
- outputUpToEndOfLine(" ]");
-}
-
-bool Output::preflightFlowElement(unsigned, void *&) {
- if (NeedFlowSequenceComma)
- output(", ");
- if (WrapColumn && Column > WrapColumn) {
- output("\n");
- for (int i = 0; i < ColumnAtFlowStart; ++i)
- output(" ");
- Column = ColumnAtFlowStart;
- output(" ");
- }
- return true;
-}
-
-void Output::postflightFlowElement(void *) {
- NeedFlowSequenceComma = true;
-}
-
-void Output::beginEnumScalar() {
- EnumerationMatchFound = false;
-}
-
-bool Output::matchEnumScalar(const char *Str, bool Match) {
- if (Match && !EnumerationMatchFound) {
- newLineCheck();
- outputUpToEndOfLine(Str);
- EnumerationMatchFound = true;
- }
- return false;
-}
-
-bool Output::matchEnumFallback() {
- if (EnumerationMatchFound)
- return false;
- EnumerationMatchFound = true;
- return true;
-}
-
-void Output::endEnumScalar() {
- if (!EnumerationMatchFound)
- llvm_unreachable("bad runtime enum value");
-}
-
-bool Output::beginBitSetScalar(bool &DoClear) {
- newLineCheck();
- output("[ ");
- NeedBitValueComma = false;
- DoClear = false;
- return true;
-}
-
-bool Output::bitSetMatch(const char *Str, bool Matches) {
- if (Matches) {
- if (NeedBitValueComma)
- output(", ");
- output(Str);
- NeedBitValueComma = true;
- }
- return false;
-}
-
-void Output::endBitSetScalar() {
- outputUpToEndOfLine(" ]");
-}
-
-void Output::scalarString(StringRef &S, QuotingType MustQuote) {
- newLineCheck();
- if (S.empty()) {
- // Print '' for the empty string because leaving the field empty is not
- // allowed.
- outputUpToEndOfLine("''");
- return;
- }
- if (MustQuote == QuotingType::None) {
- // Only quote if we must.
- outputUpToEndOfLine(S);
- return;
- }
-
- unsigned i = 0;
- unsigned j = 0;
- unsigned End = S.size();
- const char *Base = S.data();
-
- const char *const Quote = MustQuote == QuotingType::Single ? "'" : "\"";
- output(Quote); // Starting quote.
-
- // When using double-quoted strings (and only in that case), non-printable characters may be
- // present, and will be escaped using a variety of unicode-scalar and special short-form
- // escapes. This is handled in yaml::escape.
- if (MustQuote == QuotingType::Double) {
- output(yaml::escape(Base, /* EscapePrintable= */ false));
- outputUpToEndOfLine(Quote);
- return;
- }
-
- // When using single-quoted strings, any single quote ' must be doubled to be escaped.
- while (j < End) {
- if (S[j] == '\'') { // Escape quotes.
- output(StringRef(&Base[i], j - i)); // "flush".
- output(StringLiteral("''")); // Print it as ''
- i = j + 1;
- }
- ++j;
- }
- output(StringRef(&Base[i], j - i));
- outputUpToEndOfLine(Quote); // Ending quote.
-}
-
-void Output::blockScalarString(StringRef &S) {
- if (!StateStack.empty())
- newLineCheck();
- output(" |");
- outputNewLine();
-
- unsigned Indent = StateStack.empty() ? 1 : StateStack.size();
-
- auto Buffer = MemoryBuffer::getMemBuffer(S, "", false);
- for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) {
- for (unsigned I = 0; I < Indent; ++I) {
- output(" ");
- }
- output(*Lines);
- outputNewLine();
- }
-}
-
-void Output::scalarTag(std::string &Tag) {
- if (Tag.empty())
- return;
- newLineCheck();
- output(Tag);
- output(" ");
-}
-
-void Output::setError(const Twine &message) {
-}
-
-bool Output::canElideEmptySequence() {
- // Normally, with an optional key/value where the value is an empty sequence,
- // the whole key/value can be not written. But, that produces wrong yaml
- // if the key/value is the only thing in the map and the map is used in
- // a sequence. This detects if the this sequence is the first key/value
- // in map that itself is embedded in a sequnce.
- if (StateStack.size() < 2)
- return true;
- if (StateStack.back() != inMapFirstKey)
- return true;
- return !inSeqAnyElement(StateStack[StateStack.size() - 2]);
-}
-
-void Output::output(StringRef s) {
- Column += s.size();
- Out << s;
-}
-
-void Output::outputUpToEndOfLine(StringRef s) {
- output(s);
- if (StateStack.empty() || (!inFlowSeqAnyElement(StateStack.back()) &&
- !inFlowMapAnyKey(StateStack.back())))
- NeedsNewLine = true;
-}
-
-void Output::outputNewLine() {
- Out << "\n";
- Column = 0;
-}
-
-// if seq at top, indent as if map, then add "- "
-// if seq in middle, use "- " if firstKey, else use " "
-//
-
-void Output::newLineCheck() {
- if (!NeedsNewLine)
- return;
- NeedsNewLine = false;
-
- outputNewLine();
-
- if (StateStack.size() == 0)
- return;
-
- unsigned Indent = StateStack.size() - 1;
- bool OutputDash = false;
-
- if (StateStack.back() == inSeqFirstElement ||
- StateStack.back() == inSeqOtherElement) {
- OutputDash = true;
- } else if ((StateStack.size() > 1) &&
- ((StateStack.back() == inMapFirstKey) ||
- inFlowSeqAnyElement(StateStack.back()) ||
- (StateStack.back() == inFlowMapFirstKey)) &&
- inSeqAnyElement(StateStack[StateStack.size() - 2])) {
- --Indent;
- OutputDash = true;
- }
-
- for (unsigned i = 0; i < Indent; ++i) {
- output(" ");
- }
- if (OutputDash) {
- output("- ");
- }
-
-}
-
-void Output::paddedKey(StringRef key) {
- output(key);
- output(":");
- const char *spaces = " ";
- if (key.size() < strlen(spaces))
- output(&spaces[key.size()]);
- else
- output(" ");
-}
-
-void Output::flowKey(StringRef Key) {
- if (StateStack.back() == inFlowMapOtherKey)
- output(", ");
- if (WrapColumn && Column > WrapColumn) {
- output("\n");
- for (int I = 0; I < ColumnAtMapFlowStart; ++I)
- output(" ");
- Column = ColumnAtMapFlowStart;
- output(" ");
- }
- output(Key);
- output(": ");
-}
-
-NodeKind Output::getNodeKind() { report_fatal_error("invalid call"); }
-
-bool Output::inSeqAnyElement(InState State) {
- return State == inSeqFirstElement || State == inSeqOtherElement;
-}
-
-bool Output::inFlowSeqAnyElement(InState State) {
- return State == inFlowSeqFirstElement || State == inFlowSeqOtherElement;
-}
-
-bool Output::inMapAnyKey(InState State) {
- return State == inMapFirstKey || State == inMapOtherKey;
-}
-
-bool Output::inFlowMapAnyKey(InState State) {
- return State == inFlowMapFirstKey || State == inFlowMapOtherKey;
-}
-
-//===----------------------------------------------------------------------===//
-// traits for built-in types
-//===----------------------------------------------------------------------===//
-
-void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) {
- Out << (Val ? "true" : "false");
-}
-
-StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) {
- if (Scalar.equals("true")) {
- Val = true;
- return StringRef();
- } else if (Scalar.equals("false")) {
- Val = false;
- return StringRef();
- }
- return "invalid boolean";
-}
-
-void ScalarTraits<StringRef>::output(const StringRef &Val, void *,
- raw_ostream &Out) {
- Out << Val;
-}
-
-StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,
- StringRef &Val) {
- Val = Scalar;
- return StringRef();
-}
-
-void ScalarTraits<std::string>::output(const std::string &Val, void *,
- raw_ostream &Out) {
- Out << Val;
-}
-
-StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
- std::string &Val) {
- Val = Scalar.str();
- return StringRef();
-}
-
-void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,
- raw_ostream &Out) {
- // use temp uin32_t because ostream thinks uint8_t is a character
- uint32_t Num = Val;
- Out << Num;
-}
-
-StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) {
- unsigned long long n;
- if (getAsUnsignedInteger(Scalar, 0, n))
- return "invalid number";
- if (n > 0xFF)
- return "out of range number";
- Val = n;
- return StringRef();
-}
-
-void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *,
- raw_ostream &Out) {
- Out << Val;
-}
-
-StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *,
- uint16_t &Val) {
- unsigned long long n;
- if (getAsUnsignedInteger(Scalar, 0, n))
- return "invalid number";
- if (n > 0xFFFF)
- return "out of range number";
- Val = n;
- return StringRef();
-}
-
-void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *,
- raw_ostream &Out) {
- Out << Val;
-}
-
-StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *,
- uint32_t &Val) {
- unsigned long long n;
- if (getAsUnsignedInteger(Scalar, 0, n))
- return "invalid number";
- if (n > 0xFFFFFFFFUL)
- return "out of range number";
- Val = n;
- return StringRef();
-}
-
-void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *,
- raw_ostream &Out) {
- Out << Val;
-}
-
-StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *,
- uint64_t &Val) {
- unsigned long long N;
- if (getAsUnsignedInteger(Scalar, 0, N))
- return "invalid number";
- Val = N;
- return StringRef();
-}
-
-void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) {
- // use temp in32_t because ostream thinks int8_t is a character
- int32_t Num = Val;
- Out << Num;
-}
-
-StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) {
- long long N;
- if (getAsSignedInteger(Scalar, 0, N))
- return "invalid number";
- if ((N > 127) || (N < -128))
- return "out of range number";
- Val = N;
- return StringRef();
-}
-
-void ScalarTraits<int16_t>::output(const int16_t &Val, void *,
- raw_ostream &Out) {
- Out << Val;
-}
-
-StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) {
- long long N;
- if (getAsSignedInteger(Scalar, 0, N))
- return "invalid number";
- if ((N > INT16_MAX) || (N < INT16_MIN))
- return "out of range number";
- Val = N;
- return StringRef();
-}
-
-void ScalarTraits<int32_t>::output(const int32_t &Val, void *,
- raw_ostream &Out) {
- Out << Val;
-}
-
-StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) {
- long long N;
- if (getAsSignedInteger(Scalar, 0, N))
- return "invalid number";
- if ((N > INT32_MAX) || (N < INT32_MIN))
- return "out of range number";
- Val = N;
- return StringRef();
-}
-
-void ScalarTraits<int64_t>::output(const int64_t &Val, void *,
- raw_ostream &Out) {
- Out << Val;
-}
-
-StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) {
- long long N;
- if (getAsSignedInteger(Scalar, 0, N))
- return "invalid number";
- Val = N;
- return StringRef();
-}
-
-void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {
- Out << format("%g", Val);
-}
-
-StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {
- if (to_float(Scalar, Val))
- return StringRef();
- return "invalid floating point number";
-}
-
-void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
- Out << format("%g", Val);
-}
-
-StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {
- if (to_float(Scalar, Val))
- return StringRef();
- return "invalid floating point number";
-}
-
-void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {
- uint8_t Num = Val;
- Out << format("0x%02X", Num);
-}
-
-StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) {
- unsigned long long n;
- if (getAsUnsignedInteger(Scalar, 0, n))
- return "invalid hex8 number";
- if (n > 0xFF)
- return "out of range hex8 number";
- Val = n;
- return StringRef();
-}
-
-void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) {
- uint16_t Num = Val;
- Out << format("0x%04X", Num);
-}
-
-StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) {
- unsigned long long n;
- if (getAsUnsignedInteger(Scalar, 0, n))
- return "invalid hex16 number";
- if (n > 0xFFFF)
- return "out of range hex16 number";
- Val = n;
- return StringRef();
-}
-
-void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) {
- uint32_t Num = Val;
- Out << format("0x%08X", Num);
-}
-
-StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) {
- unsigned long long n;
- if (getAsUnsignedInteger(Scalar, 0, n))
- return "invalid hex32 number";
- if (n > 0xFFFFFFFFUL)
- return "out of range hex32 number";
- Val = n;
- return StringRef();
-}
-
-void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) {
- uint64_t Num = Val;
- Out << format("0x%016llX", Num);
-}
-
-StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) {
- unsigned long long Num;
- if (getAsUnsignedInteger(Scalar, 0, Num))
- return "invalid hex64 number";
- Val = Num;
- return StringRef();
-}
diff --git a/gnu/llvm/lib/Support/circular_raw_ostream.cpp b/gnu/llvm/lib/Support/circular_raw_ostream.cpp
deleted file mode 100644
index e768f17cd00..00000000000
--- a/gnu/llvm/lib/Support/circular_raw_ostream.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- circular_raw_ostream.cpp - Implement circular_raw_ostream ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This implements support for circular buffered streams.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/circular_raw_ostream.h"
-#include <algorithm>
-using namespace llvm;
-
-void circular_raw_ostream::write_impl(const char *Ptr, size_t Size) {
- if (BufferSize == 0) {
- TheStream->write(Ptr, Size);
- return;
- }
-
- // Write into the buffer, wrapping if necessary.
- while (Size != 0) {
- unsigned Bytes =
- std::min(unsigned(Size), unsigned(BufferSize - (Cur - BufferArray)));
- memcpy(Cur, Ptr, Bytes);
- Size -= Bytes;
- Cur += Bytes;
- if (Cur == BufferArray + BufferSize) {
- // Reset the output pointer to the start of the buffer.
- Cur = BufferArray;
- Filled = true;
- }
- }
-}
-
-void circular_raw_ostream::flushBufferWithBanner() {
- if (BufferSize != 0) {
- // Write out the buffer
- TheStream->write(Banner, std::strlen(Banner));
- flushBuffer();
- }
-}
diff --git a/gnu/llvm/lib/Support/raw_os_ostream.cpp b/gnu/llvm/lib/Support/raw_os_ostream.cpp
deleted file mode 100644
index 44f2325d7f8..00000000000
--- a/gnu/llvm/lib/Support/raw_os_ostream.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//===--- raw_os_ostream.cpp - Implement the raw_os_ostream class ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This implements support adapting raw_ostream to std::ostream.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/raw_os_ostream.h"
-#include <ostream>
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// raw_os_ostream
-//===----------------------------------------------------------------------===//
-
-raw_os_ostream::~raw_os_ostream() {
- flush();
-}
-
-void raw_os_ostream::write_impl(const char *Ptr, size_t Size) {
- OS.write(Ptr, Size);
-}
-
-uint64_t raw_os_ostream::current_pos() const { return OS.tellp(); }
diff --git a/gnu/llvm/lib/Support/raw_ostream.cpp b/gnu/llvm/lib/Support/raw_ostream.cpp
deleted file mode 100644
index 21dde7ff914..00000000000
--- a/gnu/llvm/lib/Support/raw_ostream.cpp
+++ /dev/null
@@ -1,918 +0,0 @@
-//===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This implements support for bulk buffered stream output.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/NativeFormatting.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/Program.h"
-#include <algorithm>
-#include <cctype>
-#include <cerrno>
-#include <cstdio>
-#include <iterator>
-#include <sys/stat.h>
-#include <system_error>
-
-// <fcntl.h> may provide O_BINARY.
-#if defined(HAVE_FCNTL_H)
-# include <fcntl.h>
-#endif
-
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined(__CYGWIN__)
-#include <io.h>
-#endif
-
-#if defined(_MSC_VER)
-#include <io.h>
-#ifndef STDIN_FILENO
-# define STDIN_FILENO 0
-#endif
-#ifndef STDOUT_FILENO
-# define STDOUT_FILENO 1
-#endif
-#ifndef STDERR_FILENO
-# define STDERR_FILENO 2
-#endif
-#endif
-
-#ifdef _WIN32
-#include "llvm/Support/ConvertUTF.h"
-#include "Windows/WindowsSupport.h"
-#endif
-
-using namespace llvm;
-
-raw_ostream::~raw_ostream() {
- // raw_ostream's subclasses should take care to flush the buffer
- // in their destructors.
- assert(OutBufCur == OutBufStart &&
- "raw_ostream destructor called with non-empty buffer!");
-
- if (BufferMode == InternalBuffer)
- delete [] OutBufStart;
-}
-
-size_t raw_ostream::preferred_buffer_size() const {
- // BUFSIZ is intended to be a reasonable default.
- return BUFSIZ;
-}
-
-void raw_ostream::SetBuffered() {
- // Ask the subclass to determine an appropriate buffer size.
- if (size_t Size = preferred_buffer_size())
- SetBufferSize(Size);
- else
- // It may return 0, meaning this stream should be unbuffered.
- SetUnbuffered();
-}
-
-void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,
- BufferKind Mode) {
- assert(((Mode == Unbuffered && !BufferStart && Size == 0) ||
- (Mode != Unbuffered && BufferStart && Size != 0)) &&
- "stream must be unbuffered or have at least one byte");
- // Make sure the current buffer is free of content (we can't flush here; the
- // child buffer management logic will be in write_impl).
- assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!");
-
- if (BufferMode == InternalBuffer)
- delete [] OutBufStart;
- OutBufStart = BufferStart;
- OutBufEnd = OutBufStart+Size;
- OutBufCur = OutBufStart;
- BufferMode = Mode;
-
- assert(OutBufStart <= OutBufEnd && "Invalid size!");
-}
-
-raw_ostream &raw_ostream::operator<<(unsigned long N) {
- write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer);
- return *this;
-}
-
-raw_ostream &raw_ostream::operator<<(long N) {
- write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer);
- return *this;
-}
-
-raw_ostream &raw_ostream::operator<<(unsigned long long N) {
- write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer);
- return *this;
-}
-
-raw_ostream &raw_ostream::operator<<(long long N) {
- write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer);
- return *this;
-}
-
-raw_ostream &raw_ostream::write_hex(unsigned long long N) {
- llvm::write_hex(*this, N, HexPrintStyle::Lower);
- return *this;
-}
-
-raw_ostream &raw_ostream::write_uuid(const uuid_t UUID) {
- for (int Idx = 0; Idx < 16; ++Idx) {
- *this << format("%02" PRIX32, UUID[Idx]);
- if (Idx == 3 || Idx == 5 || Idx == 7 || Idx == 9)
- *this << "-";
- }
- return *this;
-}
-
-
-raw_ostream &raw_ostream::write_escaped(StringRef Str,
- bool UseHexEscapes) {
- for (unsigned char c : Str) {
- switch (c) {
- case '\\':
- *this << '\\' << '\\';
- break;
- case '\t':
- *this << '\\' << 't';
- break;
- case '\n':
- *this << '\\' << 'n';
- break;
- case '"':
- *this << '\\' << '"';
- break;
- default:
- if (isPrint(c)) {
- *this << c;
- break;
- }
-
- // Write out the escaped representation.
- if (UseHexEscapes) {
- *this << '\\' << 'x';
- *this << hexdigit((c >> 4 & 0xF));
- *this << hexdigit((c >> 0) & 0xF);
- } else {
- // Always use a full 3-character octal escape.
- *this << '\\';
- *this << char('0' + ((c >> 6) & 7));
- *this << char('0' + ((c >> 3) & 7));
- *this << char('0' + ((c >> 0) & 7));
- }
- }
- }
-
- return *this;
-}
-
-raw_ostream &raw_ostream::operator<<(const void *P) {
- llvm::write_hex(*this, (uintptr_t)P, HexPrintStyle::PrefixLower);
- return *this;
-}
-
-raw_ostream &raw_ostream::operator<<(double N) {
- llvm::write_double(*this, N, FloatStyle::Exponent);
- return *this;
-}
-
-void raw_ostream::flush_nonempty() {
- assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
- size_t Length = OutBufCur - OutBufStart;
- OutBufCur = OutBufStart;
- write_impl(OutBufStart, Length);
-}
-
-raw_ostream &raw_ostream::write(unsigned char C) {
- // Group exceptional cases into a single branch.
- if (LLVM_UNLIKELY(OutBufCur >= OutBufEnd)) {
- if (LLVM_UNLIKELY(!OutBufStart)) {
- if (BufferMode == Unbuffered) {
- write_impl(reinterpret_cast<char*>(&C), 1);
- return *this;
- }
- // Set up a buffer and start over.
- SetBuffered();
- return write(C);
- }
-
- flush_nonempty();
- }
-
- *OutBufCur++ = C;
- return *this;
-}
-
-raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) {
- // Group exceptional cases into a single branch.
- if (LLVM_UNLIKELY(size_t(OutBufEnd - OutBufCur) < Size)) {
- if (LLVM_UNLIKELY(!OutBufStart)) {
- if (BufferMode == Unbuffered) {
- write_impl(Ptr, Size);
- return *this;
- }
- // Set up a buffer and start over.
- SetBuffered();
- return write(Ptr, Size);
- }
-
- size_t NumBytes = OutBufEnd - OutBufCur;
-
- // If the buffer is empty at this point we have a string that is larger
- // than the buffer. Directly write the chunk that is a multiple of the
- // preferred buffer size and put the remainder in the buffer.
- if (LLVM_UNLIKELY(OutBufCur == OutBufStart)) {
- assert(NumBytes != 0 && "undefined behavior");
- size_t BytesToWrite = Size - (Size % NumBytes);
- write_impl(Ptr, BytesToWrite);
- size_t BytesRemaining = Size - BytesToWrite;
- if (BytesRemaining > size_t(OutBufEnd - OutBufCur)) {
- // Too much left over to copy into our buffer.
- return write(Ptr + BytesToWrite, BytesRemaining);
- }
- copy_to_buffer(Ptr + BytesToWrite, BytesRemaining);
- return *this;
- }
-
- // We don't have enough space in the buffer to fit the string in. Insert as
- // much as possible, flush and start over with the remainder.
- copy_to_buffer(Ptr, NumBytes);
- flush_nonempty();
- return write(Ptr + NumBytes, Size - NumBytes);
- }
-
- copy_to_buffer(Ptr, Size);
-
- return *this;
-}
-
-void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) {
- assert(Size <= size_t(OutBufEnd - OutBufCur) && "Buffer overrun!");
-
- // Handle short strings specially, memcpy isn't very good at very short
- // strings.
- switch (Size) {
- case 4: OutBufCur[3] = Ptr[3]; LLVM_FALLTHROUGH;
- case 3: OutBufCur[2] = Ptr[2]; LLVM_FALLTHROUGH;
- case 2: OutBufCur[1] = Ptr[1]; LLVM_FALLTHROUGH;
- case 1: OutBufCur[0] = Ptr[0]; LLVM_FALLTHROUGH;
- case 0: break;
- default:
- memcpy(OutBufCur, Ptr, Size);
- break;
- }
-
- OutBufCur += Size;
-}
-
-// Formatted output.
-raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
- // If we have more than a few bytes left in our output buffer, try
- // formatting directly onto its end.
- size_t NextBufferSize = 127;
- size_t BufferBytesLeft = OutBufEnd - OutBufCur;
- if (BufferBytesLeft > 3) {
- size_t BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft);
-
- // Common case is that we have plenty of space.
- if (BytesUsed <= BufferBytesLeft) {
- OutBufCur += BytesUsed;
- return *this;
- }
-
- // Otherwise, we overflowed and the return value tells us the size to try
- // again with.
- NextBufferSize = BytesUsed;
- }
-
- // If we got here, we didn't have enough space in the output buffer for the
- // string. Try printing into a SmallVector that is resized to have enough
- // space. Iterate until we win.
- SmallVector<char, 128> V;
-
- while (true) {
- V.resize(NextBufferSize);
-
- // Try formatting into the SmallVector.
- size_t BytesUsed = Fmt.print(V.data(), NextBufferSize);
-
- // If BytesUsed fit into the vector, we win.
- if (BytesUsed <= NextBufferSize)
- return write(V.data(), BytesUsed);
-
- // Otherwise, try again with a new size.
- assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
- NextBufferSize = BytesUsed;
- }
-}
-
-raw_ostream &raw_ostream::operator<<(const formatv_object_base &Obj) {
- SmallString<128> S;
- Obj.format(*this);
- return *this;
-}
-
-raw_ostream &raw_ostream::operator<<(const FormattedString &FS) {
- if (FS.Str.size() >= FS.Width || FS.Justify == FormattedString::JustifyNone) {
- this->operator<<(FS.Str);
- return *this;
- }
- const size_t Difference = FS.Width - FS.Str.size();
- switch (FS.Justify) {
- case FormattedString::JustifyLeft:
- this->operator<<(FS.Str);
- this->indent(Difference);
- break;
- case FormattedString::JustifyRight:
- this->indent(Difference);
- this->operator<<(FS.Str);
- break;
- case FormattedString::JustifyCenter: {
- int PadAmount = Difference / 2;
- this->indent(PadAmount);
- this->operator<<(FS.Str);
- this->indent(Difference - PadAmount);
- break;
- }
- default:
- llvm_unreachable("Bad Justification");
- }
- return *this;
-}
-
-raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) {
- if (FN.Hex) {
- HexPrintStyle Style;
- if (FN.Upper && FN.HexPrefix)
- Style = HexPrintStyle::PrefixUpper;
- else if (FN.Upper && !FN.HexPrefix)
- Style = HexPrintStyle::Upper;
- else if (!FN.Upper && FN.HexPrefix)
- Style = HexPrintStyle::PrefixLower;
- else
- Style = HexPrintStyle::Lower;
- llvm::write_hex(*this, FN.HexValue, Style, FN.Width);
- } else {
- llvm::SmallString<16> Buffer;
- llvm::raw_svector_ostream Stream(Buffer);
- llvm::write_integer(Stream, FN.DecValue, 0, IntegerStyle::Integer);
- if (Buffer.size() < FN.Width)
- indent(FN.Width - Buffer.size());
- (*this) << Buffer;
- }
- return *this;
-}
-
-raw_ostream &raw_ostream::operator<<(const FormattedBytes &FB) {
- if (FB.Bytes.empty())
- return *this;
-
- size_t LineIndex = 0;
- auto Bytes = FB.Bytes;
- const size_t Size = Bytes.size();
- HexPrintStyle HPS = FB.Upper ? HexPrintStyle::Upper : HexPrintStyle::Lower;
- uint64_t OffsetWidth = 0;
- if (FB.FirstByteOffset.hasValue()) {
- // Figure out how many nibbles are needed to print the largest offset
- // represented by this data set, so that we can align the offset field
- // to the right width.
- size_t Lines = Size / FB.NumPerLine;
- uint64_t MaxOffset = *FB.FirstByteOffset + Lines * FB.NumPerLine;
- unsigned Power = 0;
- if (MaxOffset > 0)
- Power = llvm::Log2_64_Ceil(MaxOffset);
- OffsetWidth = std::max<uint64_t>(4, llvm::alignTo(Power, 4) / 4);
- }
-
- // The width of a block of data including all spaces for group separators.
- unsigned NumByteGroups =
- alignTo(FB.NumPerLine, FB.ByteGroupSize) / FB.ByteGroupSize;
- unsigned BlockCharWidth = FB.NumPerLine * 2 + NumByteGroups - 1;
-
- while (!Bytes.empty()) {
- indent(FB.IndentLevel);
-
- if (FB.FirstByteOffset.hasValue()) {
- uint64_t Offset = FB.FirstByteOffset.getValue();
- llvm::write_hex(*this, Offset + LineIndex, HPS, OffsetWidth);
- *this << ": ";
- }
-
- auto Line = Bytes.take_front(FB.NumPerLine);
-
- size_t CharsPrinted = 0;
- // Print the hex bytes for this line in groups
- for (size_t I = 0; I < Line.size(); ++I, CharsPrinted += 2) {
- if (I && (I % FB.ByteGroupSize) == 0) {
- ++CharsPrinted;
- *this << " ";
- }
- llvm::write_hex(*this, Line[I], HPS, 2);
- }
-
- if (FB.ASCII) {
- // Print any spaces needed for any bytes that we didn't print on this
- // line so that the ASCII bytes are correctly aligned.
- assert(BlockCharWidth >= CharsPrinted);
- indent(BlockCharWidth - CharsPrinted + 2);
- *this << "|";
-
- // Print the ASCII char values for each byte on this line
- for (uint8_t Byte : Line) {
- if (isPrint(Byte))
- *this << static_cast<char>(Byte);
- else
- *this << '.';
- }
- *this << '|';
- }
-
- Bytes = Bytes.drop_front(Line.size());
- LineIndex += Line.size();
- if (LineIndex < Size)
- *this << '\n';
- }
- return *this;
-}
-
-template <char C>
-static raw_ostream &write_padding(raw_ostream &OS, unsigned NumChars) {
- static const char Chars[] = {C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,
- C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,
- C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,
- C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,
- C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C};
-
- // Usually the indentation is small, handle it with a fastpath.
- if (NumChars < array_lengthof(Chars))
- return OS.write(Chars, NumChars);
-
- while (NumChars) {
- unsigned NumToWrite = std::min(NumChars,
- (unsigned)array_lengthof(Chars)-1);
- OS.write(Chars, NumToWrite);
- NumChars -= NumToWrite;
- }
- return OS;
-}
-
-/// indent - Insert 'NumSpaces' spaces.
-raw_ostream &raw_ostream::indent(unsigned NumSpaces) {
- return write_padding<' '>(*this, NumSpaces);
-}
-
-/// write_zeros - Insert 'NumZeros' nulls.
-raw_ostream &raw_ostream::write_zeros(unsigned NumZeros) {
- return write_padding<'\0'>(*this, NumZeros);
-}
-
-void raw_ostream::anchor() {}
-
-//===----------------------------------------------------------------------===//
-// Formatted Output
-//===----------------------------------------------------------------------===//
-
-// Out of line virtual method.
-void format_object_base::home() {
-}
-
-//===----------------------------------------------------------------------===//
-// raw_fd_ostream
-//===----------------------------------------------------------------------===//
-
-static int getFD(StringRef Filename, std::error_code &EC,
- sys::fs::CreationDisposition Disp, sys::fs::FileAccess Access,
- sys::fs::OpenFlags Flags) {
- assert((Access & sys::fs::FA_Write) &&
- "Cannot make a raw_ostream from a read-only descriptor!");
-
- // Handle "-" as stdout. Note that when we do this, we consider ourself
- // the owner of stdout and may set the "binary" flag globally based on Flags.
- if (Filename == "-") {
- EC = std::error_code();
- // If user requested binary then put stdout into binary mode if
- // possible.
- if (!(Flags & sys::fs::OF_Text))
- sys::ChangeStdoutToBinary();
- return STDOUT_FILENO;
- }
-
- int FD;
- if (Access & sys::fs::FA_Read)
- EC = sys::fs::openFileForReadWrite(Filename, FD, Disp, Flags);
- else
- EC = sys::fs::openFileForWrite(Filename, FD, Disp, Flags);
- if (EC)
- return -1;
-
- return FD;
-}
-
-raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC)
- : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, sys::fs::FA_Write,
- sys::fs::OF_None) {}
-
-raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
- sys::fs::CreationDisposition Disp)
- : raw_fd_ostream(Filename, EC, Disp, sys::fs::FA_Write, sys::fs::OF_None) {}
-
-raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
- sys::fs::FileAccess Access)
- : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, Access,
- sys::fs::OF_None) {}
-
-raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
- sys::fs::OpenFlags Flags)
- : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, sys::fs::FA_Write,
- Flags) {}
-
-raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
- sys::fs::CreationDisposition Disp,
- sys::fs::FileAccess Access,
- sys::fs::OpenFlags Flags)
- : raw_fd_ostream(getFD(Filename, EC, Disp, Access, Flags), true) {}
-
-/// FD is the file descriptor that this writes to. If ShouldClose is true, this
-/// closes the file when the stream is destroyed.
-raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered)
- : raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose) {
- if (FD < 0 ) {
- ShouldClose = false;
- return;
- }
-
- // Do not attempt to close stdout or stderr. We used to try to maintain the
- // property that tools that support writing file to stdout should not also
- // write informational output to stdout, but in practice we were never able to
- // maintain this invariant. Many features have been added to LLVM and clang
- // (-fdump-record-layouts, optimization remarks, etc) that print to stdout, so
- // users must simply be aware that mixed output and remarks is a possibility.
- if (FD <= STDERR_FILENO)
- ShouldClose = false;
-
-#ifdef _WIN32
- // Check if this is a console device. This is not equivalent to isatty.
- IsWindowsConsole =
- ::GetFileType((HANDLE)::_get_osfhandle(fd)) == FILE_TYPE_CHAR;
-#endif
-
- // Get the starting position.
- off_t loc = ::lseek(FD, 0, SEEK_CUR);
-#ifdef _WIN32
- // MSVCRT's _lseek(SEEK_CUR) doesn't return -1 for pipes.
- sys::fs::file_status Status;
- std::error_code EC = status(FD, Status);
- SupportsSeeking = !EC && Status.type() == sys::fs::file_type::regular_file;
-#else
- SupportsSeeking = loc != (off_t)-1;
-#endif
- if (!SupportsSeeking)
- pos = 0;
- else
- pos = static_cast<uint64_t>(loc);
-}
-
-raw_fd_ostream::~raw_fd_ostream() {
- if (FD >= 0) {
- flush();
- if (ShouldClose) {
- if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))
- error_detected(EC);
- }
- }
-
-#ifdef __MINGW32__
- // On mingw, global dtors should not call exit().
- // report_fatal_error() invokes exit(). We know report_fatal_error()
- // might not write messages to stderr when any errors were detected
- // on FD == 2.
- if (FD == 2) return;
-#endif
-
- // If there are any pending errors, report them now. Clients wishing
- // to avoid report_fatal_error calls should check for errors with
- // has_error() and clear the error flag with clear_error() before
- // destructing raw_ostream objects which may have errors.
- if (has_error())
- report_fatal_error("IO failure on output stream: " + error().message(),
- /*GenCrashDiag=*/false);
-}
-
-#if defined(_WIN32)
-// The most reliable way to print unicode in a Windows console is with
-// WriteConsoleW. To use that, first transcode from UTF-8 to UTF-16. This
-// assumes that LLVM programs always print valid UTF-8 to the console. The data
-// might not be UTF-8 for two major reasons:
-// 1. The program is printing binary (-filetype=obj -o -), in which case it
-// would have been gibberish anyway.
-// 2. The program is printing text in a semi-ascii compatible codepage like
-// shift-jis or cp1252.
-//
-// Most LLVM programs don't produce non-ascii text unless they are quoting
-// user source input. A well-behaved LLVM program should either validate that
-// the input is UTF-8 or transcode from the local codepage to UTF-8 before
-// quoting it. If they don't, this may mess up the encoding, but this is still
-// probably the best compromise we can make.
-static bool write_console_impl(int FD, StringRef Data) {
- SmallVector<wchar_t, 256> WideText;
-
- // Fall back to ::write if it wasn't valid UTF-8.
- if (auto EC = sys::windows::UTF8ToUTF16(Data, WideText))
- return false;
-
- // On Windows 7 and earlier, WriteConsoleW has a low maximum amount of data
- // that can be written to the console at a time.
- size_t MaxWriteSize = WideText.size();
- if (!RunningWindows8OrGreater())
- MaxWriteSize = 32767;
-
- size_t WCharsWritten = 0;
- do {
- size_t WCharsToWrite =
- std::min(MaxWriteSize, WideText.size() - WCharsWritten);
- DWORD ActuallyWritten;
- bool Success =
- ::WriteConsoleW((HANDLE)::_get_osfhandle(FD), &WideText[WCharsWritten],
- WCharsToWrite, &ActuallyWritten,
- /*Reserved=*/nullptr);
-
- // The most likely reason for WriteConsoleW to fail is that FD no longer
- // points to a console. Fall back to ::write. If this isn't the first loop
- // iteration, something is truly wrong.
- if (!Success)
- return false;
-
- WCharsWritten += ActuallyWritten;
- } while (WCharsWritten != WideText.size());
- return true;
-}
-#endif
-
-void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
- assert(FD >= 0 && "File already closed.");
- pos += Size;
-
-#if defined(_WIN32)
- // If this is a Windows console device, try re-encoding from UTF-8 to UTF-16
- // and using WriteConsoleW. If that fails, fall back to plain write().
- if (IsWindowsConsole)
- if (write_console_impl(FD, StringRef(Ptr, Size)))
- return;
-#endif
-
- // The maximum write size is limited to INT32_MAX. A write
- // greater than SSIZE_MAX is implementation-defined in POSIX,
- // and Windows _write requires 32 bit input.
- size_t MaxWriteSize = INT32_MAX;
-
-#if defined(__linux__)
- // It is observed that Linux returns EINVAL for a very large write (>2G).
- // Make it a reasonably small value.
- MaxWriteSize = 1024 * 1024 * 1024;
-#endif
-
- do {
- size_t ChunkSize = std::min(Size, MaxWriteSize);
- ssize_t ret = ::write(FD, Ptr, ChunkSize);
-
- if (ret < 0) {
- // If it's a recoverable error, swallow it and retry the write.
- //
- // Ideally we wouldn't ever see EAGAIN or EWOULDBLOCK here, since
- // raw_ostream isn't designed to do non-blocking I/O. However, some
- // programs, such as old versions of bjam, have mistakenly used
- // O_NONBLOCK. For compatibility, emulate blocking semantics by
- // spinning until the write succeeds. If you don't want spinning,
- // don't use O_NONBLOCK file descriptors with raw_ostream.
- if (errno == EINTR || errno == EAGAIN
-#ifdef EWOULDBLOCK
- || errno == EWOULDBLOCK
-#endif
- )
- continue;
-
- // Otherwise it's a non-recoverable error. Note it and quit.
- error_detected(std::error_code(errno, std::generic_category()));
- break;
- }
-
- // The write may have written some or all of the data. Update the
- // size and buffer pointer to reflect the remainder that needs
- // to be written. If there are no bytes left, we're done.
- Ptr += ret;
- Size -= ret;
- } while (Size > 0);
-}
-
-void raw_fd_ostream::close() {
- assert(ShouldClose);
- ShouldClose = false;
- flush();
- if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))
- error_detected(EC);
- FD = -1;
-}
-
-uint64_t raw_fd_ostream::seek(uint64_t off) {
- assert(SupportsSeeking && "Stream does not support seeking!");
- flush();
-#ifdef _WIN32
- pos = ::_lseeki64(FD, off, SEEK_SET);
-#elif defined(HAVE_LSEEK64)
- pos = ::lseek64(FD, off, SEEK_SET);
-#else
- pos = ::lseek(FD, off, SEEK_SET);
-#endif
- if (pos == (uint64_t)-1)
- error_detected(std::error_code(errno, std::generic_category()));
- return pos;
-}
-
-void raw_fd_ostream::pwrite_impl(const char *Ptr, size_t Size,
- uint64_t Offset) {
- uint64_t Pos = tell();
- seek(Offset);
- write(Ptr, Size);
- seek(Pos);
-}
-
-size_t raw_fd_ostream::preferred_buffer_size() const {
-#if defined(_WIN32)
- // Disable buffering for console devices. Console output is re-encoded from
- // UTF-8 to UTF-16 on Windows, and buffering it would require us to split the
- // buffer on a valid UTF-8 codepoint boundary. Terminal buffering is disabled
- // below on most other OSs, so do the same thing on Windows and avoid that
- // complexity.
- if (IsWindowsConsole)
- return 0;
- return raw_ostream::preferred_buffer_size();
-#elif !defined(__minix)
- // Minix has no st_blksize.
- assert(FD >= 0 && "File not yet open!");
- struct stat statbuf;
- if (fstat(FD, &statbuf) != 0)
- return 0;
-
- // If this is a terminal, don't use buffering. Line buffering
- // would be a more traditional thing to do, but it's not worth
- // the complexity.
- if (S_ISCHR(statbuf.st_mode) && isatty(FD))
- return 0;
- // Return the preferred block size.
- return statbuf.st_blksize;
-#else
- return raw_ostream::preferred_buffer_size();
-#endif
-}
-
-raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold,
- bool bg) {
- if (sys::Process::ColorNeedsFlush())
- flush();
- const char *colorcode =
- (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg)
- : sys::Process::OutputColor(colors, bold, bg);
- if (colorcode) {
- size_t len = strlen(colorcode);
- write(colorcode, len);
- // don't account colors towards output characters
- pos -= len;
- }
- return *this;
-}
-
-raw_ostream &raw_fd_ostream::resetColor() {
- if (sys::Process::ColorNeedsFlush())
- flush();
- const char *colorcode = sys::Process::ResetColor();
- if (colorcode) {
- size_t len = strlen(colorcode);
- write(colorcode, len);
- // don't account colors towards output characters
- pos -= len;
- }
- return *this;
-}
-
-raw_ostream &raw_fd_ostream::reverseColor() {
- if (sys::Process::ColorNeedsFlush())
- flush();
- const char *colorcode = sys::Process::OutputReverse();
- if (colorcode) {
- size_t len = strlen(colorcode);
- write(colorcode, len);
- // don't account colors towards output characters
- pos -= len;
- }
- return *this;
-}
-
-bool raw_fd_ostream::is_displayed() const {
- return sys::Process::FileDescriptorIsDisplayed(FD);
-}
-
-bool raw_fd_ostream::has_colors() const {
- return sys::Process::FileDescriptorHasColors(FD);
-}
-
-void raw_fd_ostream::anchor() {}
-
-//===----------------------------------------------------------------------===//
-// outs(), errs(), nulls()
-//===----------------------------------------------------------------------===//
-
-/// outs() - This returns a reference to a raw_ostream for standard output.
-/// Use it like: outs() << "foo" << "bar";
-raw_ostream &llvm::outs() {
- // Set buffer settings to model stdout behavior.
- std::error_code EC;
- static raw_fd_ostream S("-", EC, sys::fs::F_None);
- assert(!EC);
- return S;
-}
-
-/// errs() - This returns a reference to a raw_ostream for standard error.
-/// Use it like: errs() << "foo" << "bar";
-raw_ostream &llvm::errs() {
- // Set standard error to be unbuffered by default.
- static raw_fd_ostream S(STDERR_FILENO, false, true);
- return S;
-}
-
-/// nulls() - This returns a reference to a raw_ostream which discards output.
-raw_ostream &llvm::nulls() {
- static raw_null_ostream S;
- return S;
-}
-
-//===----------------------------------------------------------------------===//
-// raw_string_ostream
-//===----------------------------------------------------------------------===//
-
-raw_string_ostream::~raw_string_ostream() {
- flush();
-}
-
-void raw_string_ostream::write_impl(const char *Ptr, size_t Size) {
- OS.append(Ptr, Size);
-}
-
-//===----------------------------------------------------------------------===//
-// raw_svector_ostream
-//===----------------------------------------------------------------------===//
-
-uint64_t raw_svector_ostream::current_pos() const { return OS.size(); }
-
-void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) {
- OS.append(Ptr, Ptr + Size);
-}
-
-void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size,
- uint64_t Offset) {
- memcpy(OS.data() + Offset, Ptr, Size);
-}
-
-//===----------------------------------------------------------------------===//
-// raw_null_ostream
-//===----------------------------------------------------------------------===//
-
-raw_null_ostream::~raw_null_ostream() {
-#ifndef NDEBUG
- // ~raw_ostream asserts that the buffer is empty. This isn't necessary
- // with raw_null_ostream, but it's better to have raw_null_ostream follow
- // the rules than to change the rules just for raw_null_ostream.
- flush();
-#endif
-}
-
-void raw_null_ostream::write_impl(const char *Ptr, size_t Size) {
-}
-
-uint64_t raw_null_ostream::current_pos() const {
- return 0;
-}
-
-void raw_null_ostream::pwrite_impl(const char *Ptr, size_t Size,
- uint64_t Offset) {}
-
-void raw_pwrite_stream::anchor() {}
-
-void buffer_ostream::anchor() {}
diff --git a/gnu/llvm/lib/Support/regcomp.c b/gnu/llvm/lib/Support/regcomp.c
deleted file mode 100644
index 12669ab75d1..00000000000
--- a/gnu/llvm/lib/Support/regcomp.c
+++ /dev/null
@@ -1,1701 +0,0 @@
-/*-
- * This code is derived from OpenBSD's libc/regex, original license follows:
- *
- * Copyright (c) 1992, 1993, 1994 Henry Spencer.
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Henry Spencer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)regcomp.c 8.5 (Berkeley) 3/20/94
- */
-
-#include <sys/types.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdlib.h>
-#include "regex_impl.h"
-
-#include "regutils.h"
-#include "regex2.h"
-
-#include "llvm/Config/config.h"
-
-/* character-class table */
-static struct cclass {
- const char *name;
- const char *chars;
- const char *multis;
-} cclasses[] = {
- { "alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-0123456789", ""} ,
- { "alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
- ""} ,
- { "blank", " \t", ""} ,
- { "cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\
-\25\26\27\30\31\32\33\34\35\36\37\177", ""} ,
- { "digit", "0123456789", ""} ,
- { "graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- ""} ,
- { "lower", "abcdefghijklmnopqrstuvwxyz",
- ""} ,
- { "print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ",
- ""} ,
- { "punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- ""} ,
- { "space", "\t\n\v\f\r ", ""} ,
- { "upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
- ""} ,
- { "xdigit", "0123456789ABCDEFabcdef",
- ""} ,
- { NULL, 0, "" }
-};
-
-/* character-name table */
-static struct cname {
- const char *name;
- char code;
-} cnames[] = {
- { "NUL", '\0' },
- { "SOH", '\001' },
- { "STX", '\002' },
- { "ETX", '\003' },
- { "EOT", '\004' },
- { "ENQ", '\005' },
- { "ACK", '\006' },
- { "BEL", '\007' },
- { "alert", '\007' },
- { "BS", '\010' },
- { "backspace", '\b' },
- { "HT", '\011' },
- { "tab", '\t' },
- { "LF", '\012' },
- { "newline", '\n' },
- { "VT", '\013' },
- { "vertical-tab", '\v' },
- { "FF", '\014' },
- { "form-feed", '\f' },
- { "CR", '\015' },
- { "carriage-return", '\r' },
- { "SO", '\016' },
- { "SI", '\017' },
- { "DLE", '\020' },
- { "DC1", '\021' },
- { "DC2", '\022' },
- { "DC3", '\023' },
- { "DC4", '\024' },
- { "NAK", '\025' },
- { "SYN", '\026' },
- { "ETB", '\027' },
- { "CAN", '\030' },
- { "EM", '\031' },
- { "SUB", '\032' },
- { "ESC", '\033' },
- { "IS4", '\034' },
- { "FS", '\034' },
- { "IS3", '\035' },
- { "GS", '\035' },
- { "IS2", '\036' },
- { "RS", '\036' },
- { "IS1", '\037' },
- { "US", '\037' },
- { "space", ' ' },
- { "exclamation-mark", '!' },
- { "quotation-mark", '"' },
- { "number-sign", '#' },
- { "dollar-sign", '$' },
- { "percent-sign", '%' },
- { "ampersand", '&' },
- { "apostrophe", '\'' },
- { "left-parenthesis", '(' },
- { "right-parenthesis", ')' },
- { "asterisk", '*' },
- { "plus-sign", '+' },
- { "comma", ',' },
- { "hyphen", '-' },
- { "hyphen-minus", '-' },
- { "period", '.' },
- { "full-stop", '.' },
- { "slash", '/' },
- { "solidus", '/' },
- { "zero", '0' },
- { "one", '1' },
- { "two", '2' },
- { "three", '3' },
- { "four", '4' },
- { "five", '5' },
- { "six", '6' },
- { "seven", '7' },
- { "eight", '8' },
- { "nine", '9' },
- { "colon", ':' },
- { "semicolon", ';' },
- { "less-than-sign", '<' },
- { "equals-sign", '=' },
- { "greater-than-sign", '>' },
- { "question-mark", '?' },
- { "commercial-at", '@' },
- { "left-square-bracket", '[' },
- { "backslash", '\\' },
- { "reverse-solidus", '\\' },
- { "right-square-bracket", ']' },
- { "circumflex", '^' },
- { "circumflex-accent", '^' },
- { "underscore", '_' },
- { "low-line", '_' },
- { "grave-accent", '`' },
- { "left-brace", '{' },
- { "left-curly-bracket", '{' },
- { "vertical-line", '|' },
- { "right-brace", '}' },
- { "right-curly-bracket", '}' },
- { "tilde", '~' },
- { "DEL", '\177' },
- { NULL, 0 }
-};
-
-/*
- * parse structure, passed up and down to avoid global variables and
- * other clumsinesses
- */
-struct parse {
- char *next; /* next character in RE */
- char *end; /* end of string (-> NUL normally) */
- int error; /* has an error been seen? */
- sop *strip; /* malloced strip */
- sopno ssize; /* malloced strip size (allocated) */
- sopno slen; /* malloced strip length (used) */
- int ncsalloc; /* number of csets allocated */
- struct re_guts *g;
-# define NPAREN 10 /* we need to remember () 1-9 for back refs */
- sopno pbegin[NPAREN]; /* -> ( ([0] unused) */
- sopno pend[NPAREN]; /* -> ) ([0] unused) */
-};
-
-static void p_ere(struct parse *, int);
-static void p_ere_exp(struct parse *);
-static void p_str(struct parse *);
-static void p_bre(struct parse *, int, int);
-static int p_simp_re(struct parse *, int);
-static int p_count(struct parse *);
-static void p_bracket(struct parse *);
-static void p_b_term(struct parse *, cset *);
-static void p_b_cclass(struct parse *, cset *);
-static void p_b_eclass(struct parse *, cset *);
-static char p_b_symbol(struct parse *);
-static char p_b_coll_elem(struct parse *, int);
-static char othercase(int);
-static void bothcases(struct parse *, int);
-static void ordinary(struct parse *, int);
-static void nonnewline(struct parse *);
-static void repeat(struct parse *, sopno, int, int);
-static int seterr(struct parse *, int);
-static cset *allocset(struct parse *);
-static void freeset(struct parse *, cset *);
-static int freezeset(struct parse *, cset *);
-static int firstch(struct parse *, cset *);
-static int nch(struct parse *, cset *);
-static void mcadd(struct parse *, cset *, const char *);
-static void mcinvert(struct parse *, cset *);
-static void mccase(struct parse *, cset *);
-static int isinsets(struct re_guts *, int);
-static int samesets(struct re_guts *, int, int);
-static void categorize(struct parse *, struct re_guts *);
-static sopno dupl(struct parse *, sopno, sopno);
-static void doemit(struct parse *, sop, size_t);
-static void doinsert(struct parse *, sop, size_t, sopno);
-static void dofwd(struct parse *, sopno, sop);
-static void enlarge(struct parse *, sopno);
-static void stripsnug(struct parse *, struct re_guts *);
-static void findmust(struct parse *, struct re_guts *);
-static sopno pluscount(struct parse *, struct re_guts *);
-
-static char nuls[10]; /* place to point scanner in event of error */
-
-/*
- * macros for use with parse structure
- * BEWARE: these know that the parse structure is named `p' !!!
- */
-#define PEEK() (*p->next)
-#define PEEK2() (*(p->next+1))
-#define MORE() (p->next < p->end)
-#define MORE2() (p->next+1 < p->end)
-#define SEE(c) (MORE() && PEEK() == (c))
-#define SEETWO(a, b) (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b))
-#define EAT(c) ((SEE(c)) ? (NEXT(), 1) : 0)
-#define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0)
-#define NEXT() (p->next++)
-#define NEXT2() (p->next += 2)
-#define NEXTn(n) (p->next += (n))
-#define GETNEXT() (*p->next++)
-#define SETERROR(e) seterr(p, (e))
-#define REQUIRE(co, e) (void)((co) || SETERROR(e))
-#define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e))
-#define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e))
-#define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e))
-#define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd))
-#define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos)
-#define AHEAD(pos) dofwd(p, pos, HERE()-(pos))
-#define ASTERN(sop, pos) EMIT(sop, HERE()-pos)
-#define HERE() (p->slen)
-#define THERE() (p->slen - 1)
-#define THERETHERE() (p->slen - 2)
-#define DROP(n) (p->slen -= (n))
-
-#ifdef _POSIX2_RE_DUP_MAX
-#define DUPMAX _POSIX2_RE_DUP_MAX
-#else
-#define DUPMAX 255
-#endif
-#define INFINITY (DUPMAX + 1)
-
-#ifndef NDEBUG
-static int never = 0; /* for use in asserts; shuts lint up */
-#else
-#define never 0 /* some <assert.h>s have bugs too */
-#endif
-
-/*
- - llvm_regcomp - interface for parser and compilation
- */
-int /* 0 success, otherwise REG_something */
-llvm_regcomp(llvm_regex_t *preg, const char *pattern, int cflags)
-{
- struct parse pa;
- struct re_guts *g;
- struct parse *p = &pa;
- int i;
- size_t len;
-#ifdef REDEBUG
-# define GOODFLAGS(f) (f)
-#else
-# define GOODFLAGS(f) ((f)&~REG_DUMP)
-#endif
-
- cflags = GOODFLAGS(cflags);
- if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))
- return(REG_INVARG);
-
- if (cflags&REG_PEND) {
- if (preg->re_endp < pattern)
- return(REG_INVARG);
- len = preg->re_endp - pattern;
- } else
- len = strlen((const char *)pattern);
-
- /* do the mallocs early so failure handling is easy */
- g = (struct re_guts *)malloc(sizeof(struct re_guts) +
- (NC-1)*sizeof(cat_t));
- if (g == NULL)
- return(REG_ESPACE);
- p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */
- p->strip = (sop *)calloc(p->ssize, sizeof(sop));
- p->slen = 0;
- if (p->strip == NULL) {
- free((char *)g);
- return(REG_ESPACE);
- }
-
- /* set things up */
- p->g = g;
- p->next = (char *)pattern; /* convenience; we do not modify it */
- p->end = p->next + len;
- p->error = 0;
- p->ncsalloc = 0;
- for (i = 0; i < NPAREN; i++) {
- p->pbegin[i] = 0;
- p->pend[i] = 0;
- }
- g->csetsize = NC;
- g->sets = NULL;
- g->setbits = NULL;
- g->ncsets = 0;
- g->cflags = cflags;
- g->iflags = 0;
- g->nbol = 0;
- g->neol = 0;
- g->must = NULL;
- g->mlen = 0;
- g->nsub = 0;
- g->ncategories = 1; /* category 0 is "everything else" */
- g->categories = &g->catspace[-(CHAR_MIN)];
- (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t));
- g->backrefs = 0;
-
- /* do it */
- EMIT(OEND, 0);
- g->firststate = THERE();
- if (cflags&REG_EXTENDED)
- p_ere(p, OUT);
- else if (cflags&REG_NOSPEC)
- p_str(p);
- else
- p_bre(p, OUT, OUT);
- EMIT(OEND, 0);
- g->laststate = THERE();
-
- /* tidy up loose ends and fill things in */
- categorize(p, g);
- stripsnug(p, g);
- findmust(p, g);
- g->nplus = pluscount(p, g);
- g->magic = MAGIC2;
- preg->re_nsub = g->nsub;
- preg->re_g = g;
- preg->re_magic = MAGIC1;
-#ifndef REDEBUG
- /* not debugging, so can't rely on the assert() in llvm_regexec() */
- if (g->iflags&REGEX_BAD)
- SETERROR(REG_ASSERT);
-#endif
-
- /* win or lose, we're done */
- if (p->error != 0) /* lose */
- llvm_regfree(preg);
- return(p->error);
-}
-
-/*
- - p_ere - ERE parser top level, concatenation and alternation
- */
-static void
-p_ere(struct parse *p, int stop) /* character this ERE should end at */
-{
- char c;
- sopno prevback = 0;
- sopno prevfwd = 0;
- sopno conc;
- int first = 1; /* is this the first alternative? */
-
- for (;;) {
- /* do a bunch of concatenated expressions */
- conc = HERE();
- while (MORE() && (c = PEEK()) != '|' && c != stop)
- p_ere_exp(p);
- REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */
-
- if (!EAT('|'))
- break; /* NOTE BREAK OUT */
-
- if (first) {
- INSERT(OCH_, conc); /* offset is wrong */
- prevfwd = conc;
- prevback = conc;
- first = 0;
- }
- ASTERN(OOR1, prevback);
- prevback = THERE();
- AHEAD(prevfwd); /* fix previous offset */
- prevfwd = HERE();
- EMIT(OOR2, 0); /* offset is very wrong */
- }
-
- if (!first) { /* tail-end fixups */
- AHEAD(prevfwd);
- ASTERN(O_CH, prevback);
- }
-
- assert(!MORE() || SEE(stop));
-}
-
-/*
- - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op
- */
-static void
-p_ere_exp(struct parse *p)
-{
- char c;
- sopno pos;
- int count;
- int count2;
- int backrefnum;
- sopno subno;
- int wascaret = 0;
-
- assert(MORE()); /* caller should have ensured this */
- c = GETNEXT();
-
- pos = HERE();
- switch (c) {
- case '(':
- REQUIRE(MORE(), REG_EPAREN);
- p->g->nsub++;
- subno = p->g->nsub;
- if (subno < NPAREN)
- p->pbegin[subno] = HERE();
- EMIT(OLPAREN, subno);
- if (!SEE(')'))
- p_ere(p, ')');
- if (subno < NPAREN) {
- p->pend[subno] = HERE();
- assert(p->pend[subno] != 0);
- }
- EMIT(ORPAREN, subno);
- MUSTEAT(')', REG_EPAREN);
- break;
-#ifndef POSIX_MISTAKE
- case ')': /* happens only if no current unmatched ( */
- /*
- * You may ask, why the ifndef? Because I didn't notice
- * this until slightly too late for 1003.2, and none of the
- * other 1003.2 regular-expression reviewers noticed it at
- * all. So an unmatched ) is legal POSIX, at least until
- * we can get it fixed.
- */
- SETERROR(REG_EPAREN);
- break;
-#endif
- case '^':
- EMIT(OBOL, 0);
- p->g->iflags |= USEBOL;
- p->g->nbol++;
- wascaret = 1;
- break;
- case '$':
- EMIT(OEOL, 0);
- p->g->iflags |= USEEOL;
- p->g->neol++;
- break;
- case '|':
- SETERROR(REG_EMPTY);
- break;
- case '*':
- case '+':
- case '?':
- SETERROR(REG_BADRPT);
- break;
- case '.':
- if (p->g->cflags&REG_NEWLINE)
- nonnewline(p);
- else
- EMIT(OANY, 0);
- break;
- case '[':
- p_bracket(p);
- break;
- case '\\':
- REQUIRE(MORE(), REG_EESCAPE);
- c = GETNEXT();
- if (c >= '1' && c <= '9') {
- /* \[0-9] is taken to be a back-reference to a previously specified
- * matching group. backrefnum will hold the number. The matching
- * group must exist (i.e. if \4 is found there must have been at
- * least 4 matching groups specified in the pattern previously).
- */
- backrefnum = c - '0';
- if (p->pend[backrefnum] == 0) {
- SETERROR(REG_ESUBREG);
- break;
- }
-
- /* Make sure everything checks out and emit the sequence
- * that marks a back-reference to the parse structure.
- */
- assert(backrefnum <= p->g->nsub);
- EMIT(OBACK_, backrefnum);
- assert(p->pbegin[backrefnum] != 0);
- assert(OP(p->strip[p->pbegin[backrefnum]]) != OLPAREN);
- assert(OP(p->strip[p->pend[backrefnum]]) != ORPAREN);
- (void) dupl(p, p->pbegin[backrefnum]+1, p->pend[backrefnum]);
- EMIT(O_BACK, backrefnum);
- p->g->backrefs = 1;
- } else {
- /* Other chars are simply themselves when escaped with a backslash.
- */
- ordinary(p, c);
- }
- break;
- case '{': /* okay as ordinary except if digit follows */
- REQUIRE(!MORE() || !isdigit((uch)PEEK()), REG_BADRPT);
- /* FALLTHROUGH */
- default:
- ordinary(p, c);
- break;
- }
-
- if (!MORE())
- return;
- c = PEEK();
- /* we call { a repetition if followed by a digit */
- if (!( c == '*' || c == '+' || c == '?' ||
- (c == '{' && MORE2() && isdigit((uch)PEEK2())) ))
- return; /* no repetition, we're done */
- NEXT();
-
- REQUIRE(!wascaret, REG_BADRPT);
- switch (c) {
- case '*': /* implemented as +? */
- /* this case does not require the (y|) trick, noKLUDGE */
- INSERT(OPLUS_, pos);
- ASTERN(O_PLUS, pos);
- INSERT(OQUEST_, pos);
- ASTERN(O_QUEST, pos);
- break;
- case '+':
- INSERT(OPLUS_, pos);
- ASTERN(O_PLUS, pos);
- break;
- case '?':
- /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
- INSERT(OCH_, pos); /* offset slightly wrong */
- ASTERN(OOR1, pos); /* this one's right */
- AHEAD(pos); /* fix the OCH_ */
- EMIT(OOR2, 0); /* offset very wrong... */
- AHEAD(THERE()); /* ...so fix it */
- ASTERN(O_CH, THERETHERE());
- break;
- case '{':
- count = p_count(p);
- if (EAT(',')) {
- if (isdigit((uch)PEEK())) {
- count2 = p_count(p);
- REQUIRE(count <= count2, REG_BADBR);
- } else /* single number with comma */
- count2 = INFINITY;
- } else /* just a single number */
- count2 = count;
- repeat(p, pos, count, count2);
- if (!EAT('}')) { /* error heuristics */
- while (MORE() && PEEK() != '}')
- NEXT();
- REQUIRE(MORE(), REG_EBRACE);
- SETERROR(REG_BADBR);
- }
- break;
- }
-
- if (!MORE())
- return;
- c = PEEK();
- if (!( c == '*' || c == '+' || c == '?' ||
- (c == '{' && MORE2() && isdigit((uch)PEEK2())) ) )
- return;
- SETERROR(REG_BADRPT);
-}
-
-/*
- - p_str - string (no metacharacters) "parser"
- */
-static void
-p_str(struct parse *p)
-{
- REQUIRE(MORE(), REG_EMPTY);
- while (MORE())
- ordinary(p, GETNEXT());
-}
-
-/*
- - p_bre - BRE parser top level, anchoring and concatenation
- * Giving end1 as OUT essentially eliminates the end1/end2 check.
- *
- * This implementation is a bit of a kludge, in that a trailing $ is first
- * taken as an ordinary character and then revised to be an anchor. The
- * only undesirable side effect is that '$' gets included as a character
- * category in such cases. This is fairly harmless; not worth fixing.
- * The amount of lookahead needed to avoid this kludge is excessive.
- */
-static void
-p_bre(struct parse *p,
- int end1, /* first terminating character */
- int end2) /* second terminating character */
-{
- sopno start = HERE();
- int first = 1; /* first subexpression? */
- int wasdollar = 0;
-
- if (EAT('^')) {
- EMIT(OBOL, 0);
- p->g->iflags |= USEBOL;
- p->g->nbol++;
- }
- while (MORE() && !SEETWO(end1, end2)) {
- wasdollar = p_simp_re(p, first);
- first = 0;
- }
- if (wasdollar) { /* oops, that was a trailing anchor */
- DROP(1);
- EMIT(OEOL, 0);
- p->g->iflags |= USEEOL;
- p->g->neol++;
- }
-
- REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */
-}
-
-/*
- - p_simp_re - parse a simple RE, an atom possibly followed by a repetition
- */
-static int /* was the simple RE an unbackslashed $? */
-p_simp_re(struct parse *p,
- int starordinary) /* is a leading * an ordinary character? */
-{
- int c;
- int count;
- int count2;
- sopno pos;
- int i;
- sopno subno;
-# define BACKSL (1<<CHAR_BIT)
-
- pos = HERE(); /* repetition op, if any, covers from here */
-
- assert(MORE()); /* caller should have ensured this */
- c = GETNEXT();
- if (c == '\\') {
- REQUIRE(MORE(), REG_EESCAPE);
- c = BACKSL | GETNEXT();
- }
- switch (c) {
- case '.':
- if (p->g->cflags&REG_NEWLINE)
- nonnewline(p);
- else
- EMIT(OANY, 0);
- break;
- case '[':
- p_bracket(p);
- break;
- case BACKSL|'{':
- SETERROR(REG_BADRPT);
- break;
- case BACKSL|'(':
- p->g->nsub++;
- subno = p->g->nsub;
- if (subno < NPAREN)
- p->pbegin[subno] = HERE();
- EMIT(OLPAREN, subno);
- /* the MORE here is an error heuristic */
- if (MORE() && !SEETWO('\\', ')'))
- p_bre(p, '\\', ')');
- if (subno < NPAREN) {
- p->pend[subno] = HERE();
- assert(p->pend[subno] != 0);
- }
- EMIT(ORPAREN, subno);
- REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
- break;
- case BACKSL|')': /* should not get here -- must be user */
- case BACKSL|'}':
- SETERROR(REG_EPAREN);
- break;
- case BACKSL|'1':
- case BACKSL|'2':
- case BACKSL|'3':
- case BACKSL|'4':
- case BACKSL|'5':
- case BACKSL|'6':
- case BACKSL|'7':
- case BACKSL|'8':
- case BACKSL|'9':
- i = (c&~BACKSL) - '0';
- assert(i < NPAREN);
- if (p->pend[i] != 0) {
- assert(i <= p->g->nsub);
- EMIT(OBACK_, i);
- assert(p->pbegin[i] != 0);
- assert(OP(p->strip[p->pbegin[i]]) == OLPAREN);
- assert(OP(p->strip[p->pend[i]]) == ORPAREN);
- (void) dupl(p, p->pbegin[i]+1, p->pend[i]);
- EMIT(O_BACK, i);
- } else
- SETERROR(REG_ESUBREG);
- p->g->backrefs = 1;
- break;
- case '*':
- REQUIRE(starordinary, REG_BADRPT);
- /* FALLTHROUGH */
- default:
- ordinary(p, (char)c);
- break;
- }
-
- if (EAT('*')) { /* implemented as +? */
- /* this case does not require the (y|) trick, noKLUDGE */
- INSERT(OPLUS_, pos);
- ASTERN(O_PLUS, pos);
- INSERT(OQUEST_, pos);
- ASTERN(O_QUEST, pos);
- } else if (EATTWO('\\', '{')) {
- count = p_count(p);
- if (EAT(',')) {
- if (MORE() && isdigit((uch)PEEK())) {
- count2 = p_count(p);
- REQUIRE(count <= count2, REG_BADBR);
- } else /* single number with comma */
- count2 = INFINITY;
- } else /* just a single number */
- count2 = count;
- repeat(p, pos, count, count2);
- if (!EATTWO('\\', '}')) { /* error heuristics */
- while (MORE() && !SEETWO('\\', '}'))
- NEXT();
- REQUIRE(MORE(), REG_EBRACE);
- SETERROR(REG_BADBR);
- }
- } else if (c == '$') /* $ (but not \$) ends it */
- return(1);
-
- return(0);
-}
-
-/*
- - p_count - parse a repetition count
- */
-static int /* the value */
-p_count(struct parse *p)
-{
- int count = 0;
- int ndigits = 0;
-
- while (MORE() && isdigit((uch)PEEK()) && count <= DUPMAX) {
- count = count*10 + (GETNEXT() - '0');
- ndigits++;
- }
-
- REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
- return(count);
-}
-
-/*
- - p_bracket - parse a bracketed character list
- *
- * Note a significant property of this code: if the allocset() did SETERROR,
- * no set operations are done.
- */
-static void
-p_bracket(struct parse *p)
-{
- cset *cs;
- int invert = 0;
-
- /* Dept of Truly Sickening Special-Case Kludges */
- if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) {
- EMIT(OBOW, 0);
- NEXTn(6);
- return;
- }
- if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) {
- EMIT(OEOW, 0);
- NEXTn(6);
- return;
- }
-
- if ((cs = allocset(p)) == NULL) {
- /* allocset did set error status in p */
- return;
- }
-
- if (EAT('^'))
- invert++; /* make note to invert set at end */
- if (EAT(']'))
- CHadd(cs, ']');
- else if (EAT('-'))
- CHadd(cs, '-');
- while (MORE() && PEEK() != ']' && !SEETWO('-', ']'))
- p_b_term(p, cs);
- if (EAT('-'))
- CHadd(cs, '-');
- MUSTEAT(']', REG_EBRACK);
-
- if (p->error != 0) { /* don't mess things up further */
- freeset(p, cs);
- return;
- }
-
- if (p->g->cflags&REG_ICASE) {
- int i;
- int ci;
-
- for (i = p->g->csetsize - 1; i >= 0; i--)
- if (CHIN(cs, i) && isalpha(i)) {
- ci = othercase(i);
- if (ci != i)
- CHadd(cs, ci);
- }
- if (cs->multis != NULL)
- mccase(p, cs);
- }
- if (invert) {
- int i;
-
- for (i = p->g->csetsize - 1; i >= 0; i--)
- if (CHIN(cs, i))
- CHsub(cs, i);
- else
- CHadd(cs, i);
- if (p->g->cflags&REG_NEWLINE)
- CHsub(cs, '\n');
- if (cs->multis != NULL)
- mcinvert(p, cs);
- }
-
- assert(cs->multis == NULL); /* xxx */
-
- if (nch(p, cs) == 1) { /* optimize singleton sets */
- ordinary(p, firstch(p, cs));
- freeset(p, cs);
- } else
- EMIT(OANYOF, freezeset(p, cs));
-}
-
-/*
- - p_b_term - parse one term of a bracketed character list
- */
-static void
-p_b_term(struct parse *p, cset *cs)
-{
- char c;
- char start, finish;
- int i;
-
- /* classify what we've got */
- switch ((MORE()) ? PEEK() : '\0') {
- case '[':
- c = (MORE2()) ? PEEK2() : '\0';
- break;
- case '-':
- SETERROR(REG_ERANGE);
- return; /* NOTE RETURN */
- break;
- default:
- c = '\0';
- break;
- }
-
- switch (c) {
- case ':': /* character class */
- NEXT2();
- REQUIRE(MORE(), REG_EBRACK);
- c = PEEK();
- REQUIRE(c != '-' && c != ']', REG_ECTYPE);
- p_b_cclass(p, cs);
- REQUIRE(MORE(), REG_EBRACK);
- REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
- break;
- case '=': /* equivalence class */
- NEXT2();
- REQUIRE(MORE(), REG_EBRACK);
- c = PEEK();
- REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
- p_b_eclass(p, cs);
- REQUIRE(MORE(), REG_EBRACK);
- REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
- break;
- default: /* symbol, ordinary character, or range */
-/* xxx revision needed for multichar stuff */
- start = p_b_symbol(p);
- if (SEE('-') && MORE2() && PEEK2() != ']') {
- /* range */
- NEXT();
- if (EAT('-'))
- finish = '-';
- else
- finish = p_b_symbol(p);
- } else
- finish = start;
-/* xxx what about signed chars here... */
- REQUIRE(start <= finish, REG_ERANGE);
- for (i = start; i <= finish; i++)
- CHadd(cs, i);
- break;
- }
-}
-
-/*
- - p_b_cclass - parse a character-class name and deal with it
- */
-static void
-p_b_cclass(struct parse *p, cset *cs)
-{
- char *sp = p->next;
- struct cclass *cp;
- size_t len;
- const char *u;
- char c;
-
- while (MORE() && isalpha((uch)PEEK()))
- NEXT();
- len = p->next - sp;
- for (cp = cclasses; cp->name != NULL; cp++)
- if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
- break;
- if (cp->name == NULL) {
- /* oops, didn't find it */
- SETERROR(REG_ECTYPE);
- return;
- }
-
- u = cp->chars;
- while ((c = *u++) != '\0')
- CHadd(cs, c);
- for (u = cp->multis; *u != '\0'; u += strlen(u) + 1)
- MCadd(p, cs, u);
-}
-
-/*
- - p_b_eclass - parse an equivalence-class name and deal with it
- *
- * This implementation is incomplete. xxx
- */
-static void
-p_b_eclass(struct parse *p, cset *cs)
-{
- char c;
-
- c = p_b_coll_elem(p, '=');
- CHadd(cs, c);
-}
-
-/*
- - p_b_symbol - parse a character or [..]ed multicharacter collating symbol
- */
-static char /* value of symbol */
-p_b_symbol(struct parse *p)
-{
- char value;
-
- REQUIRE(MORE(), REG_EBRACK);
- if (!EATTWO('[', '.'))
- return(GETNEXT());
-
- /* collating symbol */
- value = p_b_coll_elem(p, '.');
- REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
- return(value);
-}
-
-/*
- - p_b_coll_elem - parse a collating-element name and look it up
- */
-static char /* value of collating element */
-p_b_coll_elem(struct parse *p,
- int endc) /* name ended by endc,']' */
-{
- char *sp = p->next;
- struct cname *cp;
- size_t len;
-
- while (MORE() && !SEETWO(endc, ']'))
- NEXT();
- if (!MORE()) {
- SETERROR(REG_EBRACK);
- return(0);
- }
- len = p->next - sp;
- for (cp = cnames; cp->name != NULL; cp++)
- if (strncmp(cp->name, sp, len) == 0 && strlen(cp->name) == len)
- return(cp->code); /* known name */
- if (len == 1)
- return(*sp); /* single character */
- SETERROR(REG_ECOLLATE); /* neither */
- return(0);
-}
-
-/*
- - othercase - return the case counterpart of an alphabetic
- */
-static char /* if no counterpart, return ch */
-othercase(int ch)
-{
- ch = (uch)ch;
- assert(isalpha(ch));
- if (isupper(ch))
- return ((uch)tolower(ch));
- else if (islower(ch))
- return ((uch)toupper(ch));
- else /* peculiar, but could happen */
- return(ch);
-}
-
-/*
- - bothcases - emit a dualcase version of a two-case character
- *
- * Boy, is this implementation ever a kludge...
- */
-static void
-bothcases(struct parse *p, int ch)
-{
- char *oldnext = p->next;
- char *oldend = p->end;
- char bracket[3];
-
- ch = (uch)ch;
- assert(othercase(ch) != ch); /* p_bracket() would recurse */
- p->next = bracket;
- p->end = bracket+2;
- bracket[0] = ch;
- bracket[1] = ']';
- bracket[2] = '\0';
- p_bracket(p);
- assert(p->next == bracket+2);
- p->next = oldnext;
- p->end = oldend;
-}
-
-/*
- - ordinary - emit an ordinary character
- */
-static void
-ordinary(struct parse *p, int ch)
-{
- cat_t *cap = p->g->categories;
-
- if ((p->g->cflags&REG_ICASE) && isalpha((uch)ch) && othercase(ch) != ch)
- bothcases(p, ch);
- else {
- EMIT(OCHAR, (uch)ch);
- if (cap[ch] == 0)
- cap[ch] = p->g->ncategories++;
- }
-}
-
-/*
- - nonnewline - emit REG_NEWLINE version of OANY
- *
- * Boy, is this implementation ever a kludge...
- */
-static void
-nonnewline(struct parse *p)
-{
- char *oldnext = p->next;
- char *oldend = p->end;
- char bracket[4];
-
- p->next = bracket;
- p->end = bracket+3;
- bracket[0] = '^';
- bracket[1] = '\n';
- bracket[2] = ']';
- bracket[3] = '\0';
- p_bracket(p);
- assert(p->next == bracket+3);
- p->next = oldnext;
- p->end = oldend;
-}
-
-/*
- - repeat - generate code for a bounded repetition, recursively if needed
- */
-static void
-repeat(struct parse *p,
- sopno start, /* operand from here to end of strip */
- int from, /* repeated from this number */
- int to) /* to this number of times (maybe INFINITY) */
-{
- sopno finish = HERE();
-# define N 2
-# define INF 3
-# define REP(f, t) ((f)*8 + (t))
-# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)
- sopno copy;
-
- if (p->error != 0) /* head off possible runaway recursion */
- return;
-
- assert(from <= to);
-
- switch (REP(MAP(from), MAP(to))) {
- case REP(0, 0): /* must be user doing this */
- DROP(finish-start); /* drop the operand */
- break;
- case REP(0, 1): /* as x{1,1}? */
- case REP(0, N): /* as x{1,n}? */
- case REP(0, INF): /* as x{1,}? */
- /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
- INSERT(OCH_, start); /* offset is wrong... */
- repeat(p, start+1, 1, to);
- ASTERN(OOR1, start);
- AHEAD(start); /* ... fix it */
- EMIT(OOR2, 0);
- AHEAD(THERE());
- ASTERN(O_CH, THERETHERE());
- break;
- case REP(1, 1): /* trivial case */
- /* done */
- break;
- case REP(1, N): /* as x?x{1,n-1} */
- /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
- INSERT(OCH_, start);
- ASTERN(OOR1, start);
- AHEAD(start);
- EMIT(OOR2, 0); /* offset very wrong... */
- AHEAD(THERE()); /* ...so fix it */
- ASTERN(O_CH, THERETHERE());
- copy = dupl(p, start+1, finish+1);
- assert(copy == finish+4);
- repeat(p, copy, 1, to-1);
- break;
- case REP(1, INF): /* as x+ */
- INSERT(OPLUS_, start);
- ASTERN(O_PLUS, start);
- break;
- case REP(N, N): /* as xx{m-1,n-1} */
- copy = dupl(p, start, finish);
- repeat(p, copy, from-1, to-1);
- break;
- case REP(N, INF): /* as xx{n-1,INF} */
- copy = dupl(p, start, finish);
- repeat(p, copy, from-1, to);
- break;
- default: /* "can't happen" */
- SETERROR(REG_ASSERT); /* just in case */
- break;
- }
-}
-
-/*
- - seterr - set an error condition
- */
-static int /* useless but makes type checking happy */
-seterr(struct parse *p, int e)
-{
- if (p->error == 0) /* keep earliest error condition */
- p->error = e;
- p->next = nuls; /* try to bring things to a halt */
- p->end = nuls;
- return(0); /* make the return value well-defined */
-}
-
-/*
- - allocset - allocate a set of characters for []
- */
-static cset *
-allocset(struct parse *p)
-{
- int no = p->g->ncsets++;
- size_t nc;
- size_t nbytes;
- cset *cs;
- size_t css = (size_t)p->g->csetsize;
- int i;
-
- if (no >= p->ncsalloc) { /* need another column of space */
- void *ptr;
-
- p->ncsalloc += CHAR_BIT;
- nc = p->ncsalloc;
- if (nc > SIZE_MAX / sizeof(cset))
- goto nomem;
- assert(nc % CHAR_BIT == 0);
- nbytes = nc / CHAR_BIT * css;
-
- ptr = (cset *)realloc((char *)p->g->sets, nc * sizeof(cset));
- if (ptr == NULL)
- goto nomem;
- p->g->sets = ptr;
-
- ptr = (uch *)realloc((char *)p->g->setbits, nbytes);
- if (ptr == NULL)
- goto nomem;
- p->g->setbits = ptr;
-
- for (i = 0; i < no; i++)
- p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT);
-
- (void) memset((char *)p->g->setbits + (nbytes - css), 0, css);
- }
- /* XXX should not happen */
- if (p->g->sets == NULL || p->g->setbits == NULL)
- goto nomem;
-
- cs = &p->g->sets[no];
- cs->ptr = p->g->setbits + css*((no)/CHAR_BIT);
- cs->mask = 1 << ((no) % CHAR_BIT);
- cs->hash = 0;
- cs->smultis = 0;
- cs->multis = NULL;
-
- return(cs);
-nomem:
- free(p->g->sets);
- p->g->sets = NULL;
- free(p->g->setbits);
- p->g->setbits = NULL;
-
- SETERROR(REG_ESPACE);
- /* caller's responsibility not to do set ops */
- return(NULL);
-}
-
-/*
- - freeset - free a now-unused set
- */
-static void
-freeset(struct parse *p, cset *cs)
-{
- size_t i;
- cset *top = &p->g->sets[p->g->ncsets];
- size_t css = (size_t)p->g->csetsize;
-
- for (i = 0; i < css; i++)
- CHsub(cs, i);
- if (cs == top-1) /* recover only the easy case */
- p->g->ncsets--;
-}
-
-/*
- - freezeset - final processing on a set of characters
- *
- * The main task here is merging identical sets. This is usually a waste
- * of time (although the hash code minimizes the overhead), but can win
- * big if REG_ICASE is being used. REG_ICASE, by the way, is why the hash
- * is done using addition rather than xor -- all ASCII [aA] sets xor to
- * the same value!
- */
-static int /* set number */
-freezeset(struct parse *p, cset *cs)
-{
- uch h = cs->hash;
- size_t i;
- cset *top = &p->g->sets[p->g->ncsets];
- cset *cs2;
- size_t css = (size_t)p->g->csetsize;
-
- /* look for an earlier one which is the same */
- for (cs2 = &p->g->sets[0]; cs2 < top; cs2++)
- if (cs2->hash == h && cs2 != cs) {
- /* maybe */
- for (i = 0; i < css; i++)
- if (!!CHIN(cs2, i) != !!CHIN(cs, i))
- break; /* no */
- if (i == css)
- break; /* yes */
- }
-
- if (cs2 < top) { /* found one */
- freeset(p, cs);
- cs = cs2;
- }
-
- return((int)(cs - p->g->sets));
-}
-
-/*
- - firstch - return first character in a set (which must have at least one)
- */
-static int /* character; there is no "none" value */
-firstch(struct parse *p, cset *cs)
-{
- size_t i;
- size_t css = (size_t)p->g->csetsize;
-
- for (i = 0; i < css; i++)
- if (CHIN(cs, i))
- return((char)i);
- assert(never);
- return(0); /* arbitrary */
-}
-
-/*
- - nch - number of characters in a set
- */
-static int
-nch(struct parse *p, cset *cs)
-{
- size_t i;
- size_t css = (size_t)p->g->csetsize;
- int n = 0;
-
- for (i = 0; i < css; i++)
- if (CHIN(cs, i))
- n++;
- return(n);
-}
-
-/*
- - mcadd - add a collating element to a cset
- */
-static void
-mcadd( struct parse *p, cset *cs, const char *cp)
-{
- size_t oldend = cs->smultis;
- void *np;
-
- cs->smultis += strlen(cp) + 1;
- np = realloc(cs->multis, cs->smultis);
- if (np == NULL) {
- if (cs->multis)
- free(cs->multis);
- cs->multis = NULL;
- SETERROR(REG_ESPACE);
- return;
- }
- cs->multis = np;
-
- llvm_strlcpy(cs->multis + oldend - 1, cp, cs->smultis - oldend + 1);
-}
-
-/*
- - mcinvert - invert the list of collating elements in a cset
- *
- * This would have to know the set of possibilities. Implementation
- * is deferred.
- */
-/* ARGSUSED */
-static void
-mcinvert(struct parse *p, cset *cs)
-{
- assert(cs->multis == NULL); /* xxx */
-}
-
-/*
- - mccase - add case counterparts of the list of collating elements in a cset
- *
- * This would have to know the set of possibilities. Implementation
- * is deferred.
- */
-/* ARGSUSED */
-static void
-mccase(struct parse *p, cset *cs)
-{
- assert(cs->multis == NULL); /* xxx */
-}
-
-/*
- - isinsets - is this character in any sets?
- */
-static int /* predicate */
-isinsets(struct re_guts *g, int c)
-{
- uch *col;
- int i;
- int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
- unsigned uc = (uch)c;
-
- for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
- if (col[uc] != 0)
- return(1);
- return(0);
-}
-
-/*
- - samesets - are these two characters in exactly the same sets?
- */
-static int /* predicate */
-samesets(struct re_guts *g, int c1, int c2)
-{
- uch *col;
- int i;
- int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;
- unsigned uc1 = (uch)c1;
- unsigned uc2 = (uch)c2;
-
- for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)
- if (col[uc1] != col[uc2])
- return(0);
- return(1);
-}
-
-/*
- - categorize - sort out character categories
- */
-static void
-categorize(struct parse *p, struct re_guts *g)
-{
- cat_t *cats = g->categories;
- int c;
- int c2;
- cat_t cat;
-
- /* avoid making error situations worse */
- if (p->error != 0)
- return;
-
- for (c = CHAR_MIN; c <= CHAR_MAX; c++)
- if (cats[c] == 0 && isinsets(g, c)) {
- cat = g->ncategories++;
- cats[c] = cat;
- for (c2 = c+1; c2 <= CHAR_MAX; c2++)
- if (cats[c2] == 0 && samesets(g, c, c2))
- cats[c2] = cat;
- }
-}
-
-/*
- - dupl - emit a duplicate of a bunch of sops
- */
-static sopno /* start of duplicate */
-dupl(struct parse *p,
- sopno start, /* from here */
- sopno finish) /* to this less one */
-{
- sopno ret = HERE();
- sopno len = finish - start;
-
- assert(finish >= start);
- if (len == 0)
- return(ret);
- enlarge(p, p->ssize + len); /* this many unexpected additions */
- assert(p->ssize >= p->slen + len);
- (void) memmove((char *)(p->strip + p->slen),
- (char *)(p->strip + start), (size_t)len*sizeof(sop));
- p->slen += len;
- return(ret);
-}
-
-/*
- - doemit - emit a strip operator
- *
- * It might seem better to implement this as a macro with a function as
- * hard-case backup, but it's just too big and messy unless there are
- * some changes to the data structures. Maybe later.
- */
-static void
-doemit(struct parse *p, sop op, size_t opnd)
-{
- /* avoid making error situations worse */
- if (p->error != 0)
- return;
-
- /* deal with oversize operands ("can't happen", more or less) */
- assert(opnd < 1<<OPSHIFT);
-
- /* deal with undersized strip */
- if (p->slen >= p->ssize)
- enlarge(p, (p->ssize+1) / 2 * 3); /* +50% */
- assert(p->slen < p->ssize);
-
- /* finally, it's all reduced to the easy case */
- p->strip[p->slen++] = SOP(op, opnd);
-}
-
-/*
- - doinsert - insert a sop into the strip
- */
-static void
-doinsert(struct parse *p, sop op, size_t opnd, sopno pos)
-{
- sopno sn;
- sop s;
- int i;
-
- /* avoid making error situations worse */
- if (p->error != 0)
- return;
-
- sn = HERE();
- EMIT(op, opnd); /* do checks, ensure space */
- assert(HERE() == sn+1);
- s = p->strip[sn];
-
- /* adjust paren pointers */
- assert(pos > 0);
- for (i = 1; i < NPAREN; i++) {
- if (p->pbegin[i] >= pos) {
- p->pbegin[i]++;
- }
- if (p->pend[i] >= pos) {
- p->pend[i]++;
- }
- }
-
- memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos],
- (HERE()-pos-1)*sizeof(sop));
- p->strip[pos] = s;
-}
-
-/*
- - dofwd - complete a forward reference
- */
-static void
-dofwd(struct parse *p, sopno pos, sop value)
-{
- /* avoid making error situations worse */
- if (p->error != 0)
- return;
-
- assert(value < 1<<OPSHIFT);
- p->strip[pos] = OP(p->strip[pos]) | value;
-}
-
-/*
- - enlarge - enlarge the strip
- */
-static void
-enlarge(struct parse *p, sopno size)
-{
- sop *sp;
-
- if (p->ssize >= size)
- return;
-
- if ((uintptr_t)size > SIZE_MAX / sizeof(sop)) {
- SETERROR(REG_ESPACE);
- return;
- }
-
- sp = (sop *)realloc(p->strip, size*sizeof(sop));
- if (sp == NULL) {
- SETERROR(REG_ESPACE);
- return;
- }
- p->strip = sp;
- p->ssize = size;
-}
-
-/*
- - stripsnug - compact the strip
- */
-static void
-stripsnug(struct parse *p, struct re_guts *g)
-{
- g->nstates = p->slen;
- if ((uintptr_t)p->slen > SIZE_MAX / sizeof(sop)) {
- g->strip = p->strip;
- SETERROR(REG_ESPACE);
- return;
- }
-
- g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));
- if (g->strip == NULL) {
- SETERROR(REG_ESPACE);
- g->strip = p->strip;
- }
-}
-
-/*
- - findmust - fill in must and mlen with longest mandatory literal string
- *
- * This algorithm could do fancy things like analyzing the operands of |
- * for common subsequences. Someday. This code is simple and finds most
- * of the interesting cases.
- *
- * Note that must and mlen got initialized during setup.
- */
-static void
-findmust(struct parse *p, struct re_guts *g)
-{
- sop *scan;
- sop *start = 0; /* start initialized in the default case, after that */
- sop *newstart = 0; /* newstart was initialized in the OCHAR case */
- sopno newlen;
- sop s;
- char *cp;
- sopno i;
-
- /* avoid making error situations worse */
- if (p->error != 0)
- return;
-
- /* find the longest OCHAR sequence in strip */
- newlen = 0;
- scan = g->strip + 1;
- do {
- s = *scan++;
- switch (OP(s)) {
- case OCHAR: /* sequence member */
- if (newlen == 0) /* new sequence */
- newstart = scan - 1;
- newlen++;
- break;
- case OPLUS_: /* things that don't break one */
- case OLPAREN:
- case ORPAREN:
- break;
- case OQUEST_: /* things that must be skipped */
- case OCH_:
- scan--;
- do {
- scan += OPND(s);
- s = *scan;
- /* assert() interferes w debug printouts */
- if (OP(s) != O_QUEST && OP(s) != O_CH &&
- OP(s) != OOR2) {
- g->iflags |= REGEX_BAD;
- return;
- }
- } while (OP(s) != O_QUEST && OP(s) != O_CH);
- /* fallthrough */
- default: /* things that break a sequence */
- if (newlen > g->mlen) { /* ends one */
- start = newstart;
- g->mlen = newlen;
- }
- newlen = 0;
- break;
- }
- } while (OP(s) != OEND);
-
- if (g->mlen == 0) /* there isn't one */
- return;
-
- /* turn it into a character string */
- g->must = malloc((size_t)g->mlen + 1);
- if (g->must == NULL) { /* argh; just forget it */
- g->mlen = 0;
- return;
- }
- cp = g->must;
- scan = start;
- for (i = g->mlen; i > 0; i--) {
- while (OP(s = *scan++) != OCHAR)
- continue;
- assert(cp < g->must + g->mlen);
- *cp++ = (char)OPND(s);
- }
- assert(cp == g->must + g->mlen);
- *cp++ = '\0'; /* just on general principles */
-}
-
-/*
- - pluscount - count + nesting
- */
-static sopno /* nesting depth */
-pluscount(struct parse *p, struct re_guts *g)
-{
- sop *scan;
- sop s;
- sopno plusnest = 0;
- sopno maxnest = 0;
-
- if (p->error != 0)
- return(0); /* there may not be an OEND */
-
- scan = g->strip + 1;
- do {
- s = *scan++;
- switch (OP(s)) {
- case OPLUS_:
- plusnest++;
- break;
- case O_PLUS:
- if (plusnest > maxnest)
- maxnest = plusnest;
- plusnest--;
- break;
- }
- } while (OP(s) != OEND);
- if (plusnest != 0)
- g->iflags |= REGEX_BAD;
- return(maxnest);
-}
diff --git a/gnu/llvm/lib/Support/regengine.inc b/gnu/llvm/lib/Support/regengine.inc
deleted file mode 100644
index 41787aff124..00000000000
--- a/gnu/llvm/lib/Support/regengine.inc
+++ /dev/null
@@ -1,1034 +0,0 @@
-/*-
- * This code is derived from OpenBSD's libc/regex, original license follows:
- *
- * Copyright (c) 1992, 1993, 1994 Henry Spencer.
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Henry Spencer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)engine.c 8.5 (Berkeley) 3/20/94
- */
-
-/*
- * The matching engine and friends. This file is #included by regexec.c
- * after suitable #defines of a variety of macros used herein, so that
- * different state representations can be used without duplicating masses
- * of code.
- */
-
-#ifdef SNAMES
-#define matcher smatcher
-#define fast sfast
-#define slow sslow
-#define dissect sdissect
-#define backref sbackref
-#define step sstep
-#define print sprint
-#define at sat
-#define match smat
-#define nope snope
-#endif
-#ifdef LNAMES
-#define matcher lmatcher
-#define fast lfast
-#define slow lslow
-#define dissect ldissect
-#define backref lbackref
-#define step lstep
-#define print lprint
-#define at lat
-#define match lmat
-#define nope lnope
-#endif
-
-/* another structure passed up and down to avoid zillions of parameters */
-struct match {
- struct re_guts *g;
- int eflags;
- llvm_regmatch_t *pmatch; /* [nsub+1] (0 element unused) */
- const char *offp; /* offsets work from here */
- const char *beginp; /* start of string -- virtual NUL precedes */
- const char *endp; /* end of string -- virtual NUL here */
- const char *coldp; /* can be no match starting before here */
- const char **lastpos; /* [nplus+1] */
- STATEVARS;
- states st; /* current states */
- states fresh; /* states for a fresh start */
- states tmp; /* temporary */
- states empty; /* empty set of states */
-};
-
-static int matcher(struct re_guts *, const char *, size_t,
- llvm_regmatch_t[], int);
-static const char *dissect(struct match *, const char *, const char *, sopno,
- sopno);
-static const char *backref(struct match *, const char *, const char *, sopno,
- sopno, sopno, int);
-static const char *fast(struct match *, const char *, const char *, sopno, sopno);
-static const char *slow(struct match *, const char *, const char *, sopno, sopno);
-static states step(struct re_guts *, sopno, sopno, states, int, states);
-#define MAX_RECURSION 100
-#define BOL (OUT+1)
-#define EOL (BOL+1)
-#define BOLEOL (BOL+2)
-#define NOTHING (BOL+3)
-#define BOW (BOL+4)
-#define EOW (BOL+5)
-#define CODEMAX (BOL+5) /* highest code used */
-#define NONCHAR(c) ((c) > CHAR_MAX)
-#define NNONCHAR (CODEMAX-CHAR_MAX)
-#ifdef REDEBUG
-static void print(struct match *, char *, states, int, FILE *);
-#endif
-#ifdef REDEBUG
-static void at(struct match *, char *, char *, char *, sopno, sopno);
-#endif
-#ifdef REDEBUG
-static char *pchar(int);
-#endif
-
-#ifdef REDEBUG
-#define SP(t, s, c) print(m, t, s, c, stdout)
-#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2)
-#define NOTE(str) { if (m->eflags&REG_TRACE) (void)printf("=%s\n", (str)); }
-static int nope = 0;
-#else
-#define SP(t, s, c) /* nothing */
-#define AT(t, p1, p2, s1, s2) /* nothing */
-#define NOTE(s) /* nothing */
-#endif
-
-/*
- - matcher - the actual matching engine
- */
-static int /* 0 success, REG_NOMATCH failure */
-matcher(struct re_guts *g, const char *string, size_t nmatch,
- llvm_regmatch_t pmatch[],
- int eflags)
-{
- const char *endp;
- size_t i;
- struct match mv;
- struct match *m = &mv;
- const char *dp;
- const sopno gf = g->firststate+1; /* +1 for OEND */
- const sopno gl = g->laststate;
- const char *start;
- const char *stop;
-
- /* simplify the situation where possible */
- if (g->cflags&REG_NOSUB)
- nmatch = 0;
- if (eflags&REG_STARTEND) {
- start = string + pmatch[0].rm_so;
- stop = string + pmatch[0].rm_eo;
- } else {
- start = string;
- stop = start + strlen(start);
- }
- if (stop < start)
- return(REG_INVARG);
-
- /* prescreening; this does wonders for this rather slow code */
- if (g->must != NULL) {
- for (dp = start; dp < stop; dp++)
- if (*dp == g->must[0] && stop - dp >= g->mlen &&
- memcmp(dp, g->must, (size_t)g->mlen) == 0)
- break;
- if (dp == stop) /* we didn't find g->must */
- return(REG_NOMATCH);
- }
-
- /* match struct setup */
- m->g = g;
- m->eflags = eflags;
- m->pmatch = NULL;
- m->lastpos = NULL;
- m->offp = string;
- m->beginp = start;
- m->endp = stop;
- STATESETUP(m, 4);
- SETUP(m->st);
- SETUP(m->fresh);
- SETUP(m->tmp);
- SETUP(m->empty);
- CLEAR(m->empty);
-
- /* this loop does only one repetition except for backrefs */
- for (;;) {
- endp = fast(m, start, stop, gf, gl);
- if (endp == NULL) { /* a miss */
- free(m->pmatch);
- free((void*)m->lastpos);
- STATETEARDOWN(m);
- return(REG_NOMATCH);
- }
- if (nmatch == 0 && !g->backrefs)
- break; /* no further info needed */
-
- /* where? */
- assert(m->coldp != NULL);
- for (;;) {
- NOTE("finding start");
- endp = slow(m, m->coldp, stop, gf, gl);
- if (endp != NULL)
- break;
- assert(m->coldp < m->endp);
- m->coldp++;
- }
- if (nmatch == 1 && !g->backrefs)
- break; /* no further info needed */
-
- /* oh my, they want the subexpressions... */
- if (m->pmatch == NULL)
- m->pmatch = (llvm_regmatch_t *)malloc((m->g->nsub + 1) *
- sizeof(llvm_regmatch_t));
- if (m->pmatch == NULL) {
- STATETEARDOWN(m);
- return(REG_ESPACE);
- }
- for (i = 1; i <= m->g->nsub; i++)
- m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1;
- if (!g->backrefs && !(m->eflags&REG_BACKR)) {
- NOTE("dissecting");
- dp = dissect(m, m->coldp, endp, gf, gl);
- } else {
- if (g->nplus > 0 && m->lastpos == NULL)
- m->lastpos = (const char **)malloc((g->nplus+1) *
- sizeof(char *));
- if (g->nplus > 0 && m->lastpos == NULL) {
- free(m->pmatch);
- STATETEARDOWN(m);
- return(REG_ESPACE);
- }
- NOTE("backref dissect");
- dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0);
- }
- if (dp != NULL)
- break;
-
- /* uh-oh... we couldn't find a subexpression-level match */
- assert(g->backrefs); /* must be back references doing it */
- assert(g->nplus == 0 || m->lastpos != NULL);
- for (;;) {
- if (dp != NULL || endp <= m->coldp)
- break; /* defeat */
- NOTE("backoff");
- endp = slow(m, m->coldp, endp-1, gf, gl);
- if (endp == NULL)
- break; /* defeat */
- /* try it on a shorter possibility */
-#ifndef NDEBUG
- for (i = 1; i <= m->g->nsub; i++) {
- assert(m->pmatch[i].rm_so == -1);
- assert(m->pmatch[i].rm_eo == -1);
- }
-#endif
- NOTE("backoff dissect");
- dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0);
- }
- assert(dp == NULL || dp == endp);
- if (dp != NULL) /* found a shorter one */
- break;
-
- /* despite initial appearances, there is no match here */
- NOTE("false alarm");
- if (m->coldp == stop)
- break;
- start = m->coldp + 1; /* recycle starting later */
- }
-
- /* fill in the details if requested */
- if (nmatch > 0) {
- pmatch[0].rm_so = m->coldp - m->offp;
- pmatch[0].rm_eo = endp - m->offp;
- }
- if (nmatch > 1) {
- assert(m->pmatch != NULL);
- for (i = 1; i < nmatch; i++)
- if (i <= m->g->nsub)
- pmatch[i] = m->pmatch[i];
- else {
- pmatch[i].rm_so = -1;
- pmatch[i].rm_eo = -1;
- }
- }
-
- if (m->pmatch != NULL)
- free((char *)m->pmatch);
- if (m->lastpos != NULL)
- free((char *)m->lastpos);
- STATETEARDOWN(m);
- return(0);
-}
-
-/*
- - dissect - figure out what matched what, no back references
- */
-static const char * /* == stop (success) always */
-dissect(struct match *m, const char *start, const char *stop, sopno startst,
- sopno stopst)
-{
- int i;
- sopno ss; /* start sop of current subRE */
- sopno es; /* end sop of current subRE */
- const char *sp; /* start of string matched by it */
- const char *stp; /* string matched by it cannot pass here */
- const char *rest; /* start of rest of string */
- const char *tail; /* string unmatched by rest of RE */
- sopno ssub; /* start sop of subsubRE */
- sopno esub; /* end sop of subsubRE */
- const char *ssp; /* start of string matched by subsubRE */
- const char *sep; /* end of string matched by subsubRE */
- const char *oldssp; /* previous ssp */
-
- AT("diss", start, stop, startst, stopst);
- sp = start;
- for (ss = startst; ss < stopst; ss = es) {
- /* identify end of subRE */
- es = ss;
- switch (OP(m->g->strip[es])) {
- case OPLUS_:
- case OQUEST_:
- es += OPND(m->g->strip[es]);
- break;
- case OCH_:
- while (OP(m->g->strip[es]) != O_CH)
- es += OPND(m->g->strip[es]);
- break;
- }
- es++;
-
- /* figure out what it matched */
- switch (OP(m->g->strip[ss])) {
- case OEND:
- assert(nope);
- break;
- case OCHAR:
- sp++;
- break;
- case OBOL:
- case OEOL:
- case OBOW:
- case OEOW:
- break;
- case OANY:
- case OANYOF:
- sp++;
- break;
- case OBACK_:
- case O_BACK:
- assert(nope);
- break;
- /* cases where length of match is hard to find */
- case OQUEST_:
- stp = stop;
- for (;;) {
- /* how long could this one be? */
- rest = slow(m, sp, stp, ss, es);
- assert(rest != NULL); /* it did match */
- /* could the rest match the rest? */
- tail = slow(m, rest, stop, es, stopst);
- if (tail == stop)
- break; /* yes! */
- /* no -- try a shorter match for this one */
- stp = rest - 1;
- assert(stp >= sp); /* it did work */
- }
- ssub = ss + 1;
- esub = es - 1;
- /* did innards match? */
- if (slow(m, sp, rest, ssub, esub) != NULL) {
- const char *dp = dissect(m, sp, rest, ssub, esub);
- (void)dp; /* avoid warning if assertions off */
- assert(dp == rest);
- } else /* no */
- assert(sp == rest);
- sp = rest;
- break;
- case OPLUS_:
- stp = stop;
- for (;;) {
- /* how long could this one be? */
- rest = slow(m, sp, stp, ss, es);
- assert(rest != NULL); /* it did match */
- /* could the rest match the rest? */
- tail = slow(m, rest, stop, es, stopst);
- if (tail == stop)
- break; /* yes! */
- /* no -- try a shorter match for this one */
- stp = rest - 1;
- assert(stp >= sp); /* it did work */
- }
- ssub = ss + 1;
- esub = es - 1;
- ssp = sp;
- oldssp = ssp;
- for (;;) { /* find last match of innards */
- sep = slow(m, ssp, rest, ssub, esub);
- if (sep == NULL || sep == ssp)
- break; /* failed or matched null */
- oldssp = ssp; /* on to next try */
- ssp = sep;
- }
- if (sep == NULL) {
- /* last successful match */
- sep = ssp;
- ssp = oldssp;
- }
- assert(sep == rest); /* must exhaust substring */
- assert(slow(m, ssp, sep, ssub, esub) == rest);
- {
- const char *dp = dissect(m, ssp, sep, ssub, esub);
- (void)dp; /* avoid warning if assertions off */
- assert(dp == sep);
- }
- sp = rest;
- break;
- case OCH_:
- stp = stop;
- for (;;) {
- /* how long could this one be? */
- rest = slow(m, sp, stp, ss, es);
- assert(rest != NULL); /* it did match */
- /* could the rest match the rest? */
- tail = slow(m, rest, stop, es, stopst);
- if (tail == stop)
- break; /* yes! */
- /* no -- try a shorter match for this one */
- stp = rest - 1;
- assert(stp >= sp); /* it did work */
- }
- ssub = ss + 1;
- esub = ss + OPND(m->g->strip[ss]) - 1;
- assert(OP(m->g->strip[esub]) == OOR1);
- for (;;) { /* find first matching branch */
- if (slow(m, sp, rest, ssub, esub) == rest)
- break; /* it matched all of it */
- /* that one missed, try next one */
- assert(OP(m->g->strip[esub]) == OOR1);
- esub++;
- assert(OP(m->g->strip[esub]) == OOR2);
- ssub = esub + 1;
- esub += OPND(m->g->strip[esub]);
- if (OP(m->g->strip[esub]) == OOR2)
- esub--;
- else
- assert(OP(m->g->strip[esub]) == O_CH);
- }
- {
- const char *dp = dissect(m, sp, rest, ssub, esub);
- (void)dp; /* avoid warning if assertions off */
- assert(dp == rest);
- }
- sp = rest;
- break;
- case O_PLUS:
- case O_QUEST:
- case OOR1:
- case OOR2:
- case O_CH:
- assert(nope);
- break;
- case OLPAREN:
- i = OPND(m->g->strip[ss]);
- assert(0 < i && i <= m->g->nsub);
- m->pmatch[i].rm_so = sp - m->offp;
- break;
- case ORPAREN:
- i = OPND(m->g->strip[ss]);
- assert(0 < i && i <= m->g->nsub);
- m->pmatch[i].rm_eo = sp - m->offp;
- break;
- default: /* uh oh */
- assert(nope);
- break;
- }
- }
-
- assert(sp == stop);
- return(sp);
-}
-
-/*
- - backref - figure out what matched what, figuring in back references
- */
-static const char * /* == stop (success) or NULL (failure) */
-backref(struct match *m, const char *start, const char *stop, sopno startst,
- sopno stopst, sopno lev, int rec) /* PLUS nesting level */
-{
- int i;
- sopno ss; /* start sop of current subRE */
- const char *sp; /* start of string matched by it */
- sopno ssub; /* start sop of subsubRE */
- sopno esub; /* end sop of subsubRE */
- const char *ssp; /* start of string matched by subsubRE */
- const char *dp;
- size_t len;
- int hard;
- sop s;
- llvm_regoff_t offsave;
- cset *cs;
-
- AT("back", start, stop, startst, stopst);
- sp = start;
-
- /* get as far as we can with easy stuff */
- hard = 0;
- for (ss = startst; !hard && ss < stopst; ss++)
- switch (OP(s = m->g->strip[ss])) {
- case OCHAR:
- if (sp == stop || *sp++ != (char)OPND(s))
- return(NULL);
- break;
- case OANY:
- if (sp == stop)
- return(NULL);
- sp++;
- break;
- case OANYOF:
- cs = &m->g->sets[OPND(s)];
- if (sp == stop || !CHIN(cs, *sp++))
- return(NULL);
- break;
- case OBOL:
- if ( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
- (sp < m->endp && *(sp-1) == '\n' &&
- (m->g->cflags&REG_NEWLINE)) )
- { /* yes */ }
- else
- return(NULL);
- break;
- case OEOL:
- if ( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
- (sp < m->endp && *sp == '\n' &&
- (m->g->cflags&REG_NEWLINE)) )
- { /* yes */ }
- else
- return(NULL);
- break;
- case OBOW:
- if (( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
- (sp < m->endp && *(sp-1) == '\n' &&
- (m->g->cflags&REG_NEWLINE)) ||
- (sp > m->beginp &&
- !ISWORD(*(sp-1))) ) &&
- (sp < m->endp && ISWORD(*sp)) )
- { /* yes */ }
- else
- return(NULL);
- break;
- case OEOW:
- if (( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
- (sp < m->endp && *sp == '\n' &&
- (m->g->cflags&REG_NEWLINE)) ||
- (sp < m->endp && !ISWORD(*sp)) ) &&
- (sp > m->beginp && ISWORD(*(sp-1))) )
- { /* yes */ }
- else
- return(NULL);
- break;
- case O_QUEST:
- break;
- case OOR1: /* matches null but needs to skip */
- ss++;
- s = m->g->strip[ss];
- do {
- assert(OP(s) == OOR2);
- ss += OPND(s);
- } while (OP(s = m->g->strip[ss]) != O_CH);
- /* note that the ss++ gets us past the O_CH */
- break;
- default: /* have to make a choice */
- hard = 1;
- break;
- }
- if (!hard) { /* that was it! */
- if (sp != stop)
- return(NULL);
- return(sp);
- }
- ss--; /* adjust for the for's final increment */
-
- /* the hard stuff */
- AT("hard", sp, stop, ss, stopst);
- s = m->g->strip[ss];
- switch (OP(s)) {
- case OBACK_: /* the vilest depths */
- i = OPND(s);
- assert(0 < i && i <= m->g->nsub);
- if (m->pmatch[i].rm_eo == -1)
- return(NULL);
- assert(m->pmatch[i].rm_so != -1);
- len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so;
- if (len == 0 && rec++ > MAX_RECURSION)
- return(NULL);
- assert(stop - m->beginp >= len);
- if (sp > stop - len)
- return(NULL); /* not enough left to match */
- ssp = m->offp + m->pmatch[i].rm_so;
- if (memcmp(sp, ssp, len) != 0)
- return(NULL);
- while (m->g->strip[ss] != SOP(O_BACK, i))
- ss++;
- return(backref(m, sp+len, stop, ss+1, stopst, lev, rec));
- break;
- case OQUEST_: /* to null or not */
- dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
- if (dp != NULL)
- return(dp); /* not */
- return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev, rec));
- break;
- case OPLUS_:
- assert(m->lastpos != NULL);
- assert(lev+1 <= m->g->nplus);
- m->lastpos[lev+1] = sp;
- return(backref(m, sp, stop, ss+1, stopst, lev+1, rec));
- break;
- case O_PLUS:
- if (sp == m->lastpos[lev]) /* last pass matched null */
- return(backref(m, sp, stop, ss+1, stopst, lev-1, rec));
- /* try another pass */
- m->lastpos[lev] = sp;
- dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev, rec);
- if (dp == NULL)
- return(backref(m, sp, stop, ss+1, stopst, lev-1, rec));
- else
- return(dp);
- break;
- case OCH_: /* find the right one, if any */
- ssub = ss + 1;
- esub = ss + OPND(s) - 1;
- assert(OP(m->g->strip[esub]) == OOR1);
- for (;;) { /* find first matching branch */
- dp = backref(m, sp, stop, ssub, esub, lev, rec);
- if (dp != NULL)
- return(dp);
- /* that one missed, try next one */
- if (OP(m->g->strip[esub]) == O_CH)
- return(NULL); /* there is none */
- esub++;
- assert(OP(m->g->strip[esub]) == OOR2);
- ssub = esub + 1;
- esub += OPND(m->g->strip[esub]);
- if (OP(m->g->strip[esub]) == OOR2)
- esub--;
- else
- assert(OP(m->g->strip[esub]) == O_CH);
- }
- break;
- case OLPAREN: /* must undo assignment if rest fails */
- i = OPND(s);
- assert(0 < i && i <= m->g->nsub);
- offsave = m->pmatch[i].rm_so;
- m->pmatch[i].rm_so = sp - m->offp;
- dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
- if (dp != NULL)
- return(dp);
- m->pmatch[i].rm_so = offsave;
- return(NULL);
- break;
- case ORPAREN: /* must undo assignment if rest fails */
- i = OPND(s);
- assert(0 < i && i <= m->g->nsub);
- offsave = m->pmatch[i].rm_eo;
- m->pmatch[i].rm_eo = sp - m->offp;
- dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
- if (dp != NULL)
- return(dp);
- m->pmatch[i].rm_eo = offsave;
- return(NULL);
- break;
- default: /* uh oh */
- assert(nope);
- break;
- }
-
- /* "can't happen" */
- assert(nope);
- /* NOTREACHED */
- return NULL;
-}
-
-/*
- - fast - step through the string at top speed
- */
-static const char * /* where tentative match ended, or NULL */
-fast(struct match *m, const char *start, const char *stop, sopno startst,
- sopno stopst)
-{
- states st = m->st;
- states fresh = m->fresh;
- states tmp = m->tmp;
- const char *p = start;
- int c = (start == m->beginp) ? OUT : *(start-1);
- int lastc; /* previous c */
- int flagch;
- int i;
- const char *coldp; /* last p after which no match was underway */
-
- CLEAR(st);
- SET1(st, startst);
- st = step(m->g, startst, stopst, st, NOTHING, st);
- ASSIGN(fresh, st);
- SP("start", st, *p);
- coldp = NULL;
- for (;;) {
- /* next character */
- lastc = c;
- c = (p == m->endp) ? OUT : *p;
- if (EQ(st, fresh))
- coldp = p;
-
- /* is there an EOL and/or BOL between lastc and c? */
- flagch = '\0';
- i = 0;
- if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
- (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
- flagch = BOL;
- i = m->g->nbol;
- }
- if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
- (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
- flagch = (flagch == BOL) ? BOLEOL : EOL;
- i += m->g->neol;
- }
- if (i != 0) {
- for (; i > 0; i--)
- st = step(m->g, startst, stopst, st, flagch, st);
- SP("boleol", st, c);
- }
-
- /* how about a word boundary? */
- if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
- (c != OUT && ISWORD(c)) ) {
- flagch = BOW;
- }
- if ( (lastc != OUT && ISWORD(lastc)) &&
- (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
- flagch = EOW;
- }
- if (flagch == BOW || flagch == EOW) {
- st = step(m->g, startst, stopst, st, flagch, st);
- SP("boweow", st, c);
- }
-
- /* are we done? */
- if (ISSET(st, stopst) || p == stop)
- break; /* NOTE BREAK OUT */
-
- /* no, we must deal with this character */
- ASSIGN(tmp, st);
- ASSIGN(st, fresh);
- assert(c != OUT);
- st = step(m->g, startst, stopst, tmp, c, st);
- SP("aft", st, c);
- assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
- p++;
- }
-
- assert(coldp != NULL);
- m->coldp = coldp;
- if (ISSET(st, stopst))
- return(p+1);
- else
- return(NULL);
-}
-
-/*
- - slow - step through the string more deliberately
- */
-static const char * /* where it ended */
-slow(struct match *m, const char *start, const char *stop, sopno startst,
- sopno stopst)
-{
- states st = m->st;
- states empty = m->empty;
- states tmp = m->tmp;
- const char *p = start;
- int c = (start == m->beginp) ? OUT : *(start-1);
- int lastc; /* previous c */
- int flagch;
- int i;
- const char *matchp; /* last p at which a match ended */
-
- AT("slow", start, stop, startst, stopst);
- CLEAR(st);
- SET1(st, startst);
- SP("sstart", st, *p);
- st = step(m->g, startst, stopst, st, NOTHING, st);
- matchp = NULL;
- for (;;) {
- /* next character */
- lastc = c;
- c = (p == m->endp) ? OUT : *p;
-
- /* is there an EOL and/or BOL between lastc and c? */
- flagch = '\0';
- i = 0;
- if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
- (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
- flagch = BOL;
- i = m->g->nbol;
- }
- if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
- (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
- flagch = (flagch == BOL) ? BOLEOL : EOL;
- i += m->g->neol;
- }
- if (i != 0) {
- for (; i > 0; i--)
- st = step(m->g, startst, stopst, st, flagch, st);
- SP("sboleol", st, c);
- }
-
- /* how about a word boundary? */
- if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
- (c != OUT && ISWORD(c)) ) {
- flagch = BOW;
- }
- if ( (lastc != OUT && ISWORD(lastc)) &&
- (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
- flagch = EOW;
- }
- if (flagch == BOW || flagch == EOW) {
- st = step(m->g, startst, stopst, st, flagch, st);
- SP("sboweow", st, c);
- }
-
- /* are we done? */
- if (ISSET(st, stopst))
- matchp = p;
- if (EQ(st, empty) || p == stop)
- break; /* NOTE BREAK OUT */
-
- /* no, we must deal with this character */
- ASSIGN(tmp, st);
- ASSIGN(st, empty);
- assert(c != OUT);
- st = step(m->g, startst, stopst, tmp, c, st);
- SP("saft", st, c);
- assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
- p++;
- }
-
- return(matchp);
-}
-
-
-/*
- - step - map set of states reachable before char to set reachable after
- */
-static states
-step(struct re_guts *g,
- sopno start, /* start state within strip */
- sopno stop, /* state after stop state within strip */
- states bef, /* states reachable before */
- int ch, /* character or NONCHAR code */
- states aft) /* states already known reachable after */
-{
- cset *cs;
- sop s;
- sopno pc;
- onestate here; /* note, macros know this name */
- sopno look;
- int i;
-
- for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) {
- s = g->strip[pc];
- switch (OP(s)) {
- case OEND:
- assert(pc == stop-1);
- break;
- case OCHAR:
- /* only characters can match */
- assert(!NONCHAR(ch) || ch != (char)OPND(s));
- if (ch == (char)OPND(s))
- FWD(aft, bef, 1);
- break;
- case OBOL:
- if (ch == BOL || ch == BOLEOL)
- FWD(aft, bef, 1);
- break;
- case OEOL:
- if (ch == EOL || ch == BOLEOL)
- FWD(aft, bef, 1);
- break;
- case OBOW:
- if (ch == BOW)
- FWD(aft, bef, 1);
- break;
- case OEOW:
- if (ch == EOW)
- FWD(aft, bef, 1);
- break;
- case OANY:
- if (!NONCHAR(ch))
- FWD(aft, bef, 1);
- break;
- case OANYOF:
- cs = &g->sets[OPND(s)];
- if (!NONCHAR(ch) && CHIN(cs, ch))
- FWD(aft, bef, 1);
- break;
- case OBACK_: /* ignored here */
- case O_BACK:
- FWD(aft, aft, 1);
- break;
- case OPLUS_: /* forward, this is just an empty */
- FWD(aft, aft, 1);
- break;
- case O_PLUS: /* both forward and back */
- FWD(aft, aft, 1);
- i = ISSETBACK(aft, OPND(s));
- BACK(aft, aft, OPND(s));
- if (!i && ISSETBACK(aft, OPND(s))) {
- /* oho, must reconsider loop body */
- pc -= OPND(s) + 1;
- INIT(here, pc);
- }
- break;
- case OQUEST_: /* two branches, both forward */
- FWD(aft, aft, 1);
- FWD(aft, aft, OPND(s));
- break;
- case O_QUEST: /* just an empty */
- FWD(aft, aft, 1);
- break;
- case OLPAREN: /* not significant here */
- case ORPAREN:
- FWD(aft, aft, 1);
- break;
- case OCH_: /* mark the first two branches */
- FWD(aft, aft, 1);
- assert(OP(g->strip[pc+OPND(s)]) == OOR2);
- FWD(aft, aft, OPND(s));
- break;
- case OOR1: /* done a branch, find the O_CH */
- if (ISSTATEIN(aft, here)) {
- for (look = 1;
- OP(s = g->strip[pc+look]) != O_CH;
- look += OPND(s))
- assert(OP(s) == OOR2);
- FWD(aft, aft, look);
- }
- break;
- case OOR2: /* propagate OCH_'s marking */
- FWD(aft, aft, 1);
- if (OP(g->strip[pc+OPND(s)]) != O_CH) {
- assert(OP(g->strip[pc+OPND(s)]) == OOR2);
- FWD(aft, aft, OPND(s));
- }
- break;
- case O_CH: /* just empty */
- FWD(aft, aft, 1);
- break;
- default: /* ooooops... */
- assert(nope);
- break;
- }
- }
-
- return(aft);
-}
-
-#ifdef REDEBUG
-/*
- - print - print a set of states
- */
-static void
-print(struct match *m, char *caption, states st, int ch, FILE *d)
-{
- struct re_guts *g = m->g;
- int i;
- int first = 1;
-
- if (!(m->eflags&REG_TRACE))
- return;
-
- (void)fprintf(d, "%s", caption);
- if (ch != '\0')
- (void)fprintf(d, " %s", pchar(ch));
- for (i = 0; i < g->nstates; i++)
- if (ISSET(st, i)) {
- (void)fprintf(d, "%s%d", (first) ? "\t" : ", ", i);
- first = 0;
- }
- (void)fprintf(d, "\n");
-}
-
-/*
- - at - print current situation
- */
-static void
-at(struct match *m, char *title, char *start, char *stop, sopno startst,
- sopno stopst)
-{
- if (!(m->eflags&REG_TRACE))
- return;
-
- (void)printf("%s %s-", title, pchar(*start));
- (void)printf("%s ", pchar(*stop));
- (void)printf("%ld-%ld\n", (long)startst, (long)stopst);
-}
-
-#ifndef PCHARDONE
-#define PCHARDONE /* never again */
-/*
- - pchar - make a character printable
- *
- * Is this identical to regchar() over in debug.c? Well, yes. But a
- * duplicate here avoids having a debugging-capable regexec.o tied to
- * a matching debug.o, and this is convenient. It all disappears in
- * the non-debug compilation anyway, so it doesn't matter much.
- */
-static char * /* -> representation */
-pchar(int ch)
-{
- static char pbuf[10];
-
- if (isPrint(ch) || ch == ' ')
- (void)snprintf(pbuf, sizeof pbuf, "%c", ch);
- else
- (void)snprintf(pbuf, sizeof pbuf, "\\%o", ch);
- return(pbuf);
-}
-#endif
-#endif
-
-#undef matcher
-#undef fast
-#undef slow
-#undef dissect
-#undef backref
-#undef step
-#undef print
-#undef at
-#undef match
-#undef nope
diff --git a/gnu/llvm/lib/Support/regerror.c b/gnu/llvm/lib/Support/regerror.c
deleted file mode 100644
index 1d67c9a2b03..00000000000
--- a/gnu/llvm/lib/Support/regerror.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*-
- * This code is derived from OpenBSD's libc/regex, original license follows:
- *
- * Copyright (c) 1992, 1993, 1994 Henry Spencer.
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Henry Spencer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)regerror.c 8.4 (Berkeley) 3/20/94
- */
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdlib.h>
-#include "regex_impl.h"
-
-#include "regutils.h"
-
-#ifdef _MSC_VER
-#define snprintf _snprintf
-#endif
-
-static const char *regatoi(const llvm_regex_t *, char *, int);
-
-static struct rerr {
- int code;
- const char *name;
- const char *explain;
-} rerrs[] = {
- { REG_NOMATCH, "REG_NOMATCH", "llvm_regexec() failed to match" },
- { REG_BADPAT, "REG_BADPAT", "invalid regular expression" },
- { REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element" },
- { REG_ECTYPE, "REG_ECTYPE", "invalid character class" },
- { REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)" },
- { REG_ESUBREG, "REG_ESUBREG", "invalid backreference number" },
- { REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced" },
- { REG_EPAREN, "REG_EPAREN", "parentheses not balanced" },
- { REG_EBRACE, "REG_EBRACE", "braces not balanced" },
- { REG_BADBR, "REG_BADBR", "invalid repetition count(s)" },
- { REG_ERANGE, "REG_ERANGE", "invalid character range" },
- { REG_ESPACE, "REG_ESPACE", "out of memory" },
- { REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid" },
- { REG_EMPTY, "REG_EMPTY", "empty (sub)expression" },
- { REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug" },
- { REG_INVARG, "REG_INVARG", "invalid argument to regex routine" },
- { 0, "", "*** unknown regexp error code ***" }
-};
-
-/*
- - llvm_regerror - the interface to error numbers
- = extern size_t llvm_regerror(int, const llvm_regex_t *, char *, size_t);
- */
-/* ARGSUSED */
-size_t
-llvm_regerror(int errcode, const llvm_regex_t *preg, char *errbuf, size_t errbuf_size)
-{
- struct rerr *r;
- size_t len;
- int target = errcode &~ REG_ITOA;
- const char *s;
- char convbuf[50];
-
- if (errcode == REG_ATOI)
- s = regatoi(preg, convbuf, sizeof convbuf);
- else {
- for (r = rerrs; r->code != 0; r++)
- if (r->code == target)
- break;
-
- if (errcode&REG_ITOA) {
- if (r->code != 0) {
- assert(strlen(r->name) < sizeof(convbuf));
- (void) llvm_strlcpy(convbuf, r->name, sizeof convbuf);
- } else
- (void)snprintf(convbuf, sizeof convbuf,
- "REG_0x%x", target);
- s = convbuf;
- } else
- s = r->explain;
- }
-
- len = strlen(s) + 1;
- if (errbuf_size > 0) {
- llvm_strlcpy(errbuf, s, errbuf_size);
- }
-
- return(len);
-}
-
-/*
- - regatoi - internal routine to implement REG_ATOI
- */
-static const char *
-regatoi(const llvm_regex_t *preg, char *localbuf, int localbufsize)
-{
- struct rerr *r;
-
- for (r = rerrs; r->code != 0; r++)
- if (strcmp(r->name, preg->re_endp) == 0)
- break;
- if (r->code == 0)
- return("0");
-
- (void)snprintf(localbuf, localbufsize, "%d", r->code);
- return(localbuf);
-}
diff --git a/gnu/llvm/lib/Support/regex2.h b/gnu/llvm/lib/Support/regex2.h
deleted file mode 100644
index 19d14cd14ab..00000000000
--- a/gnu/llvm/lib/Support/regex2.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*-
- * This code is derived from OpenBSD's libc/regex, original license follows:
- *
- * Copyright (c) 1992, 1993, 1994 Henry Spencer.
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Henry Spencer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)regex2.h 8.4 (Berkeley) 3/20/94
- */
-
-#ifndef LLVM_SUPPORT_REGEX2_H
-#define LLVM_SUPPORT_REGEX2_H
-
-#include "regutils.h"
-#include <stddef.h>
-
-/*
- * internals of regex_t
- */
-#define MAGIC1 ((('r'^0200)<<8) | 'e')
-
-/*
- * The internal representation is a *strip*, a sequence of
- * operators ending with an endmarker. (Some terminology etc. is a
- * historical relic of earlier versions which used multiple strips.)
- * Certain oddities in the representation are there to permit running
- * the machinery backwards; in particular, any deviation from sequential
- * flow must be marked at both its source and its destination. Some
- * fine points:
- *
- * - OPLUS_ and O_PLUS are *inside* the loop they create.
- * - OQUEST_ and O_QUEST are *outside* the bypass they create.
- * - OCH_ and O_CH are *outside* the multi-way branch they create, while
- * OOR1 and OOR2 are respectively the end and the beginning of one of
- * the branches. Note that there is an implicit OOR2 following OCH_
- * and an implicit OOR1 preceding O_CH.
- *
- * In state representations, an operator's bit is on to signify a state
- * immediately *preceding* "execution" of that operator.
- */
-typedef unsigned long sop; /* strip operator */
-typedef long sopno;
-#define OPRMASK 0xf8000000LU
-#define OPDMASK 0x07ffffffLU
-#define OPSHIFT ((unsigned)27)
-#define OP(n) ((n)&OPRMASK)
-#define OPND(n) ((n)&OPDMASK)
-#define SOP(op, opnd) ((op)|(opnd))
-/* operators meaning operand */
-/* (back, fwd are offsets) */
-#define OEND (1LU<<OPSHIFT) /* endmarker - */
-#define OCHAR (2LU<<OPSHIFT) /* character unsigned char */
-#define OBOL (3LU<<OPSHIFT) /* left anchor - */
-#define OEOL (4LU<<OPSHIFT) /* right anchor - */
-#define OANY (5LU<<OPSHIFT) /* . - */
-#define OANYOF (6LU<<OPSHIFT) /* [...] set number */
-#define OBACK_ (7LU<<OPSHIFT) /* begin \d paren number */
-#define O_BACK (8LU<<OPSHIFT) /* end \d paren number */
-#define OPLUS_ (9LU<<OPSHIFT) /* + prefix fwd to suffix */
-#define O_PLUS (10LU<<OPSHIFT) /* + suffix back to prefix */
-#define OQUEST_ (11LU<<OPSHIFT) /* ? prefix fwd to suffix */
-#define O_QUEST (12LU<<OPSHIFT) /* ? suffix back to prefix */
-#define OLPAREN (13LU<<OPSHIFT) /* ( fwd to ) */
-#define ORPAREN (14LU<<OPSHIFT) /* ) back to ( */
-#define OCH_ (15LU<<OPSHIFT) /* begin choice fwd to OOR2 */
-#define OOR1 (16LU<<OPSHIFT) /* | pt. 1 back to OOR1 or OCH_ */
-#define OOR2 (17LU<<OPSHIFT) /* | pt. 2 fwd to OOR2 or O_CH */
-#define O_CH (18LU<<OPSHIFT) /* end choice back to OOR1 */
-#define OBOW (19LU<<OPSHIFT) /* begin word - */
-#define OEOW (20LU<<OPSHIFT) /* end word - */
-
-/*
- * Structure for [] character-set representation. Character sets are
- * done as bit vectors, grouped 8 to a byte vector for compactness.
- * The individual set therefore has both a pointer to the byte vector
- * and a mask to pick out the relevant bit of each byte. A hash code
- * simplifies testing whether two sets could be identical.
- *
- * This will get trickier for multicharacter collating elements. As
- * preliminary hooks for dealing with such things, we also carry along
- * a string of multi-character elements, and decide the size of the
- * vectors at run time.
- */
-typedef struct {
- uch *ptr; /* -> uch [csetsize] */
- uch mask; /* bit within array */
- uch hash; /* hash code */
- size_t smultis;
- char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */
-} cset;
-/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */
-#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c))
-#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c))
-#define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask)
-#define MCadd(p, cs, cp) mcadd(p, cs, cp) /* llvm_regcomp() internal fns */
-#define MCsub(p, cs, cp) mcsub(p, cs, cp)
-#define MCin(p, cs, cp) mcin(p, cs, cp)
-
-/* stuff for character categories */
-typedef unsigned char cat_t;
-
-/*
- * main compiled-expression structure
- */
-struct re_guts {
- int magic;
-# define MAGIC2 ((('R'^0200)<<8)|'E')
- sop *strip; /* malloced area for strip */
- int csetsize; /* number of bits in a cset vector */
- int ncsets; /* number of csets in use */
- cset *sets; /* -> cset [ncsets] */
- uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */
- int cflags; /* copy of llvm_regcomp() cflags argument */
- sopno nstates; /* = number of sops */
- sopno firststate; /* the initial OEND (normally 0) */
- sopno laststate; /* the final OEND */
- int iflags; /* internal flags */
-# define USEBOL 01 /* used ^ */
-# define USEEOL 02 /* used $ */
-# define REGEX_BAD 04 /* something wrong */
- int nbol; /* number of ^ used */
- int neol; /* number of $ used */
- int ncategories; /* how many character categories */
- cat_t *categories; /* ->catspace[-CHAR_MIN] */
- char *must; /* match must contain this string */
- int mlen; /* length of must */
- size_t nsub; /* copy of re_nsub */
- int backrefs; /* does it use back references? */
- sopno nplus; /* how deep does it nest +s? */
- /* catspace must be last */
- cat_t catspace[1]; /* actually [NC] */
-};
-
-/* misc utilities */
-#define OUT (CHAR_MAX+1) /* a non-character value */
-#define ISWORD(c) (isalnum(c&0xff) || (c) == '_')
-
-#endif
diff --git a/gnu/llvm/lib/Support/regex_impl.h b/gnu/llvm/lib/Support/regex_impl.h
deleted file mode 100644
index 8ddac7dcf99..00000000000
--- a/gnu/llvm/lib/Support/regex_impl.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*-
- * This code is derived from OpenBSD's libc/regex, original license follows:
- *
- * Copyright (c) 1992 Henry Spencer.
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Henry Spencer of the University of Toronto.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)regex.h 8.1 (Berkeley) 6/2/93
- */
-
-#ifndef _REGEX_H_
-#define _REGEX_H_
-
-#include <sys/types.h>
-typedef off_t llvm_regoff_t;
-typedef struct {
- llvm_regoff_t rm_so; /* start of match */
- llvm_regoff_t rm_eo; /* end of match */
-} llvm_regmatch_t;
-
-typedef struct llvm_regex {
- int re_magic;
- size_t re_nsub; /* number of parenthesized subexpressions */
- const char *re_endp; /* end pointer for REG_PEND */
- struct re_guts *re_g; /* none of your business :-) */
-} llvm_regex_t;
-
-/* llvm_regcomp() flags */
-#define REG_BASIC 0000
-#define REG_EXTENDED 0001
-#define REG_ICASE 0002
-#define REG_NOSUB 0004
-#define REG_NEWLINE 0010
-#define REG_NOSPEC 0020
-#define REG_PEND 0040
-#define REG_DUMP 0200
-
-/* llvm_regerror() flags */
-#define REG_NOMATCH 1
-#define REG_BADPAT 2
-#define REG_ECOLLATE 3
-#define REG_ECTYPE 4
-#define REG_EESCAPE 5
-#define REG_ESUBREG 6
-#define REG_EBRACK 7
-#define REG_EPAREN 8
-#define REG_EBRACE 9
-#define REG_BADBR 10
-#define REG_ERANGE 11
-#define REG_ESPACE 12
-#define REG_BADRPT 13
-#define REG_EMPTY 14
-#define REG_ASSERT 15
-#define REG_INVARG 16
-#define REG_ATOI 255 /* convert name to number (!) */
-#define REG_ITOA 0400 /* convert number to name (!) */
-
-/* llvm_regexec() flags */
-#define REG_NOTBOL 00001
-#define REG_NOTEOL 00002
-#define REG_STARTEND 00004
-#define REG_TRACE 00400 /* tracing of execution */
-#define REG_LARGE 01000 /* force large representation */
-#define REG_BACKR 02000 /* force use of backref code */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int llvm_regcomp(llvm_regex_t *, const char *, int);
-size_t llvm_regerror(int, const llvm_regex_t *, char *, size_t);
-int llvm_regexec(const llvm_regex_t *, const char *, size_t,
- llvm_regmatch_t [], int);
-void llvm_regfree(llvm_regex_t *);
-size_t llvm_strlcpy(char *dst, const char *src, size_t siz);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !_REGEX_H_ */
diff --git a/gnu/llvm/lib/Support/regexec.c b/gnu/llvm/lib/Support/regexec.c
deleted file mode 100644
index bd5e72d4c52..00000000000
--- a/gnu/llvm/lib/Support/regexec.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*-
- * This code is derived from OpenBSD's libc/regex, original license follows:
- *
- * Copyright (c) 1992, 1993, 1994 Henry Spencer.
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Henry Spencer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)regexec.c 8.3 (Berkeley) 3/20/94
- */
-
-/*
- * the outer shell of llvm_regexec()
- *
- * This file includes engine.inc *twice*, after muchos fiddling with the
- * macros that code uses. This lets the same code operate on two different
- * representations for state sets.
- */
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <ctype.h>
-#include "regex_impl.h"
-
-#include "regutils.h"
-#include "regex2.h"
-
-/* macros for manipulating states, small version */
-/* FIXME: 'states' is assumed as 'long' on small version. */
-#define states1 long /* for later use in llvm_regexec() decision */
-#define states states1
-#define CLEAR(v) ((v) = 0)
-#define SET0(v, n) ((v) &= ~((unsigned long)1 << (n)))
-#define SET1(v, n) ((v) |= (unsigned long)1 << (n))
-#define ISSET(v, n) (((v) & ((unsigned long)1 << (n))) != 0)
-#define ASSIGN(d, s) ((d) = (s))
-#define EQ(a, b) ((a) == (b))
-#define STATEVARS long dummy /* dummy version */
-#define STATESETUP(m, n) /* nothing */
-#define STATETEARDOWN(m) /* nothing */
-#define SETUP(v) ((v) = 0)
-#define onestate long
-#define INIT(o, n) ((o) = (unsigned long)1 << (n))
-#define INC(o) ((o) = (unsigned long)(o) << 1)
-#define ISSTATEIN(v, o) (((v) & (o)) != 0)
-/* some abbreviations; note that some of these know variable names! */
-/* do "if I'm here, I can also be there" etc without branches */
-#define FWD(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) << (n))
-#define BACK(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) >> (n))
-#define ISSETBACK(v, n) (((v) & ((unsigned long)here >> (n))) != 0)
-/* function names */
-#define SNAMES /* engine.inc looks after details */
-
-#include "regengine.inc"
-
-/* now undo things */
-#undef states
-#undef CLEAR
-#undef SET0
-#undef SET1
-#undef ISSET
-#undef ASSIGN
-#undef EQ
-#undef STATEVARS
-#undef STATESETUP
-#undef STATETEARDOWN
-#undef SETUP
-#undef onestate
-#undef INIT
-#undef INC
-#undef ISSTATEIN
-#undef FWD
-#undef BACK
-#undef ISSETBACK
-#undef SNAMES
-
-/* macros for manipulating states, large version */
-#define states char *
-#define CLEAR(v) memset(v, 0, m->g->nstates)
-#define SET0(v, n) ((v)[n] = 0)
-#define SET1(v, n) ((v)[n] = 1)
-#define ISSET(v, n) ((v)[n])
-#define ASSIGN(d, s) memmove(d, s, m->g->nstates)
-#define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0)
-#define STATEVARS long vn; char *space
-#define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \
- if ((m)->space == NULL) return(REG_ESPACE); \
- (m)->vn = 0; }
-#define STATETEARDOWN(m) { free((m)->space); }
-#define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates])
-#define onestate long
-#define INIT(o, n) ((o) = (n))
-#define INC(o) ((o)++)
-#define ISSTATEIN(v, o) ((v)[o])
-/* some abbreviations; note that some of these know variable names! */
-/* do "if I'm here, I can also be there" etc without branches */
-#define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here])
-#define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here])
-#define ISSETBACK(v, n) ((v)[here - (n)])
-/* function names */
-#define LNAMES /* flag */
-
-#include "regengine.inc"
-
-/*
- - llvm_regexec - interface for matching
- *
- * We put this here so we can exploit knowledge of the state representation
- * when choosing which matcher to call. Also, by this point the matchers
- * have been prototyped.
- */
-int /* 0 success, REG_NOMATCH failure */
-llvm_regexec(const llvm_regex_t *preg, const char *string, size_t nmatch,
- llvm_regmatch_t pmatch[], int eflags)
-{
- struct re_guts *g = preg->re_g;
-#ifdef REDEBUG
-# define GOODFLAGS(f) (f)
-#else
-# define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND))
-#endif
-
- if (preg->re_magic != MAGIC1 || g->magic != MAGIC2)
- return(REG_BADPAT);
- assert(!(g->iflags&REGEX_BAD));
- if (g->iflags&REGEX_BAD) /* backstop for no-debug case */
- return(REG_BADPAT);
- eflags = GOODFLAGS(eflags);
-
- if (g->nstates <= (long)(CHAR_BIT*sizeof(states1)) && !(eflags&REG_LARGE))
- return(smatcher(g, string, nmatch, pmatch, eflags));
- else
- return(lmatcher(g, string, nmatch, pmatch, eflags));
-}
diff --git a/gnu/llvm/lib/Support/regfree.c b/gnu/llvm/lib/Support/regfree.c
deleted file mode 100644
index dc2b4af90fa..00000000000
--- a/gnu/llvm/lib/Support/regfree.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-
- * This code is derived from OpenBSD's libc/regex, original license follows:
- *
- * Copyright (c) 1992, 1993, 1994 Henry Spencer.
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Henry Spencer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)regfree.c 8.3 (Berkeley) 3/20/94
- */
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "regex_impl.h"
-
-#include "regutils.h"
-#include "regex2.h"
-
-/*
- - llvm_regfree - free everything
- */
-void
-llvm_regfree(llvm_regex_t *preg)
-{
- struct re_guts *g;
-
- if (preg->re_magic != MAGIC1) /* oops */
- return; /* nice to complain, but hard */
-
- g = preg->re_g;
- if (g == NULL || g->magic != MAGIC2) /* oops again */
- return;
- preg->re_magic = 0; /* mark it invalid */
- g->magic = 0; /* mark it invalid */
-
- if (g->strip != NULL)
- free((char *)g->strip);
- if (g->sets != NULL)
- free((char *)g->sets);
- if (g->setbits != NULL)
- free((char *)g->setbits);
- if (g->must != NULL)
- free(g->must);
- free((char *)g);
-}
diff --git a/gnu/llvm/lib/Support/regstrlcpy.c b/gnu/llvm/lib/Support/regstrlcpy.c
deleted file mode 100644
index 8b68afdf75f..00000000000
--- a/gnu/llvm/lib/Support/regstrlcpy.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * This code is derived from OpenBSD's libc, original license follows:
- *
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <string.h>
-
-#include "regex_impl.h"
-/*
- * Copy src to string dst of size siz. At most siz-1 characters
- * will be copied. Always NUL terminates (unless siz == 0).
- * Returns strlen(src); if retval >= siz, truncation occurred.
- */
-size_t
-llvm_strlcpy(char *dst, const char *src, size_t siz)
-{
- char *d = dst;
- const char *s = src;
- size_t n = siz;
-
- /* Copy as many bytes as will fit */
- if (n != 0) {
- while (--n != 0) {
- if ((*d++ = *s++) == '\0')
- break;
- }
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0) {
- if (siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while (*s++)
- ;
- }
-
- return(s - src - 1); /* count does not include NUL */
-}
diff --git a/gnu/llvm/lib/Support/regutils.h b/gnu/llvm/lib/Support/regutils.h
deleted file mode 100644
index 49a975cd270..00000000000
--- a/gnu/llvm/lib/Support/regutils.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*-
- * This code is derived from OpenBSD's libc/regex, original license follows:
- *
- * Copyright (c) 1992, 1993, 1994 Henry Spencer.
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Henry Spencer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)utils.h 8.3 (Berkeley) 3/20/94
- */
-
-#ifndef LLVM_SUPPORT_REGUTILS_H
-#define LLVM_SUPPORT_REGUTILS_H
-
-/* utility definitions */
-#define NC (CHAR_MAX - CHAR_MIN + 1)
-typedef unsigned char uch;
-
-/* switch off assertions (if not already off) if no REDEBUG */
-#ifndef REDEBUG
-#ifndef NDEBUG
-#define NDEBUG /* no assertions please */
-#endif
-#endif
-#include <assert.h>
-
-/* for old systems with bcopy() but no memmove() */
-#ifdef USEBCOPY
-#define memmove(d, s, c) bcopy(s, d, c)
-#endif
-
-#endif
diff --git a/gnu/llvm/lib/Support/xxhash.cpp b/gnu/llvm/lib/Support/xxhash.cpp
deleted file mode 100644
index e9dceed2c4a..00000000000
--- a/gnu/llvm/lib/Support/xxhash.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-* xxHash - Fast Hash algorithm
-* Copyright (C) 2012-2016, Yann Collet
-*
-* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-*
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following disclaimer
-* in the documentation and/or other materials provided with the
-* distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
-* You can contact the author at :
-* - xxHash homepage: http://www.xxhash.com
-* - xxHash source repository : https://github.com/Cyan4973/xxHash
-*/
-
-/* based on revision d2df04efcbef7d7f6886d345861e5dfda4edacc1 Removed
- * everything but a simple interface for computing XXh64. */
-
-#include "llvm/Support/xxhash.h"
-#include "llvm/Support/Endian.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-using namespace llvm;
-using namespace support;
-
-static uint64_t rotl64(uint64_t X, size_t R) {
- return (X << R) | (X >> (64 - R));
-}
-
-static const uint64_t PRIME64_1 = 11400714785074694791ULL;
-static const uint64_t PRIME64_2 = 14029467366897019727ULL;
-static const uint64_t PRIME64_3 = 1609587929392839161ULL;
-static const uint64_t PRIME64_4 = 9650029242287828579ULL;
-static const uint64_t PRIME64_5 = 2870177450012600261ULL;
-
-static uint64_t round(uint64_t Acc, uint64_t Input) {
- Acc += Input * PRIME64_2;
- Acc = rotl64(Acc, 31);
- Acc *= PRIME64_1;
- return Acc;
-}
-
-static uint64_t mergeRound(uint64_t Acc, uint64_t Val) {
- Val = round(0, Val);
- Acc ^= Val;
- Acc = Acc * PRIME64_1 + PRIME64_4;
- return Acc;
-}
-
-uint64_t llvm::xxHash64(StringRef Data) {
- size_t Len = Data.size();
- uint64_t Seed = 0;
- const unsigned char *P = Data.bytes_begin();
- const unsigned char *const BEnd = Data.bytes_end();
- uint64_t H64;
-
- if (Len >= 32) {
- const unsigned char *const Limit = BEnd - 32;
- uint64_t V1 = Seed + PRIME64_1 + PRIME64_2;
- uint64_t V2 = Seed + PRIME64_2;
- uint64_t V3 = Seed + 0;
- uint64_t V4 = Seed - PRIME64_1;
-
- do {
- V1 = round(V1, endian::read64le(P));
- P += 8;
- V2 = round(V2, endian::read64le(P));
- P += 8;
- V3 = round(V3, endian::read64le(P));
- P += 8;
- V4 = round(V4, endian::read64le(P));
- P += 8;
- } while (P <= Limit);
-
- H64 = rotl64(V1, 1) + rotl64(V2, 7) + rotl64(V3, 12) + rotl64(V4, 18);
- H64 = mergeRound(H64, V1);
- H64 = mergeRound(H64, V2);
- H64 = mergeRound(H64, V3);
- H64 = mergeRound(H64, V4);
-
- } else {
- H64 = Seed + PRIME64_5;
- }
-
- H64 += (uint64_t)Len;
-
- while (P + 8 <= BEnd) {
- uint64_t const K1 = round(0, endian::read64le(P));
- H64 ^= K1;
- H64 = rotl64(H64, 27) * PRIME64_1 + PRIME64_4;
- P += 8;
- }
-
- if (P + 4 <= BEnd) {
- H64 ^= (uint64_t)(endian::read32le(P)) * PRIME64_1;
- H64 = rotl64(H64, 23) * PRIME64_2 + PRIME64_3;
- P += 4;
- }
-
- while (P < BEnd) {
- H64 ^= (*P) * PRIME64_5;
- H64 = rotl64(H64, 11) * PRIME64_1;
- P++;
- }
-
- H64 ^= H64 >> 33;
- H64 *= PRIME64_2;
- H64 ^= H64 >> 29;
- H64 *= PRIME64_3;
- H64 ^= H64 >> 32;
-
- return H64;
-}
-
-uint64_t llvm::xxHash64(ArrayRef<uint8_t> Data) {
- return xxHash64({(const char *)Data.data(), Data.size()});
-}