diff options
Diffstat (limited to 'gnu/llvm/lib/Support')
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", <); - 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(), <); - 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 ¤t_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 &®ex) { - 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 << "&"; - else if (C == '<') - Out << "<"; - else if (C == '>') - Out << ">"; - else if (C == '\"') - Out << """; - else if (C == '\'') - Out << "'"; - 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, - ¶m, 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®_EXTENDED) && (cflags®_NOSPEC)) - return(REG_INVARG); - - if (cflags®_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®_EXTENDED) - p_ere(p, OUT); - else if (cflags®_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®EX_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®_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®_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®_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®_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®_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®_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®_NOSUB) - nmatch = 0; - if (eflags®_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®_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®_NOTBOL)) || - (sp < m->endp && *(sp-1) == '\n' && - (m->g->cflags®_NEWLINE)) ) - { /* yes */ } - else - return(NULL); - break; - case OEOL: - if ( (sp == m->endp && !(m->eflags®_NOTEOL)) || - (sp < m->endp && *sp == '\n' && - (m->g->cflags®_NEWLINE)) ) - { /* yes */ } - else - return(NULL); - break; - case OBOW: - if (( (sp == m->beginp && !(m->eflags®_NOTBOL)) || - (sp < m->endp && *(sp-1) == '\n' && - (m->g->cflags®_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®_NOTEOL)) || - (sp < m->endp && *sp == '\n' && - (m->g->cflags®_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®_NEWLINE) || - (lastc == OUT && !(m->eflags®_NOTBOL)) ) { - flagch = BOL; - i = m->g->nbol; - } - if ( (c == '\n' && m->g->cflags®_NEWLINE) || - (c == OUT && !(m->eflags®_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®_NEWLINE) || - (lastc == OUT && !(m->eflags®_NOTBOL)) ) { - flagch = BOL; - i = m->g->nbol; - } - if ( (c == '\n' && m->g->cflags®_NEWLINE) || - (c == OUT && !(m->eflags®_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®_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®_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®_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®EX_BAD)); - if (g->iflags®EX_BAD) /* backstop for no-debug case */ - return(REG_BADPAT); - eflags = GOODFLAGS(eflags); - - if (g->nstates <= (long)(CHAR_BIT*sizeof(states1)) && !(eflags®_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()}); -} |
