summaryrefslogtreecommitdiff
path: root/third_party/llvm-project/include/llvm/ADT
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2019-12-19 09:04:08 -0800
committerGitHub <noreply@github.com>2019-12-19 09:04:08 -0800
commit4d28d3f32e7f213e300b24bc61c3f0ac9d6e1ab6 (patch)
tree91bffc2d47b1fe4bba01e7ada77006ef340bd138 /third_party/llvm-project/include/llvm/ADT
parent0048f5b004ddf50e750aa335d0be314a73852058 (diff)
downloadbinaryen-4d28d3f32e7f213e300b24bc61c3f0ac9d6e1ab6.tar.gz
binaryen-4d28d3f32e7f213e300b24bc61c3f0ac9d6e1ab6.tar.bz2
binaryen-4d28d3f32e7f213e300b24bc61c3f0ac9d6e1ab6.zip
DWARF parsing and writing support using LLVM (#2520)
This imports LLVM code for DWARF handling. That code has the Apache 2 license like us. It's also the same code used to emit DWARF in the common toolchain, so it seems like a safe choice. This adds two passes: --dwarfdump which runs the same code LLVM runs for llvm-dwarfdump. This shows we can parse it ok, and will be useful for debugging. And --dwarfupdate writes out the DWARF sections (unchanged from what we read, so it just roundtrips - for updating we need #2515). This puts LLVM in thirdparty which is added here. All the LLVM code is behind USE_LLVM_DWARF, which is on by default, but off in JS for now, as it increases code size by 20%. This current approach imports the LLVM files directly. This is not how they are intended to be used, so it required a bunch of local changes - more than I expected actually, for the platform-specific stuff. For now this seems to work, so it may be good enough, but in the long term we may want to switch to linking against libllvm. A downside to doing that is that binaryen users would need to have an LLVM build, and even in the waterfall builds we'd have a problem - while we ship LLVM there anyhow, we constantly update it, which means that binaryen would need to be on latest llvm all the time too (which otherwise, given DWARF is quite stable, we might not need to constantly update). An even larger issue is that as I did this work I learned about how DWARF works in LLVM, and while the reading code is easy to reuse, the writing code is trickier. The main code path is heavily integrated with the MC layer, which we don't have - we might want to create a "fake MC layer" for that, but it sounds hard. Instead, there is the YAML path which is used mostly for testing, and which can convert DWARF to and from YAML and from binary. Using the non-YAML parts there, we can convert binary DWARF to the YAML layer's nice Info data, then convert that to binary. This works, however, this is not the path LLVM uses normally, and it supports only some basic DWARF sections - I had to add ranges support, in fact. So if we need more complex things, we may end up needing to use the MC layer approach, or consider some other DWARF library. However, hopefully that should not affect the core binaryen code which just calls a library for DWARF stuff. Helps #2400
Diffstat (limited to 'third_party/llvm-project/include/llvm/ADT')
-rw-r--r--third_party/llvm-project/include/llvm/ADT/APFloat.h1290
-rw-r--r--third_party/llvm-project/include/llvm/ADT/APInt.h2258
-rw-r--r--third_party/llvm-project/include/llvm/ADT/APSInt.h353
-rw-r--r--third_party/llvm-project/include/llvm/ADT/AllocatorList.h240
-rw-r--r--third_party/llvm-project/include/llvm/ADT/ArrayRef.h540
-rw-r--r--third_party/llvm-project/include/llvm/ADT/BitmaskEnum.h152
-rw-r--r--third_party/llvm-project/include/llvm/ADT/DenseMap.h1275
-rw-r--r--third_party/llvm-project/include/llvm/ADT/DenseMapInfo.h300
-rw-r--r--third_party/llvm-project/include/llvm/ADT/DenseSet.h283
-rw-r--r--third_party/llvm-project/include/llvm/ADT/EpochTracker.h98
-rw-r--r--third_party/llvm-project/include/llvm/ADT/FoldingSet.h761
-rw-r--r--third_party/llvm-project/include/llvm/ADT/FunctionExtras.h292
-rw-r--r--third_party/llvm-project/include/llvm/ADT/Hashing.h659
-rw-r--r--third_party/llvm-project/include/llvm/ADT/MapVector.h239
-rw-r--r--third_party/llvm-project/include/llvm/ADT/None.h26
-rw-r--r--third_party/llvm-project/include/llvm/ADT/Optional.h429
-rw-r--r--third_party/llvm-project/include/llvm/ADT/PointerIntPair.h243
-rw-r--r--third_party/llvm-project/include/llvm/ADT/PointerUnion.h309
-rw-r--r--third_party/llvm-project/include/llvm/ADT/STLExtras.h1578
-rw-r--r--third_party/llvm-project/include/llvm/ADT/SmallPtrSet.h511
-rw-r--r--third_party/llvm-project/include/llvm/ADT/SmallSet.h278
-rw-r--r--third_party/llvm-project/include/llvm/ADT/SmallString.h296
-rw-r--r--third_party/llvm-project/include/llvm/ADT/SmallVector.h930
-rw-r--r--third_party/llvm-project/include/llvm/ADT/StringExtras.h401
-rw-r--r--third_party/llvm-project/include/llvm/ADT/StringMap.h593
-rw-r--r--third_party/llvm-project/include/llvm/ADT/StringRef.h920
-rw-r--r--third_party/llvm-project/include/llvm/ADT/StringSet.h58
-rw-r--r--third_party/llvm-project/include/llvm/ADT/StringSwitch.h196
-rw-r--r--third_party/llvm-project/include/llvm/ADT/Triple.h881
-rw-r--r--third_party/llvm-project/include/llvm/ADT/Twine.h544
-rw-r--r--third_party/llvm-project/include/llvm/ADT/bit.h58
-rw-r--r--third_party/llvm-project/include/llvm/ADT/edit_distance.h102
-rw-r--r--third_party/llvm-project/include/llvm/ADT/fallible_iterator.h243
-rw-r--r--third_party/llvm-project/include/llvm/ADT/ilist_base.h92
-rw-r--r--third_party/llvm-project/include/llvm/ADT/ilist_iterator.h198
-rw-r--r--third_party/llvm-project/include/llvm/ADT/ilist_node.h305
-rw-r--r--third_party/llvm-project/include/llvm/ADT/ilist_node_base.h52
-rw-r--r--third_party/llvm-project/include/llvm/ADT/ilist_node_options.h131
-rw-r--r--third_party/llvm-project/include/llvm/ADT/iterator.h366
-rw-r--r--third_party/llvm-project/include/llvm/ADT/iterator_range.h69
-rw-r--r--third_party/llvm-project/include/llvm/ADT/simple_ilist.h314
41 files changed, 18863 insertions, 0 deletions
diff --git a/third_party/llvm-project/include/llvm/ADT/APFloat.h b/third_party/llvm-project/include/llvm/ADT/APFloat.h
new file mode 100644
index 000000000..1c4969733
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/APFloat.h
@@ -0,0 +1,1290 @@
+//===- llvm/ADT/APFloat.h - Arbitrary Precision Floating Point ---*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief
+/// This file declares a class to represent arbitrary precision floating point
+/// values and provide a variety of arithmetic operations on them.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_APFLOAT_H
+#define LLVM_ADT_APFLOAT_H
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <memory>
+
+#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)
+
+namespace llvm {
+
+struct fltSemantics;
+class APSInt;
+class StringRef;
+class APFloat;
+class raw_ostream;
+
+template <typename T> class SmallVectorImpl;
+
+/// Enum that represents what fraction of the LSB truncated bits of an fp number
+/// represent.
+///
+/// This essentially combines the roles of guard and sticky bits.
+enum lostFraction { // Example of truncated bits:
+ lfExactlyZero, // 000000
+ lfLessThanHalf, // 0xxxxx x's not all zero
+ lfExactlyHalf, // 100000
+ lfMoreThanHalf // 1xxxxx x's not all zero
+};
+
+/// A self-contained host- and target-independent arbitrary-precision
+/// floating-point software implementation.
+///
+/// APFloat uses bignum integer arithmetic as provided by static functions in
+/// the APInt class. The library will work with bignum integers whose parts are
+/// any unsigned type at least 16 bits wide, but 64 bits is recommended.
+///
+/// Written for clarity rather than speed, in particular with a view to use in
+/// the front-end of a cross compiler so that target arithmetic can be correctly
+/// performed on the host. Performance should nonetheless be reasonable,
+/// particularly for its intended use. It may be useful as a base
+/// implementation for a run-time library during development of a faster
+/// target-specific one.
+///
+/// All 5 rounding modes in the IEEE-754R draft are handled correctly for all
+/// implemented operations. Currently implemented operations are add, subtract,
+/// multiply, divide, fused-multiply-add, conversion-to-float,
+/// conversion-to-integer and conversion-from-integer. New rounding modes
+/// (e.g. away from zero) can be added with three or four lines of code.
+///
+/// Four formats are built-in: IEEE single precision, double precision,
+/// quadruple precision, and x87 80-bit extended double (when operating with
+/// full extended precision). Adding a new format that obeys IEEE semantics
+/// only requires adding two lines of code: a declaration and definition of the
+/// format.
+///
+/// All operations return the status of that operation as an exception bit-mask,
+/// so multiple operations can be done consecutively with their results or-ed
+/// together. The returned status can be useful for compiler diagnostics; e.g.,
+/// inexact, underflow and overflow can be easily diagnosed on constant folding,
+/// and compiler optimizers can determine what exceptions would be raised by
+/// folding operations and optimize, or perhaps not optimize, accordingly.
+///
+/// At present, underflow tininess is detected after rounding; it should be
+/// straight forward to add support for the before-rounding case too.
+///
+/// The library reads hexadecimal floating point numbers as per C99, and
+/// correctly rounds if necessary according to the specified rounding mode.
+/// Syntax is required to have been validated by the caller. It also converts
+/// floating point numbers to hexadecimal text as per the C99 %a and %A
+/// conversions. The output precision (or alternatively the natural minimal
+/// precision) can be specified; if the requested precision is less than the
+/// natural precision the output is correctly rounded for the specified rounding
+/// mode.
+///
+/// It also reads decimal floating point numbers and correctly rounds according
+/// to the specified rounding mode.
+///
+/// Conversion to decimal text is not currently implemented.
+///
+/// Non-zero finite numbers are represented internally as a sign bit, a 16-bit
+/// signed exponent, and the significand as an array of integer parts. After
+/// normalization of a number of precision P the exponent is within the range of
+/// the format, and if the number is not denormal the P-th bit of the
+/// significand is set as an explicit integer bit. For denormals the most
+/// significant bit is shifted right so that the exponent is maintained at the
+/// format's minimum, so that the smallest denormal has just the least
+/// significant bit of the significand set. The sign of zeroes and infinities
+/// is significant; the exponent and significand of such numbers is not stored,
+/// but has a known implicit (deterministic) value: 0 for the significands, 0
+/// for zero exponent, all 1 bits for infinity exponent. For NaNs the sign and
+/// significand are deterministic, although not really meaningful, and preserved
+/// in non-conversion operations. The exponent is implicitly all 1 bits.
+///
+/// APFloat does not provide any exception handling beyond default exception
+/// handling. We represent Signaling NaNs via IEEE-754R 2008 6.2.1 should clause
+/// by encoding Signaling NaNs with the first bit of its trailing significand as
+/// 0.
+///
+/// TODO
+/// ====
+///
+/// Some features that may or may not be worth adding:
+///
+/// Binary to decimal conversion (hard).
+///
+/// Optional ability to detect underflow tininess before rounding.
+///
+/// New formats: x87 in single and double precision mode (IEEE apart from
+/// extended exponent range) (hard).
+///
+/// New operations: sqrt, IEEE remainder, C90 fmod, nexttoward.
+///
+
+// This is the common type definitions shared by APFloat and its internal
+// implementation classes. This struct should not define any non-static data
+// members.
+struct APFloatBase {
+ typedef APInt::WordType integerPart;
+ static const unsigned integerPartWidth = APInt::APINT_BITS_PER_WORD;
+
+ /// A signed type to represent a floating point numbers unbiased exponent.
+ typedef signed short ExponentType;
+
+ /// \name Floating Point Semantics.
+ /// @{
+ enum Semantics {
+ S_IEEEhalf,
+ S_IEEEsingle,
+ S_IEEEdouble,
+ S_x87DoubleExtended,
+ S_IEEEquad,
+ S_PPCDoubleDouble
+ };
+
+ static const llvm::fltSemantics &EnumToSemantics(Semantics S);
+ static Semantics SemanticsToEnum(const llvm::fltSemantics &Sem);
+
+ static const fltSemantics &IEEEhalf() LLVM_READNONE;
+ static const fltSemantics &IEEEsingle() LLVM_READNONE;
+ static const fltSemantics &IEEEdouble() LLVM_READNONE;
+ static const fltSemantics &IEEEquad() LLVM_READNONE;
+ static const fltSemantics &PPCDoubleDouble() LLVM_READNONE;
+ static const fltSemantics &x87DoubleExtended() LLVM_READNONE;
+
+ /// A Pseudo fltsemantic used to construct APFloats that cannot conflict with
+ /// anything real.
+ static const fltSemantics &Bogus() LLVM_READNONE;
+
+ /// @}
+
+ /// IEEE-754R 5.11: Floating Point Comparison Relations.
+ enum cmpResult {
+ cmpLessThan,
+ cmpEqual,
+ cmpGreaterThan,
+ cmpUnordered
+ };
+
+ /// IEEE-754R 4.3: Rounding-direction attributes.
+ enum roundingMode {
+ rmNearestTiesToEven,
+ rmTowardPositive,
+ rmTowardNegative,
+ rmTowardZero,
+ rmNearestTiesToAway
+ };
+
+ /// IEEE-754R 7: Default exception handling.
+ ///
+ /// opUnderflow or opOverflow are always returned or-ed with opInexact.
+ ///
+ /// APFloat models this behavior specified by IEEE-754:
+ /// "For operations producing results in floating-point format, the default
+ /// result of an operation that signals the invalid operation exception
+ /// shall be a quiet NaN."
+ enum opStatus {
+ opOK = 0x00,
+ opInvalidOp = 0x01,
+ opDivByZero = 0x02,
+ opOverflow = 0x04,
+ opUnderflow = 0x08,
+ opInexact = 0x10
+ };
+
+ /// Category of internally-represented number.
+ enum fltCategory {
+ fcInfinity,
+ fcNaN,
+ fcNormal,
+ fcZero
+ };
+
+ /// Convenience enum used to construct an uninitialized APFloat.
+ enum uninitializedTag {
+ uninitialized
+ };
+
+ /// Enumeration of \c ilogb error results.
+ enum IlogbErrorKinds {
+ IEK_Zero = INT_MIN + 1,
+ IEK_NaN = INT_MIN,
+ IEK_Inf = INT_MAX
+ };
+
+ static unsigned int semanticsPrecision(const fltSemantics &);
+ static ExponentType semanticsMinExponent(const fltSemantics &);
+ static ExponentType semanticsMaxExponent(const fltSemantics &);
+ static unsigned int semanticsSizeInBits(const fltSemantics &);
+
+ /// Returns the size of the floating point number (in bits) in the given
+ /// semantics.
+ static unsigned getSizeInBits(const fltSemantics &Sem);
+};
+
+namespace detail {
+
+class IEEEFloat final : public APFloatBase {
+public:
+ /// \name Constructors
+ /// @{
+
+ IEEEFloat(const fltSemantics &); // Default construct to 0.0
+ IEEEFloat(const fltSemantics &, integerPart);
+ IEEEFloat(const fltSemantics &, uninitializedTag);
+ IEEEFloat(const fltSemantics &, const APInt &);
+ explicit IEEEFloat(double d);
+ explicit IEEEFloat(float f);
+ IEEEFloat(const IEEEFloat &);
+ IEEEFloat(IEEEFloat &&);
+ ~IEEEFloat();
+
+ /// @}
+
+ /// Returns whether this instance allocated memory.
+ bool needsCleanup() const { return partCount() > 1; }
+
+ /// \name Convenience "constructors"
+ /// @{
+
+ /// @}
+
+ /// \name Arithmetic
+ /// @{
+
+ opStatus add(const IEEEFloat &, roundingMode);
+ opStatus subtract(const IEEEFloat &, roundingMode);
+ opStatus multiply(const IEEEFloat &, roundingMode);
+ opStatus divide(const IEEEFloat &, roundingMode);
+ /// IEEE remainder.
+ opStatus remainder(const IEEEFloat &);
+ /// C fmod, or llvm frem.
+ opStatus mod(const IEEEFloat &);
+ opStatus fusedMultiplyAdd(const IEEEFloat &, const IEEEFloat &, roundingMode);
+ opStatus roundToIntegral(roundingMode);
+ /// IEEE-754R 5.3.1: nextUp/nextDown.
+ opStatus next(bool nextDown);
+
+ /// @}
+
+ /// \name Sign operations.
+ /// @{
+
+ void changeSign();
+
+ /// @}
+
+ /// \name Conversions
+ /// @{
+
+ opStatus convert(const fltSemantics &, roundingMode, bool *);
+ opStatus convertToInteger(MutableArrayRef<integerPart>, unsigned int, bool,
+ roundingMode, bool *) const;
+ opStatus convertFromAPInt(const APInt &, bool, roundingMode);
+ opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int,
+ bool, roundingMode);
+ opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int,
+ bool, roundingMode);
+ opStatus convertFromString(StringRef, roundingMode);
+ APInt bitcastToAPInt() const;
+ double convertToDouble() const;
+ float convertToFloat() const;
+
+ /// @}
+
+ /// The definition of equality is not straightforward for floating point, so
+ /// we won't use operator==. Use one of the following, or write whatever it
+ /// is you really mean.
+ bool operator==(const IEEEFloat &) const = delete;
+
+ /// IEEE comparison with another floating point number (NaNs compare
+ /// unordered, 0==-0).
+ cmpResult compare(const IEEEFloat &) const;
+
+ /// Bitwise comparison for equality (QNaNs compare equal, 0!=-0).
+ bool bitwiseIsEqual(const IEEEFloat &) const;
+
+ /// 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.
+ unsigned int convertToHexString(char *dst, unsigned int hexDigits,
+ bool upperCase, roundingMode) const;
+
+ /// \name IEEE-754R 5.7.2 General operations.
+ /// @{
+
+ /// IEEE-754R isSignMinus: Returns true if and only if the current value is
+ /// negative.
+ ///
+ /// This applies to zeros and NaNs as well.
+ bool isNegative() const { return sign; }
+
+ /// IEEE-754R isNormal: Returns true if and only if the current value is normal.
+ ///
+ /// This implies that the current value of the float is not zero, subnormal,
+ /// infinite, or NaN following the definition of normality from IEEE-754R.
+ bool isNormal() const { return !isDenormal() && isFiniteNonZero(); }
+
+ /// Returns true if and only if the current value is zero, subnormal, or
+ /// normal.
+ ///
+ /// This means that the value is not infinite or NaN.
+ bool isFinite() const { return !isNaN() && !isInfinity(); }
+
+ /// Returns true if and only if the float is plus or minus zero.
+ bool isZero() const { return category == fcZero; }
+
+ /// IEEE-754R isSubnormal(): Returns true if and only if the float is a
+ /// denormal.
+ bool isDenormal() const;
+
+ /// IEEE-754R isInfinite(): Returns true if and only if the float is infinity.
+ bool isInfinity() const { return category == fcInfinity; }
+
+ /// Returns true if and only if the float is a quiet or signaling NaN.
+ bool isNaN() const { return category == fcNaN; }
+
+ /// Returns true if and only if the float is a signaling NaN.
+ bool isSignaling() const;
+
+ /// @}
+
+ /// \name Simple Queries
+ /// @{
+
+ fltCategory getCategory() const { return category; }
+ const fltSemantics &getSemantics() const { return *semantics; }
+ bool isNonZero() const { return category != fcZero; }
+ bool isFiniteNonZero() const { return isFinite() && !isZero(); }
+ bool isPosZero() const { return isZero() && !isNegative(); }
+ bool isNegZero() const { return isZero() && isNegative(); }
+
+ /// Returns true if and only if the number has the smallest possible non-zero
+ /// magnitude in the current semantics.
+ bool isSmallest() const;
+
+ /// Returns true if and only if the number has the largest possible finite
+ /// magnitude in the current semantics.
+ bool isLargest() const;
+
+ /// Returns true if and only if the number is an exact integer.
+ bool isInteger() const;
+
+ /// @}
+
+ IEEEFloat &operator=(const IEEEFloat &);
+ IEEEFloat &operator=(IEEEFloat &&);
+
+ /// Overload to compute a hash code for an APFloat value.
+ ///
+ /// Note that the use of hash codes for floating point values is in general
+ /// frought with peril. Equality is hard to define for these values. For
+ /// example, should negative and positive zero hash to different codes? Are
+ /// they equal or not? This hash value implementation specifically
+ /// emphasizes producing different codes for different inputs in order to
+ /// be used in canonicalization and memoization. As such, equality is
+ /// bitwiseIsEqual, and 0 != -0.
+ friend hash_code hash_value(const IEEEFloat &Arg);
+
+ /// Converts this value into a decimal string.
+ ///
+ /// \param FormatPrecision The maximum number of digits of
+ /// precision to output. If there are fewer digits available,
+ /// zero padding will not be used unless the value is
+ /// integral and small enough to be expressed in
+ /// FormatPrecision digits. 0 means to use the natural
+ /// precision of the number.
+ /// \param FormatMaxPadding The maximum number of zeros to
+ /// consider inserting before falling back to scientific
+ /// notation. 0 means to always use scientific notation.
+ ///
+ /// \param TruncateZero Indicate whether to remove the trailing zero in
+ /// fraction part or not. Also setting this parameter to false forcing
+ /// producing of output more similar to default printf behavior.
+ /// Specifically the lower e is used as exponent delimiter and exponent
+ /// always contains no less than two digits.
+ ///
+ /// Number Precision MaxPadding Result
+ /// ------ --------- ---------- ------
+ /// 1.01E+4 5 2 10100
+ /// 1.01E+4 4 2 1.01E+4
+ /// 1.01E+4 5 1 1.01E+4
+ /// 1.01E-2 5 2 0.0101
+ /// 1.01E-2 4 2 0.0101
+ /// 1.01E-2 4 1 1.01E-2
+ void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
+ unsigned FormatMaxPadding = 3, bool TruncateZero = true) const;
+
+ /// If this value has an exact multiplicative inverse, store it in inv and
+ /// return true.
+ bool getExactInverse(APFloat *inv) const;
+
+ /// Returns the exponent of the internal representation of the APFloat.
+ ///
+ /// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)).
+ /// For special APFloat values, this returns special error codes:
+ ///
+ /// NaN -> \c IEK_NaN
+ /// 0 -> \c IEK_Zero
+ /// Inf -> \c IEK_Inf
+ ///
+ friend int ilogb(const IEEEFloat &Arg);
+
+ /// Returns: X * 2^Exp for integral exponents.
+ friend IEEEFloat scalbn(IEEEFloat X, int Exp, roundingMode);
+
+ friend IEEEFloat frexp(const IEEEFloat &X, int &Exp, roundingMode);
+
+ /// \name Special value setters.
+ /// @{
+
+ void makeLargest(bool Neg = false);
+ void makeSmallest(bool Neg = false);
+ void makeNaN(bool SNaN = false, bool Neg = false,
+ const APInt *fill = nullptr);
+ void makeInf(bool Neg = false);
+ void makeZero(bool Neg = false);
+ void makeQuiet();
+
+ /// Returns the smallest (by magnitude) normalized finite number in the given
+ /// semantics.
+ ///
+ /// \param Negative - True iff the number should be negative
+ void makeSmallestNormalized(bool Negative = false);
+
+ /// @}
+
+ cmpResult compareAbsoluteValue(const IEEEFloat &) const;
+
+private:
+ /// \name Simple Queries
+ /// @{
+
+ integerPart *significandParts();
+ const integerPart *significandParts() const;
+ unsigned int partCount() const;
+
+ /// @}
+
+ /// \name Significand operations.
+ /// @{
+
+ integerPart addSignificand(const IEEEFloat &);
+ integerPart subtractSignificand(const IEEEFloat &, integerPart);
+ lostFraction addOrSubtractSignificand(const IEEEFloat &, bool subtract);
+ lostFraction multiplySignificand(const IEEEFloat &, const IEEEFloat *);
+ lostFraction divideSignificand(const IEEEFloat &);
+ void incrementSignificand();
+ void initialize(const fltSemantics *);
+ void shiftSignificandLeft(unsigned int);
+ lostFraction shiftSignificandRight(unsigned int);
+ unsigned int significandLSB() const;
+ unsigned int significandMSB() const;
+ void zeroSignificand();
+ /// Return true if the significand excluding the integral bit is all ones.
+ bool isSignificandAllOnes() const;
+ /// Return true if the significand excluding the integral bit is all zeros.
+ bool isSignificandAllZeros() const;
+
+ /// @}
+
+ /// \name Arithmetic on special values.
+ /// @{
+
+ opStatus addOrSubtractSpecials(const IEEEFloat &, bool subtract);
+ opStatus divideSpecials(const IEEEFloat &);
+ opStatus multiplySpecials(const IEEEFloat &);
+ opStatus modSpecials(const IEEEFloat &);
+
+ /// @}
+
+ /// \name Miscellany
+ /// @{
+
+ bool convertFromStringSpecials(StringRef str);
+ opStatus normalize(roundingMode, lostFraction);
+ opStatus addOrSubtract(const IEEEFloat &, roundingMode, bool subtract);
+ opStatus handleOverflow(roundingMode);
+ bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const;
+ opStatus convertToSignExtendedInteger(MutableArrayRef<integerPart>,
+ unsigned int, bool, roundingMode,
+ bool *) const;
+ opStatus convertFromUnsignedParts(const integerPart *, unsigned int,
+ roundingMode);
+ opStatus convertFromHexadecimalString(StringRef, roundingMode);
+ opStatus convertFromDecimalString(StringRef, roundingMode);
+ char *convertNormalToHexString(char *, unsigned int, bool,
+ roundingMode) const;
+ opStatus roundSignificandWithExponent(const integerPart *, unsigned int, int,
+ roundingMode);
+
+ /// @}
+
+ APInt convertHalfAPFloatToAPInt() const;
+ APInt convertFloatAPFloatToAPInt() const;
+ APInt convertDoubleAPFloatToAPInt() const;
+ APInt convertQuadrupleAPFloatToAPInt() const;
+ APInt convertF80LongDoubleAPFloatToAPInt() const;
+ APInt convertPPCDoubleDoubleAPFloatToAPInt() const;
+ void initFromAPInt(const fltSemantics *Sem, const APInt &api);
+ void initFromHalfAPInt(const APInt &api);
+ void initFromFloatAPInt(const APInt &api);
+ void initFromDoubleAPInt(const APInt &api);
+ void initFromQuadrupleAPInt(const APInt &api);
+ void initFromF80LongDoubleAPInt(const APInt &api);
+ void initFromPPCDoubleDoubleAPInt(const APInt &api);
+
+ void assign(const IEEEFloat &);
+ void copySignificand(const IEEEFloat &);
+ void freeSignificand();
+
+ /// Note: this must be the first data member.
+ /// The semantics that this value obeys.
+ const fltSemantics *semantics;
+
+ /// A binary fraction with an explicit integer bit.
+ ///
+ /// The significand must be at least one bit wider than the target precision.
+ union Significand {
+ integerPart part;
+ integerPart *parts;
+ } significand;
+
+ /// The signed unbiased exponent of the value.
+ ExponentType exponent;
+
+ /// What kind of floating point number this is.
+ ///
+ /// Only 2 bits are required, but VisualStudio incorrectly sign extends it.
+ /// Using the extra bit keeps it from failing under VisualStudio.
+ fltCategory category : 3;
+
+ /// Sign bit of the number.
+ unsigned int sign : 1;
+};
+
+hash_code hash_value(const IEEEFloat &Arg);
+int ilogb(const IEEEFloat &Arg);
+IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode);
+IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM);
+
+// This mode implements more precise float in terms of two APFloats.
+// The interface and layout is designed for arbitray underlying semantics,
+// though currently only PPCDoubleDouble semantics are supported, whose
+// corresponding underlying semantics are IEEEdouble.
+class DoubleAPFloat final : public APFloatBase {
+ // Note: this must be the first data member.
+ const fltSemantics *Semantics;
+ std::unique_ptr<APFloat[]> Floats;
+
+ opStatus addImpl(const APFloat &a, const APFloat &aa, const APFloat &c,
+ const APFloat &cc, roundingMode RM);
+
+ opStatus addWithSpecial(const DoubleAPFloat &LHS, const DoubleAPFloat &RHS,
+ DoubleAPFloat &Out, roundingMode RM);
+
+public:
+ DoubleAPFloat(const fltSemantics &S);
+ DoubleAPFloat(const fltSemantics &S, uninitializedTag);
+ DoubleAPFloat(const fltSemantics &S, integerPart);
+ DoubleAPFloat(const fltSemantics &S, const APInt &I);
+ DoubleAPFloat(const fltSemantics &S, APFloat &&First, APFloat &&Second);
+ DoubleAPFloat(const DoubleAPFloat &RHS);
+ DoubleAPFloat(DoubleAPFloat &&RHS);
+
+ DoubleAPFloat &operator=(const DoubleAPFloat &RHS);
+
+ DoubleAPFloat &operator=(DoubleAPFloat &&RHS) {
+ if (this != &RHS) {
+ this->~DoubleAPFloat();
+ new (this) DoubleAPFloat(std::move(RHS));
+ }
+ return *this;
+ }
+
+ bool needsCleanup() const { return Floats != nullptr; }
+
+ APFloat &getFirst() { return Floats[0]; }
+ const APFloat &getFirst() const { return Floats[0]; }
+ APFloat &getSecond() { return Floats[1]; }
+ const APFloat &getSecond() const { return Floats[1]; }
+
+ opStatus add(const DoubleAPFloat &RHS, roundingMode RM);
+ opStatus subtract(const DoubleAPFloat &RHS, roundingMode RM);
+ opStatus multiply(const DoubleAPFloat &RHS, roundingMode RM);
+ opStatus divide(const DoubleAPFloat &RHS, roundingMode RM);
+ opStatus remainder(const DoubleAPFloat &RHS);
+ opStatus mod(const DoubleAPFloat &RHS);
+ opStatus fusedMultiplyAdd(const DoubleAPFloat &Multiplicand,
+ const DoubleAPFloat &Addend, roundingMode RM);
+ opStatus roundToIntegral(roundingMode RM);
+ void changeSign();
+ cmpResult compareAbsoluteValue(const DoubleAPFloat &RHS) const;
+
+ fltCategory getCategory() const;
+ bool isNegative() const;
+
+ void makeInf(bool Neg);
+ void makeZero(bool Neg);
+ void makeLargest(bool Neg);
+ void makeSmallest(bool Neg);
+ void makeSmallestNormalized(bool Neg);
+ void makeNaN(bool SNaN, bool Neg, const APInt *fill);
+
+ cmpResult compare(const DoubleAPFloat &RHS) const;
+ bool bitwiseIsEqual(const DoubleAPFloat &RHS) const;
+ APInt bitcastToAPInt() const;
+ opStatus convertFromString(StringRef, roundingMode);
+ opStatus next(bool nextDown);
+
+ opStatus convertToInteger(MutableArrayRef<integerPart> Input,
+ unsigned int Width, bool IsSigned, roundingMode RM,
+ bool *IsExact) const;
+ opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM);
+ opStatus convertFromSignExtendedInteger(const integerPart *Input,
+ unsigned int InputSize, bool IsSigned,
+ roundingMode RM);
+ opStatus convertFromZeroExtendedInteger(const integerPart *Input,
+ unsigned int InputSize, bool IsSigned,
+ roundingMode RM);
+ unsigned int convertToHexString(char *DST, unsigned int HexDigits,
+ bool UpperCase, roundingMode RM) const;
+
+ bool isDenormal() const;
+ bool isSmallest() const;
+ bool isLargest() const;
+ bool isInteger() const;
+
+ void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
+ unsigned FormatMaxPadding, bool TruncateZero = true) const;
+
+ bool getExactInverse(APFloat *inv) const;
+
+ friend int ilogb(const DoubleAPFloat &Arg);
+ friend DoubleAPFloat scalbn(DoubleAPFloat X, int Exp, roundingMode);
+ friend DoubleAPFloat frexp(const DoubleAPFloat &X, int &Exp, roundingMode);
+ friend hash_code hash_value(const DoubleAPFloat &Arg);
+};
+
+hash_code hash_value(const DoubleAPFloat &Arg);
+
+} // End detail namespace
+
+// This is a interface class that is currently forwarding functionalities from
+// detail::IEEEFloat.
+class APFloat : public APFloatBase {
+ typedef detail::IEEEFloat IEEEFloat;
+ typedef detail::DoubleAPFloat DoubleAPFloat;
+
+ static_assert(std::is_standard_layout<IEEEFloat>::value, "");
+
+ union Storage {
+ const fltSemantics *semantics;
+ IEEEFloat IEEE;
+ DoubleAPFloat Double;
+
+ explicit Storage(IEEEFloat F, const fltSemantics &S);
+ explicit Storage(DoubleAPFloat F, const fltSemantics &S)
+ : Double(std::move(F)) {
+ assert(&S == &PPCDoubleDouble());
+ }
+
+ template <typename... ArgTypes>
+ Storage(const fltSemantics &Semantics, ArgTypes &&... Args) {
+ if (usesLayout<IEEEFloat>(Semantics)) {
+ new (&IEEE) IEEEFloat(Semantics, std::forward<ArgTypes>(Args)...);
+ return;
+ }
+ if (usesLayout<DoubleAPFloat>(Semantics)) {
+ new (&Double) DoubleAPFloat(Semantics, std::forward<ArgTypes>(Args)...);
+ return;
+ }
+ llvm_unreachable("Unexpected semantics");
+ }
+
+ ~Storage() {
+ if (usesLayout<IEEEFloat>(*semantics)) {
+ IEEE.~IEEEFloat();
+ return;
+ }
+ if (usesLayout<DoubleAPFloat>(*semantics)) {
+ Double.~DoubleAPFloat();
+ return;
+ }
+ llvm_unreachable("Unexpected semantics");
+ }
+
+ Storage(const Storage &RHS) {
+ if (usesLayout<IEEEFloat>(*RHS.semantics)) {
+ new (this) IEEEFloat(RHS.IEEE);
+ return;
+ }
+ if (usesLayout<DoubleAPFloat>(*RHS.semantics)) {
+ new (this) DoubleAPFloat(RHS.Double);
+ return;
+ }
+ llvm_unreachable("Unexpected semantics");
+ }
+
+ Storage(Storage &&RHS) {
+ if (usesLayout<IEEEFloat>(*RHS.semantics)) {
+ new (this) IEEEFloat(std::move(RHS.IEEE));
+ return;
+ }
+ if (usesLayout<DoubleAPFloat>(*RHS.semantics)) {
+ new (this) DoubleAPFloat(std::move(RHS.Double));
+ return;
+ }
+ llvm_unreachable("Unexpected semantics");
+ }
+
+ Storage &operator=(const Storage &RHS) {
+ if (usesLayout<IEEEFloat>(*semantics) &&
+ usesLayout<IEEEFloat>(*RHS.semantics)) {
+ IEEE = RHS.IEEE;
+ } else if (usesLayout<DoubleAPFloat>(*semantics) &&
+ usesLayout<DoubleAPFloat>(*RHS.semantics)) {
+ Double = RHS.Double;
+ } else if (this != &RHS) {
+ this->~Storage();
+ new (this) Storage(RHS);
+ }
+ return *this;
+ }
+
+ Storage &operator=(Storage &&RHS) {
+ if (usesLayout<IEEEFloat>(*semantics) &&
+ usesLayout<IEEEFloat>(*RHS.semantics)) {
+ IEEE = std::move(RHS.IEEE);
+ } else if (usesLayout<DoubleAPFloat>(*semantics) &&
+ usesLayout<DoubleAPFloat>(*RHS.semantics)) {
+ Double = std::move(RHS.Double);
+ } else if (this != &RHS) {
+ this->~Storage();
+ new (this) Storage(std::move(RHS));
+ }
+ return *this;
+ }
+ } U;
+
+ template <typename T> static bool usesLayout(const fltSemantics &Semantics) {
+ static_assert(std::is_same<T, IEEEFloat>::value ||
+ std::is_same<T, DoubleAPFloat>::value, "");
+ if (std::is_same<T, DoubleAPFloat>::value) {
+ return &Semantics == &PPCDoubleDouble();
+ }
+ return &Semantics != &PPCDoubleDouble();
+ }
+
+ IEEEFloat &getIEEE() {
+ if (usesLayout<IEEEFloat>(*U.semantics))
+ return U.IEEE;
+ if (usesLayout<DoubleAPFloat>(*U.semantics))
+ return U.Double.getFirst().U.IEEE;
+ llvm_unreachable("Unexpected semantics");
+ }
+
+ const IEEEFloat &getIEEE() const {
+ if (usesLayout<IEEEFloat>(*U.semantics))
+ return U.IEEE;
+ if (usesLayout<DoubleAPFloat>(*U.semantics))
+ return U.Double.getFirst().U.IEEE;
+ llvm_unreachable("Unexpected semantics");
+ }
+
+ void makeZero(bool Neg) { APFLOAT_DISPATCH_ON_SEMANTICS(makeZero(Neg)); }
+
+ void makeInf(bool Neg) { APFLOAT_DISPATCH_ON_SEMANTICS(makeInf(Neg)); }
+
+ void makeNaN(bool SNaN, bool Neg, const APInt *fill) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(makeNaN(SNaN, Neg, fill));
+ }
+
+ void makeLargest(bool Neg) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(makeLargest(Neg));
+ }
+
+ void makeSmallest(bool Neg) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(makeSmallest(Neg));
+ }
+
+ void makeSmallestNormalized(bool Neg) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(makeSmallestNormalized(Neg));
+ }
+
+ // FIXME: This is due to clang 3.3 (or older version) always checks for the
+ // default constructor in an array aggregate initialization, even if no
+ // elements in the array is default initialized.
+ APFloat() : U(IEEEdouble()) {
+ llvm_unreachable("This is a workaround for old clang.");
+ }
+
+ explicit APFloat(IEEEFloat F, const fltSemantics &S) : U(std::move(F), S) {}
+ explicit APFloat(DoubleAPFloat F, const fltSemantics &S)
+ : U(std::move(F), S) {}
+
+ cmpResult compareAbsoluteValue(const APFloat &RHS) const {
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only compare APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.compareAbsoluteValue(RHS.U.IEEE);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.compareAbsoluteValue(RHS.U.Double);
+ llvm_unreachable("Unexpected semantics");
+ }
+
+public:
+ APFloat(const fltSemantics &Semantics) : U(Semantics) {}
+ APFloat(const fltSemantics &Semantics, StringRef S);
+ APFloat(const fltSemantics &Semantics, integerPart I) : U(Semantics, I) {}
+ // TODO: Remove this constructor. This isn't faster than the first one.
+ APFloat(const fltSemantics &Semantics, uninitializedTag)
+ : U(Semantics, uninitialized) {}
+ APFloat(const fltSemantics &Semantics, const APInt &I) : U(Semantics, I) {}
+ explicit APFloat(double d) : U(IEEEFloat(d), IEEEdouble()) {}
+ explicit APFloat(float f) : U(IEEEFloat(f), IEEEsingle()) {}
+ APFloat(const APFloat &RHS) = default;
+ APFloat(APFloat &&RHS) = default;
+
+ ~APFloat() = default;
+
+ bool needsCleanup() const { APFLOAT_DISPATCH_ON_SEMANTICS(needsCleanup()); }
+
+ /// Factory for Positive and Negative Zero.
+ ///
+ /// \param Negative True iff the number should be negative.
+ static APFloat getZero(const fltSemantics &Sem, bool Negative = false) {
+ APFloat Val(Sem, uninitialized);
+ Val.makeZero(Negative);
+ return Val;
+ }
+
+ /// Factory for Positive and Negative Infinity.
+ ///
+ /// \param Negative True iff the number should be negative.
+ static APFloat getInf(const fltSemantics &Sem, bool Negative = false) {
+ APFloat Val(Sem, uninitialized);
+ Val.makeInf(Negative);
+ return Val;
+ }
+
+ /// Factory for NaN values.
+ ///
+ /// \param Negative - True iff the NaN generated should be negative.
+ /// \param payload - The unspecified fill bits for creating the NaN, 0 by
+ /// default. The value is truncated as necessary.
+ static APFloat getNaN(const fltSemantics &Sem, bool Negative = false,
+ uint64_t payload = 0) {
+ if (payload) {
+ APInt intPayload(64, payload);
+ return getQNaN(Sem, Negative, &intPayload);
+ } else {
+ return getQNaN(Sem, Negative, nullptr);
+ }
+ }
+
+ /// Factory for QNaN values.
+ static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false,
+ const APInt *payload = nullptr) {
+ APFloat Val(Sem, uninitialized);
+ Val.makeNaN(false, Negative, payload);
+ return Val;
+ }
+
+ /// Factory for SNaN values.
+ static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false,
+ const APInt *payload = nullptr) {
+ APFloat Val(Sem, uninitialized);
+ Val.makeNaN(true, Negative, payload);
+ return Val;
+ }
+
+ /// Returns the largest finite number in the given semantics.
+ ///
+ /// \param Negative - True iff the number should be negative
+ static APFloat getLargest(const fltSemantics &Sem, bool Negative = false) {
+ APFloat Val(Sem, uninitialized);
+ Val.makeLargest(Negative);
+ return Val;
+ }
+
+ /// Returns the smallest (by magnitude) finite number in the given semantics.
+ /// Might be denormalized, which implies a relative loss of precision.
+ ///
+ /// \param Negative - True iff the number should be negative
+ static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false) {
+ APFloat Val(Sem, uninitialized);
+ Val.makeSmallest(Negative);
+ return Val;
+ }
+
+ /// Returns the smallest (by magnitude) normalized finite number in the given
+ /// semantics.
+ ///
+ /// \param Negative - True iff the number should be negative
+ static APFloat getSmallestNormalized(const fltSemantics &Sem,
+ bool Negative = false) {
+ APFloat Val(Sem, uninitialized);
+ Val.makeSmallestNormalized(Negative);
+ return Val;
+ }
+
+ /// Returns a float which is bitcasted from an all one value int.
+ ///
+ /// \param BitWidth - Select float type
+ /// \param isIEEE - If 128 bit number, select between PPC and IEEE
+ static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
+
+ /// Used to insert APFloat objects, or objects that contain APFloat objects,
+ /// into FoldingSets.
+ void Profile(FoldingSetNodeID &NID) const;
+
+ opStatus add(const APFloat &RHS, roundingMode RM) {
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.add(RHS.U.IEEE, RM);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.add(RHS.U.Double, RM);
+ llvm_unreachable("Unexpected semantics");
+ }
+ opStatus subtract(const APFloat &RHS, roundingMode RM) {
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.subtract(RHS.U.IEEE, RM);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.subtract(RHS.U.Double, RM);
+ llvm_unreachable("Unexpected semantics");
+ }
+ opStatus multiply(const APFloat &RHS, roundingMode RM) {
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.multiply(RHS.U.IEEE, RM);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.multiply(RHS.U.Double, RM);
+ llvm_unreachable("Unexpected semantics");
+ }
+ opStatus divide(const APFloat &RHS, roundingMode RM) {
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.divide(RHS.U.IEEE, RM);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.divide(RHS.U.Double, RM);
+ llvm_unreachable("Unexpected semantics");
+ }
+ opStatus remainder(const APFloat &RHS) {
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.remainder(RHS.U.IEEE);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.remainder(RHS.U.Double);
+ llvm_unreachable("Unexpected semantics");
+ }
+ opStatus mod(const APFloat &RHS) {
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.mod(RHS.U.IEEE);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.mod(RHS.U.Double);
+ llvm_unreachable("Unexpected semantics");
+ }
+ opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend,
+ roundingMode RM) {
+ assert(&getSemantics() == &Multiplicand.getSemantics() &&
+ "Should only call on APFloats with the same semantics");
+ assert(&getSemantics() == &Addend.getSemantics() &&
+ "Should only call on APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.fusedMultiplyAdd(Multiplicand.U.IEEE, Addend.U.IEEE, RM);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.fusedMultiplyAdd(Multiplicand.U.Double, Addend.U.Double,
+ RM);
+ llvm_unreachable("Unexpected semantics");
+ }
+ opStatus roundToIntegral(roundingMode RM) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(roundToIntegral(RM));
+ }
+
+ // TODO: bool parameters are not readable and a source of bugs.
+ // Do something.
+ opStatus next(bool nextDown) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(next(nextDown));
+ }
+
+ /// Add two APFloats, rounding ties to the nearest even.
+ /// No error checking.
+ APFloat operator+(const APFloat &RHS) const {
+ APFloat Result(*this);
+ (void)Result.add(RHS, rmNearestTiesToEven);
+ return Result;
+ }
+
+ /// Subtract two APFloats, rounding ties to the nearest even.
+ /// No error checking.
+ APFloat operator-(const APFloat &RHS) const {
+ APFloat Result(*this);
+ (void)Result.subtract(RHS, rmNearestTiesToEven);
+ return Result;
+ }
+
+ /// Multiply two APFloats, rounding ties to the nearest even.
+ /// No error checking.
+ APFloat operator*(const APFloat &RHS) const {
+ APFloat Result(*this);
+ (void)Result.multiply(RHS, rmNearestTiesToEven);
+ return Result;
+ }
+
+ /// Divide the first APFloat by the second, rounding ties to the nearest even.
+ /// No error checking.
+ APFloat operator/(const APFloat &RHS) const {
+ APFloat Result(*this);
+ (void)Result.divide(RHS, rmNearestTiesToEven);
+ return Result;
+ }
+
+ void changeSign() { APFLOAT_DISPATCH_ON_SEMANTICS(changeSign()); }
+ void clearSign() {
+ if (isNegative())
+ changeSign();
+ }
+ void copySign(const APFloat &RHS) {
+ if (isNegative() != RHS.isNegative())
+ changeSign();
+ }
+
+ /// A static helper to produce a copy of an APFloat value with its sign
+ /// copied from some other APFloat.
+ static APFloat copySign(APFloat Value, const APFloat &Sign) {
+ Value.copySign(Sign);
+ return Value;
+ }
+
+ opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
+ bool *losesInfo);
+ opStatus convertToInteger(MutableArrayRef<integerPart> Input,
+ unsigned int Width, bool IsSigned, roundingMode RM,
+ bool *IsExact) const {
+ APFLOAT_DISPATCH_ON_SEMANTICS(
+ convertToInteger(Input, Width, IsSigned, RM, IsExact));
+ }
+ opStatus convertToInteger(APSInt &Result, roundingMode RM,
+ bool *IsExact) const;
+ opStatus convertFromAPInt(const APInt &Input, bool IsSigned,
+ roundingMode RM) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(convertFromAPInt(Input, IsSigned, RM));
+ }
+ opStatus convertFromSignExtendedInteger(const integerPart *Input,
+ unsigned int InputSize, bool IsSigned,
+ roundingMode RM) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(
+ convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM));
+ }
+ opStatus convertFromZeroExtendedInteger(const integerPart *Input,
+ unsigned int InputSize, bool IsSigned,
+ roundingMode RM) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(
+ convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM));
+ }
+ opStatus convertFromString(StringRef, roundingMode);
+ APInt bitcastToAPInt() const {
+ APFLOAT_DISPATCH_ON_SEMANTICS(bitcastToAPInt());
+ }
+ double convertToDouble() const { return getIEEE().convertToDouble(); }
+ float convertToFloat() const { return getIEEE().convertToFloat(); }
+
+ bool operator==(const APFloat &) const = delete;
+
+ cmpResult compare(const APFloat &RHS) const {
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only compare APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.compare(RHS.U.IEEE);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.compare(RHS.U.Double);
+ llvm_unreachable("Unexpected semantics");
+ }
+
+ bool bitwiseIsEqual(const APFloat &RHS) const {
+ if (&getSemantics() != &RHS.getSemantics())
+ return false;
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.bitwiseIsEqual(RHS.U.IEEE);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.bitwiseIsEqual(RHS.U.Double);
+ llvm_unreachable("Unexpected semantics");
+ }
+
+ /// We don't rely on operator== working on double values, as
+ /// it returns true for things that are clearly not equal, like -0.0 and 0.0.
+ /// As such, this method can be used to do an exact bit-for-bit comparison of
+ /// two floating point values.
+ ///
+ /// We leave the version with the double argument here because it's just so
+ /// convenient to write "2.0" and the like. Without this function we'd
+ /// have to duplicate its logic everywhere it's called.
+ bool isExactlyValue(double V) const {
+ bool ignored;
+ APFloat Tmp(V);
+ Tmp.convert(getSemantics(), APFloat::rmNearestTiesToEven, &ignored);
+ return bitwiseIsEqual(Tmp);
+ }
+
+ unsigned int convertToHexString(char *DST, unsigned int HexDigits,
+ bool UpperCase, roundingMode RM) const {
+ APFLOAT_DISPATCH_ON_SEMANTICS(
+ convertToHexString(DST, HexDigits, UpperCase, RM));
+ }
+
+ bool isZero() const { return getCategory() == fcZero; }
+ bool isInfinity() const { return getCategory() == fcInfinity; }
+ bool isNaN() const { return getCategory() == fcNaN; }
+
+ bool isNegative() const { return getIEEE().isNegative(); }
+ bool isDenormal() const { APFLOAT_DISPATCH_ON_SEMANTICS(isDenormal()); }
+ bool isSignaling() const { return getIEEE().isSignaling(); }
+
+ bool isNormal() const { return !isDenormal() && isFiniteNonZero(); }
+ bool isFinite() const { return !isNaN() && !isInfinity(); }
+
+ fltCategory getCategory() const { return getIEEE().getCategory(); }
+ const fltSemantics &getSemantics() const { return *U.semantics; }
+ bool isNonZero() const { return !isZero(); }
+ bool isFiniteNonZero() const { return isFinite() && !isZero(); }
+ bool isPosZero() const { return isZero() && !isNegative(); }
+ bool isNegZero() const { return isZero() && isNegative(); }
+ bool isSmallest() const { APFLOAT_DISPATCH_ON_SEMANTICS(isSmallest()); }
+ bool isLargest() const { APFLOAT_DISPATCH_ON_SEMANTICS(isLargest()); }
+ bool isInteger() const { APFLOAT_DISPATCH_ON_SEMANTICS(isInteger()); }
+
+ APFloat &operator=(const APFloat &RHS) = default;
+ APFloat &operator=(APFloat &&RHS) = default;
+
+ void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
+ unsigned FormatMaxPadding = 3, bool TruncateZero = true) const {
+ APFLOAT_DISPATCH_ON_SEMANTICS(
+ toString(Str, FormatPrecision, FormatMaxPadding, TruncateZero));
+ }
+
+ void print(raw_ostream &) const;
+ void dump() const;
+
+ bool getExactInverse(APFloat *inv) const {
+ APFLOAT_DISPATCH_ON_SEMANTICS(getExactInverse(inv));
+ }
+
+ friend hash_code hash_value(const APFloat &Arg);
+ friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); }
+ friend APFloat scalbn(APFloat X, int Exp, roundingMode RM);
+ friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
+ friend IEEEFloat;
+ friend DoubleAPFloat;
+};
+
+/// See friend declarations above.
+///
+/// These additional declarations are required in order to compile LLVM with IBM
+/// xlC compiler.
+hash_code hash_value(const APFloat &Arg);
+inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) {
+ if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics()))
+ return APFloat(scalbn(X.U.IEEE, Exp, RM), X.getSemantics());
+ if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics()))
+ return APFloat(scalbn(X.U.Double, Exp, RM), X.getSemantics());
+ llvm_unreachable("Unexpected semantics");
+}
+
+/// Equivalent of C standard library function.
+///
+/// While the C standard says Exp is an unspecified value for infinity and nan,
+/// this returns INT_MAX for infinities, and INT_MIN for NaNs.
+inline APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM) {
+ if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics()))
+ return APFloat(frexp(X.U.IEEE, Exp, RM), X.getSemantics());
+ if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics()))
+ return APFloat(frexp(X.U.Double, Exp, RM), X.getSemantics());
+ llvm_unreachable("Unexpected semantics");
+}
+/// Returns the absolute value of the argument.
+inline APFloat abs(APFloat X) {
+ X.clearSign();
+ return X;
+}
+
+/// Returns the negated value of the argument.
+inline APFloat neg(APFloat X) {
+ X.changeSign();
+ return X;
+}
+
+/// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if
+/// both are not NaN. If either argument is a NaN, returns the other argument.
+LLVM_READONLY
+inline APFloat minnum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return B;
+ if (B.isNaN())
+ return A;
+ return (B.compare(A) == APFloat::cmpLessThan) ? B : A;
+}
+
+/// Implements IEEE maxNum semantics. Returns the larger of the 2 arguments if
+/// both are not NaN. If either argument is a NaN, returns the other argument.
+LLVM_READONLY
+inline APFloat maxnum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return B;
+ if (B.isNaN())
+ return A;
+ return (A.compare(B) == APFloat::cmpLessThan) ? B : A;
+}
+
+/// Implements IEEE 754-2018 minimum semantics. Returns the smaller of 2
+/// arguments, propagating NaNs and treating -0 as less than +0.
+LLVM_READONLY
+inline APFloat minimum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return A;
+ if (B.isNaN())
+ return B;
+ if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
+ return A.isNegative() ? A : B;
+ return (B.compare(A) == APFloat::cmpLessThan) ? B : A;
+}
+
+/// Implements IEEE 754-2018 maximum semantics. Returns the larger of 2
+/// arguments, propagating NaNs and treating -0 as less than +0.
+LLVM_READONLY
+inline APFloat maximum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return A;
+ if (B.isNaN())
+ return B;
+ if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
+ return A.isNegative() ? B : A;
+ return (A.compare(B) == APFloat::cmpLessThan) ? B : A;
+}
+
+} // namespace llvm
+
+#undef APFLOAT_DISPATCH_ON_SEMANTICS
+#endif // LLVM_ADT_APFLOAT_H
diff --git a/third_party/llvm-project/include/llvm/ADT/APInt.h b/third_party/llvm-project/include/llvm/ADT/APInt.h
new file mode 100644
index 000000000..60a0db7e9
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/APInt.h
@@ -0,0 +1,2258 @@
+//===-- llvm/ADT/APInt.h - For Arbitrary Precision Integer -----*- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements a class to represent arbitrary precision
+/// integral constant values and operations on them.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_APINT_H
+#define LLVM_ADT_APINT_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <climits>
+#include <cstring>
+#include <string>
+
+namespace llvm {
+class FoldingSetNodeID;
+class StringRef;
+class hash_code;
+class raw_ostream;
+
+template <typename T> class SmallVectorImpl;
+template <typename T> class ArrayRef;
+template <typename T> class Optional;
+
+class APInt;
+
+inline APInt operator-(APInt);
+
+//===----------------------------------------------------------------------===//
+// APInt Class
+//===----------------------------------------------------------------------===//
+
+/// Class for arbitrary precision integers.
+///
+/// APInt is a functional replacement for common case unsigned integer type like
+/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width
+/// integer sizes and large integer value types such as 3-bits, 15-bits, or more
+/// than 64-bits of precision. APInt provides a variety of arithmetic operators
+/// and methods to manipulate integer values of any bit-width. It supports both
+/// the typical integer arithmetic and comparison operations as well as bitwise
+/// manipulation.
+///
+/// The class has several invariants worth noting:
+/// * All bit, byte, and word positions are zero-based.
+/// * Once the bit width is set, it doesn't change except by the Truncate,
+/// SignExtend, or ZeroExtend operations.
+/// * All binary operators must be on APInt instances of the same bit width.
+/// Attempting to use these operators on instances with different bit
+/// widths will yield an assertion.
+/// * The value is stored canonically as an unsigned value. For operations
+/// where it makes a difference, there are both signed and unsigned variants
+/// of the operation. For example, sdiv and udiv. However, because the bit
+/// widths must be the same, operations such as Mul and Add produce the same
+/// results regardless of whether the values are interpreted as signed or
+/// not.
+/// * In general, the class tries to follow the style of computation that LLVM
+/// uses in its IR. This simplifies its use for LLVM.
+///
+class LLVM_NODISCARD APInt {
+public:
+ typedef uint64_t WordType;
+
+ /// This enum is used to hold the constants we needed for APInt.
+ enum : unsigned {
+ /// Byte size of a word.
+ APINT_WORD_SIZE = sizeof(WordType),
+ /// Bits in a word.
+ APINT_BITS_PER_WORD = APINT_WORD_SIZE * CHAR_BIT
+ };
+
+ enum class Rounding {
+ DOWN,
+ TOWARD_ZERO,
+ UP,
+ };
+
+ static const WordType WORDTYPE_MAX = ~WordType(0);
+
+private:
+ /// This union is used to store the integer value. When the
+ /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal.
+ union {
+ uint64_t VAL; ///< Used to store the <= 64 bits integer value.
+ uint64_t *pVal; ///< Used to store the >64 bits integer value.
+ } U;
+
+ unsigned BitWidth; ///< The number of bits in this APInt.
+
+ friend struct DenseMapAPIntKeyInfo;
+
+ friend class APSInt;
+
+ /// Fast internal constructor
+ ///
+ /// This constructor is used only internally for speed of construction of
+ /// temporaries. It is unsafe for general use so it is not public.
+ APInt(uint64_t *val, unsigned bits) : BitWidth(bits) {
+ U.pVal = val;
+ }
+
+ /// Determine if this APInt just has one word to store value.
+ ///
+ /// \returns true if the number of bits <= 64, false otherwise.
+ bool isSingleWord() const { return BitWidth <= APINT_BITS_PER_WORD; }
+
+ /// Determine which word a bit is in.
+ ///
+ /// \returns the word position for the specified bit position.
+ static unsigned whichWord(unsigned bitPosition) {
+ return bitPosition / APINT_BITS_PER_WORD;
+ }
+
+ /// Determine which bit in a word a bit is in.
+ ///
+ /// \returns the bit position in a word for the specified bit position
+ /// in the APInt.
+ static unsigned whichBit(unsigned bitPosition) {
+ return bitPosition % APINT_BITS_PER_WORD;
+ }
+
+ /// Get a single bit mask.
+ ///
+ /// \returns a uint64_t with only bit at "whichBit(bitPosition)" set
+ /// This method generates and returns a uint64_t (word) mask for a single
+ /// bit at a specific bit position. This is used to mask the bit in the
+ /// corresponding word.
+ static uint64_t maskBit(unsigned bitPosition) {
+ return 1ULL << whichBit(bitPosition);
+ }
+
+ /// Clear unused high order bits
+ ///
+ /// This method is used internally to clear the top "N" bits in the high order
+ /// word that are not used by the APInt. This is needed after the most
+ /// significant word is assigned a value to ensure that those bits are
+ /// zero'd out.
+ APInt &clearUnusedBits() {
+ // Compute how many bits are used in the final word
+ unsigned WordBits = ((BitWidth-1) % APINT_BITS_PER_WORD) + 1;
+
+ // Mask out the high bits.
+ uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - WordBits);
+ if (isSingleWord())
+ U.VAL &= mask;
+ else
+ U.pVal[getNumWords() - 1] &= mask;
+ return *this;
+ }
+
+ /// Get the word corresponding to a bit position
+ /// \returns the corresponding word for the specified bit position.
+ uint64_t getWord(unsigned bitPosition) const {
+ return isSingleWord() ? U.VAL : U.pVal[whichWord(bitPosition)];
+ }
+
+ /// Utility method to change the bit width of this APInt to new bit width,
+ /// allocating and/or deallocating as necessary. There is no guarantee on the
+ /// value of any bits upon return. Caller should populate the bits after.
+ void reallocate(unsigned NewBitWidth);
+
+ /// Convert a char array into an APInt
+ ///
+ /// \param radix 2, 8, 10, 16, or 36
+ /// Converts a string into a number. The string must be non-empty
+ /// and well-formed as a number of the given base. The bit-width
+ /// must be sufficient to hold the result.
+ ///
+ /// This is used by the constructors that take string arguments.
+ ///
+ /// StringRef::getAsInteger is superficially similar but (1) does
+ /// not assume that the string is well-formed and (2) grows the
+ /// result to hold the input.
+ void fromString(unsigned numBits, StringRef str, uint8_t radix);
+
+ /// An internal division function for dividing APInts.
+ ///
+ /// This is used by the toString method to divide by the radix. It simply
+ /// provides a more convenient form of divide for internal use since KnuthDiv
+ /// has specific constraints on its inputs. If those constraints are not met
+ /// then it provides a simpler form of divide.
+ static void divide(const WordType *LHS, unsigned lhsWords,
+ const WordType *RHS, unsigned rhsWords, WordType *Quotient,
+ WordType *Remainder);
+
+ /// out-of-line slow case for inline constructor
+ void initSlowCase(uint64_t val, bool isSigned);
+
+ /// shared code between two array constructors
+ void initFromArray(ArrayRef<uint64_t> array);
+
+ /// out-of-line slow case for inline copy constructor
+ void initSlowCase(const APInt &that);
+
+ /// out-of-line slow case for shl
+ void shlSlowCase(unsigned ShiftAmt);
+
+ /// out-of-line slow case for lshr.
+ void lshrSlowCase(unsigned ShiftAmt);
+
+ /// out-of-line slow case for ashr.
+ void ashrSlowCase(unsigned ShiftAmt);
+
+ /// out-of-line slow case for operator=
+ void AssignSlowCase(const APInt &RHS);
+
+ /// out-of-line slow case for operator==
+ bool EqualSlowCase(const APInt &RHS) const LLVM_READONLY;
+
+ /// out-of-line slow case for countLeadingZeros
+ unsigned countLeadingZerosSlowCase() const LLVM_READONLY;
+
+ /// out-of-line slow case for countLeadingOnes.
+ unsigned countLeadingOnesSlowCase() const LLVM_READONLY;
+
+ /// out-of-line slow case for countTrailingZeros.
+ unsigned countTrailingZerosSlowCase() const LLVM_READONLY;
+
+ /// out-of-line slow case for countTrailingOnes
+ unsigned countTrailingOnesSlowCase() const LLVM_READONLY;
+
+ /// out-of-line slow case for countPopulation
+ unsigned countPopulationSlowCase() const LLVM_READONLY;
+
+ /// out-of-line slow case for intersects.
+ bool intersectsSlowCase(const APInt &RHS) const LLVM_READONLY;
+
+ /// out-of-line slow case for isSubsetOf.
+ bool isSubsetOfSlowCase(const APInt &RHS) const LLVM_READONLY;
+
+ /// out-of-line slow case for setBits.
+ void setBitsSlowCase(unsigned loBit, unsigned hiBit);
+
+ /// out-of-line slow case for flipAllBits.
+ void flipAllBitsSlowCase();
+
+ /// out-of-line slow case for operator&=.
+ void AndAssignSlowCase(const APInt& RHS);
+
+ /// out-of-line slow case for operator|=.
+ void OrAssignSlowCase(const APInt& RHS);
+
+ /// out-of-line slow case for operator^=.
+ void XorAssignSlowCase(const APInt& RHS);
+
+ /// Unsigned comparison. Returns -1, 0, or 1 if this APInt is less than, equal
+ /// to, or greater than RHS.
+ int compare(const APInt &RHS) const LLVM_READONLY;
+
+ /// Signed comparison. Returns -1, 0, or 1 if this APInt is less than, equal
+ /// to, or greater than RHS.
+ int compareSigned(const APInt &RHS) const LLVM_READONLY;
+
+public:
+ /// \name Constructors
+ /// @{
+
+ /// Create a new APInt of numBits width, initialized as val.
+ ///
+ /// If isSigned is true then val is treated as if it were a signed value
+ /// (i.e. as an int64_t) and the appropriate sign extension to the bit width
+ /// will be done. Otherwise, no sign extension occurs (high order bits beyond
+ /// the range of val are zero filled).
+ ///
+ /// \param numBits the bit width of the constructed APInt
+ /// \param val the initial value of the APInt
+ /// \param isSigned how to treat signedness of val
+ APInt(unsigned numBits, uint64_t val, bool isSigned = false)
+ : BitWidth(numBits) {
+ assert(BitWidth && "bitwidth too small");
+ if (isSingleWord()) {
+ U.VAL = val;
+ clearUnusedBits();
+ } else {
+ initSlowCase(val, isSigned);
+ }
+ }
+
+ /// Construct an APInt of numBits width, initialized as bigVal[].
+ ///
+ /// Note that bigVal.size() can be smaller or larger than the corresponding
+ /// bit width but any extraneous bits will be dropped.
+ ///
+ /// \param numBits the bit width of the constructed APInt
+ /// \param bigVal a sequence of words to form the initial value of the APInt
+ APInt(unsigned numBits, ArrayRef<uint64_t> bigVal);
+
+ /// Equivalent to APInt(numBits, ArrayRef<uint64_t>(bigVal, numWords)), but
+ /// deprecated because this constructor is prone to ambiguity with the
+ /// APInt(unsigned, uint64_t, bool) constructor.
+ ///
+ /// If this overload is ever deleted, care should be taken to prevent calls
+ /// from being incorrectly captured by the APInt(unsigned, uint64_t, bool)
+ /// constructor.
+ APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]);
+
+ /// Construct an APInt from a string representation.
+ ///
+ /// This constructor interprets the string \p str in the given radix. The
+ /// interpretation stops when the first character that is not suitable for the
+ /// radix is encountered, or the end of the string. Acceptable radix values
+ /// are 2, 8, 10, 16, and 36. It is an error for the value implied by the
+ /// string to require more bits than numBits.
+ ///
+ /// \param numBits the bit width of the constructed APInt
+ /// \param str the string to be interpreted
+ /// \param radix the radix to use for the conversion
+ APInt(unsigned numBits, StringRef str, uint8_t radix);
+
+ /// Simply makes *this a copy of that.
+ /// Copy Constructor.
+ APInt(const APInt &that) : BitWidth(that.BitWidth) {
+ if (isSingleWord())
+ U.VAL = that.U.VAL;
+ else
+ initSlowCase(that);
+ }
+
+ /// Move Constructor.
+ APInt(APInt &&that) : BitWidth(that.BitWidth) {
+ memcpy(&U, &that.U, sizeof(U));
+ that.BitWidth = 0;
+ }
+
+ /// Destructor.
+ ~APInt() {
+ if (needsCleanup())
+ delete[] U.pVal;
+ }
+
+ /// Default constructor that creates an uninteresting APInt
+ /// representing a 1-bit zero value.
+ ///
+ /// This is useful for object deserialization (pair this with the static
+ /// method Read).
+ explicit APInt() : BitWidth(1) { U.VAL = 0; }
+
+ /// Returns whether this instance allocated memory.
+ bool needsCleanup() const { return !isSingleWord(); }
+
+ /// Used to insert APInt objects, or objects that contain APInt objects, into
+ /// FoldingSets.
+ void Profile(FoldingSetNodeID &id) const;
+
+ /// @}
+ /// \name Value Tests
+ /// @{
+
+ /// Determine sign of this APInt.
+ ///
+ /// This tests the high bit of this APInt to determine if it is set.
+ ///
+ /// \returns true if this APInt is negative, false otherwise
+ bool isNegative() const { return (*this)[BitWidth - 1]; }
+
+ /// Determine if this APInt Value is non-negative (>= 0)
+ ///
+ /// This tests the high bit of the APInt to determine if it is unset.
+ bool isNonNegative() const { return !isNegative(); }
+
+ /// Determine if sign bit of this APInt is set.
+ ///
+ /// This tests the high bit of this APInt to determine if it is set.
+ ///
+ /// \returns true if this APInt has its sign bit set, false otherwise.
+ bool isSignBitSet() const { return (*this)[BitWidth-1]; }
+
+ /// Determine if sign bit of this APInt is clear.
+ ///
+ /// This tests the high bit of this APInt to determine if it is clear.
+ ///
+ /// \returns true if this APInt has its sign bit clear, false otherwise.
+ bool isSignBitClear() const { return !isSignBitSet(); }
+
+ /// Determine if this APInt Value is positive.
+ ///
+ /// This tests if the value of this APInt is positive (> 0). Note
+ /// that 0 is not a positive value.
+ ///
+ /// \returns true if this APInt is positive.
+ bool isStrictlyPositive() const { return isNonNegative() && !isNullValue(); }
+
+ /// Determine if all bits are set
+ ///
+ /// This checks to see if the value has all bits of the APInt are set or not.
+ bool isAllOnesValue() const {
+ if (isSingleWord())
+ return U.VAL == WORDTYPE_MAX >> (APINT_BITS_PER_WORD - BitWidth);
+ return countTrailingOnesSlowCase() == BitWidth;
+ }
+
+ /// Determine if all bits are clear
+ ///
+ /// This checks to see if the value has all bits of the APInt are clear or
+ /// not.
+ bool isNullValue() const { return !*this; }
+
+ /// Determine if this is a value of 1.
+ ///
+ /// This checks to see if the value of this APInt is one.
+ bool isOneValue() const {
+ if (isSingleWord())
+ return U.VAL == 1;
+ return countLeadingZerosSlowCase() == BitWidth - 1;
+ }
+
+ /// Determine if this is the largest unsigned value.
+ ///
+ /// This checks to see if the value of this APInt is the maximum unsigned
+ /// value for the APInt's bit width.
+ bool isMaxValue() const { return isAllOnesValue(); }
+
+ /// Determine if this is the largest signed value.
+ ///
+ /// This checks to see if the value of this APInt is the maximum signed
+ /// value for the APInt's bit width.
+ bool isMaxSignedValue() const {
+ if (isSingleWord())
+ return U.VAL == ((WordType(1) << (BitWidth - 1)) - 1);
+ return !isNegative() && countTrailingOnesSlowCase() == BitWidth - 1;
+ }
+
+ /// Determine if this is the smallest unsigned value.
+ ///
+ /// This checks to see if the value of this APInt is the minimum unsigned
+ /// value for the APInt's bit width.
+ bool isMinValue() const { return isNullValue(); }
+
+ /// Determine if this is the smallest signed value.
+ ///
+ /// This checks to see if the value of this APInt is the minimum signed
+ /// value for the APInt's bit width.
+ bool isMinSignedValue() const {
+ if (isSingleWord())
+ return U.VAL == (WordType(1) << (BitWidth - 1));
+ return isNegative() && countTrailingZerosSlowCase() == BitWidth - 1;
+ }
+
+ /// Check if this APInt has an N-bits unsigned integer value.
+ bool isIntN(unsigned N) const {
+ assert(N && "N == 0 ???");
+ return getActiveBits() <= N;
+ }
+
+ /// Check if this APInt has an N-bits signed integer value.
+ bool isSignedIntN(unsigned N) const {
+ assert(N && "N == 0 ???");
+ return getMinSignedBits() <= N;
+ }
+
+ /// Check if this APInt's value is a power of two greater than zero.
+ ///
+ /// \returns true if the argument APInt value is a power of two > 0.
+ bool isPowerOf2() const {
+ if (isSingleWord())
+ return isPowerOf2_64(U.VAL);
+ return countPopulationSlowCase() == 1;
+ }
+
+ /// Check if the APInt's value is returned by getSignMask.
+ ///
+ /// \returns true if this is the value returned by getSignMask.
+ bool isSignMask() const { return isMinSignedValue(); }
+
+ /// Convert APInt to a boolean value.
+ ///
+ /// This converts the APInt to a boolean value as a test against zero.
+ bool getBoolValue() const { return !!*this; }
+
+ /// If this value is smaller than the specified limit, return it, otherwise
+ /// return the limit value. This causes the value to saturate to the limit.
+ uint64_t getLimitedValue(uint64_t Limit = UINT64_MAX) const {
+ return ugt(Limit) ? Limit : getZExtValue();
+ }
+
+ /// Check if the APInt consists of a repeated bit pattern.
+ ///
+ /// e.g. 0x01010101 satisfies isSplat(8).
+ /// \param SplatSizeInBits The size of the pattern in bits. Must divide bit
+ /// width without remainder.
+ bool isSplat(unsigned SplatSizeInBits) const;
+
+ /// \returns true if this APInt value is a sequence of \param numBits ones
+ /// starting at the least significant bit with the remainder zero.
+ bool isMask(unsigned numBits) const {
+ assert(numBits != 0 && "numBits must be non-zero");
+ assert(numBits <= BitWidth && "numBits out of range");
+ if (isSingleWord())
+ return U.VAL == (WORDTYPE_MAX >> (APINT_BITS_PER_WORD - numBits));
+ unsigned Ones = countTrailingOnesSlowCase();
+ return (numBits == Ones) &&
+ ((Ones + countLeadingZerosSlowCase()) == BitWidth);
+ }
+
+ /// \returns true if this APInt is a non-empty sequence of ones starting at
+ /// the least significant bit with the remainder zero.
+ /// Ex. isMask(0x0000FFFFU) == true.
+ bool isMask() const {
+ if (isSingleWord())
+ return isMask_64(U.VAL);
+ unsigned Ones = countTrailingOnesSlowCase();
+ return (Ones > 0) && ((Ones + countLeadingZerosSlowCase()) == BitWidth);
+ }
+
+ /// Return true if this APInt value contains a sequence of ones with
+ /// the remainder zero.
+ bool isShiftedMask() const {
+ if (isSingleWord())
+ return isShiftedMask_64(U.VAL);
+ unsigned Ones = countPopulationSlowCase();
+ unsigned LeadZ = countLeadingZerosSlowCase();
+ return (Ones + LeadZ + countTrailingZeros()) == BitWidth;
+ }
+
+ /// @}
+ /// \name Value Generators
+ /// @{
+
+ /// Gets maximum unsigned value of APInt for specific bit width.
+ static APInt getMaxValue(unsigned numBits) {
+ return getAllOnesValue(numBits);
+ }
+
+ /// Gets maximum signed value of APInt for a specific bit width.
+ static APInt getSignedMaxValue(unsigned numBits) {
+ APInt API = getAllOnesValue(numBits);
+ API.clearBit(numBits - 1);
+ return API;
+ }
+
+ /// Gets minimum unsigned value of APInt for a specific bit width.
+ static APInt getMinValue(unsigned numBits) { return APInt(numBits, 0); }
+
+ /// Gets minimum signed value of APInt for a specific bit width.
+ static APInt getSignedMinValue(unsigned numBits) {
+ APInt API(numBits, 0);
+ API.setBit(numBits - 1);
+ return API;
+ }
+
+ /// Get the SignMask for a specific bit width.
+ ///
+ /// This is just a wrapper function of getSignedMinValue(), and it helps code
+ /// readability when we want to get a SignMask.
+ static APInt getSignMask(unsigned BitWidth) {
+ return getSignedMinValue(BitWidth);
+ }
+
+ /// Get the all-ones value.
+ ///
+ /// \returns the all-ones value for an APInt of the specified bit-width.
+ static APInt getAllOnesValue(unsigned numBits) {
+ return APInt(numBits, WORDTYPE_MAX, true);
+ }
+
+ /// Get the '0' value.
+ ///
+ /// \returns the '0' value for an APInt of the specified bit-width.
+ static APInt getNullValue(unsigned numBits) { return APInt(numBits, 0); }
+
+ /// Compute an APInt containing numBits highbits from this APInt.
+ ///
+ /// Get an APInt with the same BitWidth as this APInt, just zero mask
+ /// the low bits and right shift to the least significant bit.
+ ///
+ /// \returns the high "numBits" bits of this APInt.
+ APInt getHiBits(unsigned numBits) const;
+
+ /// Compute an APInt containing numBits lowbits from this APInt.
+ ///
+ /// Get an APInt with the same BitWidth as this APInt, just zero mask
+ /// the high bits.
+ ///
+ /// \returns the low "numBits" bits of this APInt.
+ APInt getLoBits(unsigned numBits) const;
+
+ /// Return an APInt with exactly one bit set in the result.
+ static APInt getOneBitSet(unsigned numBits, unsigned BitNo) {
+ APInt Res(numBits, 0);
+ Res.setBit(BitNo);
+ return Res;
+ }
+
+ /// Get a value with a block of bits set.
+ ///
+ /// Constructs an APInt value that has a contiguous range of bits set. The
+ /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other
+ /// bits will be zero. For example, with parameters(32, 0, 16) you would get
+ /// 0x0000FFFF. If hiBit is less than loBit then the set bits "wrap". For
+ /// example, with parameters (32, 28, 4), you would get 0xF000000F.
+ ///
+ /// \param numBits the intended bit width of the result
+ /// \param loBit the index of the lowest bit set.
+ /// \param hiBit the index of the highest bit set.
+ ///
+ /// \returns An APInt value with the requested bits set.
+ static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) {
+ APInt Res(numBits, 0);
+ Res.setBits(loBit, hiBit);
+ return Res;
+ }
+
+ /// Get a value with upper bits starting at loBit set.
+ ///
+ /// Constructs an APInt value that has a contiguous range of bits set. The
+ /// bits from loBit (inclusive) to numBits (exclusive) will be set. All other
+ /// bits will be zero. For example, with parameters(32, 12) you would get
+ /// 0xFFFFF000.
+ ///
+ /// \param numBits the intended bit width of the result
+ /// \param loBit the index of the lowest bit to set.
+ ///
+ /// \returns An APInt value with the requested bits set.
+ static APInt getBitsSetFrom(unsigned numBits, unsigned loBit) {
+ APInt Res(numBits, 0);
+ Res.setBitsFrom(loBit);
+ return Res;
+ }
+
+ /// Get a value with high bits set
+ ///
+ /// Constructs an APInt value that has the top hiBitsSet bits set.
+ ///
+ /// \param numBits the bitwidth of the result
+ /// \param hiBitsSet the number of high-order bits set in the result.
+ static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) {
+ APInt Res(numBits, 0);
+ Res.setHighBits(hiBitsSet);
+ return Res;
+ }
+
+ /// Get a value with low bits set
+ ///
+ /// Constructs an APInt value that has the bottom loBitsSet bits set.
+ ///
+ /// \param numBits the bitwidth of the result
+ /// \param loBitsSet the number of low-order bits set in the result.
+ static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) {
+ APInt Res(numBits, 0);
+ Res.setLowBits(loBitsSet);
+ return Res;
+ }
+
+ /// Return a value containing V broadcasted over NewLen bits.
+ static APInt getSplat(unsigned NewLen, const APInt &V);
+
+ /// Determine if two APInts have the same value, after zero-extending
+ /// one of them (if needed!) to ensure that the bit-widths match.
+ static bool isSameValue(const APInt &I1, const APInt &I2) {
+ if (I1.getBitWidth() == I2.getBitWidth())
+ return I1 == I2;
+
+ if (I1.getBitWidth() > I2.getBitWidth())
+ return I1 == I2.zext(I1.getBitWidth());
+
+ return I1.zext(I2.getBitWidth()) == I2;
+ }
+
+ /// Overload to compute a hash_code for an APInt value.
+ friend hash_code hash_value(const APInt &Arg);
+
+ /// This function returns a pointer to the internal storage of the APInt.
+ /// This is useful for writing out the APInt in binary form without any
+ /// conversions.
+ const uint64_t *getRawData() const {
+ if (isSingleWord())
+ return &U.VAL;
+ return &U.pVal[0];
+ }
+
+ /// @}
+ /// \name Unary Operators
+ /// @{
+
+ /// Postfix increment operator.
+ ///
+ /// Increments *this by 1.
+ ///
+ /// \returns a new APInt value representing the original value of *this.
+ const APInt operator++(int) {
+ APInt API(*this);
+ ++(*this);
+ return API;
+ }
+
+ /// Prefix increment operator.
+ ///
+ /// \returns *this incremented by one
+ APInt &operator++();
+
+ /// Postfix decrement operator.
+ ///
+ /// Decrements *this by 1.
+ ///
+ /// \returns a new APInt value representing the original value of *this.
+ const APInt operator--(int) {
+ APInt API(*this);
+ --(*this);
+ return API;
+ }
+
+ /// Prefix decrement operator.
+ ///
+ /// \returns *this decremented by one.
+ APInt &operator--();
+
+ /// Logical negation operator.
+ ///
+ /// Performs logical negation operation on this APInt.
+ ///
+ /// \returns true if *this is zero, false otherwise.
+ bool operator!() const {
+ if (isSingleWord())
+ return U.VAL == 0;
+ return countLeadingZerosSlowCase() == BitWidth;
+ }
+
+ /// @}
+ /// \name Assignment Operators
+ /// @{
+
+ /// Copy assignment operator.
+ ///
+ /// \returns *this after assignment of RHS.
+ APInt &operator=(const APInt &RHS) {
+ // If the bitwidths are the same, we can avoid mucking with memory
+ if (isSingleWord() && RHS.isSingleWord()) {
+ U.VAL = RHS.U.VAL;
+ BitWidth = RHS.BitWidth;
+ return clearUnusedBits();
+ }
+
+ AssignSlowCase(RHS);
+ return *this;
+ }
+
+ /// Move assignment operator.
+ APInt &operator=(APInt &&that) {
+#ifdef _MSC_VER
+ // The MSVC std::shuffle implementation still does self-assignment.
+ if (this == &that)
+ return *this;
+#endif
+ assert(this != &that && "Self-move not supported");
+ if (!isSingleWord())
+ delete[] U.pVal;
+
+ // Use memcpy so that type based alias analysis sees both VAL and pVal
+ // as modified.
+ memcpy(&U, &that.U, sizeof(U));
+
+ BitWidth = that.BitWidth;
+ that.BitWidth = 0;
+
+ return *this;
+ }
+
+ /// Assignment operator.
+ ///
+ /// The RHS value is assigned to *this. If the significant bits in RHS exceed
+ /// the bit width, the excess bits are truncated. If the bit width is larger
+ /// than 64, the value is zero filled in the unspecified high order bits.
+ ///
+ /// \returns *this after assignment of RHS value.
+ APInt &operator=(uint64_t RHS) {
+ if (isSingleWord()) {
+ U.VAL = RHS;
+ clearUnusedBits();
+ } else {
+ U.pVal[0] = RHS;
+ memset(U.pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE);
+ }
+ return *this;
+ }
+
+ /// Bitwise AND assignment operator.
+ ///
+ /// Performs a bitwise AND operation on this APInt and RHS. The result is
+ /// assigned to *this.
+ ///
+ /// \returns *this after ANDing with RHS.
+ APInt &operator&=(const APInt &RHS) {
+ assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+ if (isSingleWord())
+ U.VAL &= RHS.U.VAL;
+ else
+ AndAssignSlowCase(RHS);
+ return *this;
+ }
+
+ /// Bitwise AND assignment operator.
+ ///
+ /// Performs a bitwise AND operation on this APInt and RHS. RHS is
+ /// logically zero-extended or truncated to match the bit-width of
+ /// the LHS.
+ APInt &operator&=(uint64_t RHS) {
+ if (isSingleWord()) {
+ U.VAL &= RHS;
+ return *this;
+ }
+ U.pVal[0] &= RHS;
+ memset(U.pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE);
+ return *this;
+ }
+
+ /// Bitwise OR assignment operator.
+ ///
+ /// Performs a bitwise OR operation on this APInt and RHS. The result is
+ /// assigned *this;
+ ///
+ /// \returns *this after ORing with RHS.
+ APInt &operator|=(const APInt &RHS) {
+ assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+ if (isSingleWord())
+ U.VAL |= RHS.U.VAL;
+ else
+ OrAssignSlowCase(RHS);
+ return *this;
+ }
+
+ /// Bitwise OR assignment operator.
+ ///
+ /// Performs a bitwise OR operation on this APInt and RHS. RHS is
+ /// logically zero-extended or truncated to match the bit-width of
+ /// the LHS.
+ APInt &operator|=(uint64_t RHS) {
+ if (isSingleWord()) {
+ U.VAL |= RHS;
+ clearUnusedBits();
+ } else {
+ U.pVal[0] |= RHS;
+ }
+ return *this;
+ }
+
+ /// Bitwise XOR assignment operator.
+ ///
+ /// Performs a bitwise XOR operation on this APInt and RHS. The result is
+ /// assigned to *this.
+ ///
+ /// \returns *this after XORing with RHS.
+ APInt &operator^=(const APInt &RHS) {
+ assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+ if (isSingleWord())
+ U.VAL ^= RHS.U.VAL;
+ else
+ XorAssignSlowCase(RHS);
+ return *this;
+ }
+
+ /// Bitwise XOR assignment operator.
+ ///
+ /// Performs a bitwise XOR operation on this APInt and RHS. RHS is
+ /// logically zero-extended or truncated to match the bit-width of
+ /// the LHS.
+ APInt &operator^=(uint64_t RHS) {
+ if (isSingleWord()) {
+ U.VAL ^= RHS;
+ clearUnusedBits();
+ } else {
+ U.pVal[0] ^= RHS;
+ }
+ return *this;
+ }
+
+ /// Multiplication assignment operator.
+ ///
+ /// Multiplies this APInt by RHS and assigns the result to *this.
+ ///
+ /// \returns *this
+ APInt &operator*=(const APInt &RHS);
+ APInt &operator*=(uint64_t RHS);
+
+ /// Addition assignment operator.
+ ///
+ /// Adds RHS to *this and assigns the result to *this.
+ ///
+ /// \returns *this
+ APInt &operator+=(const APInt &RHS);
+ APInt &operator+=(uint64_t RHS);
+
+ /// Subtraction assignment operator.
+ ///
+ /// Subtracts RHS from *this and assigns the result to *this.
+ ///
+ /// \returns *this
+ APInt &operator-=(const APInt &RHS);
+ APInt &operator-=(uint64_t RHS);
+
+ /// Left-shift assignment function.
+ ///
+ /// Shifts *this left by shiftAmt and assigns the result to *this.
+ ///
+ /// \returns *this after shifting left by ShiftAmt
+ APInt &operator<<=(unsigned ShiftAmt) {
+ assert(ShiftAmt <= BitWidth && "Invalid shift amount");
+ if (isSingleWord()) {
+ if (ShiftAmt == BitWidth)
+ U.VAL = 0;
+ else
+ U.VAL <<= ShiftAmt;
+ return clearUnusedBits();
+ }
+ shlSlowCase(ShiftAmt);
+ return *this;
+ }
+
+ /// Left-shift assignment function.
+ ///
+ /// Shifts *this left by shiftAmt and assigns the result to *this.
+ ///
+ /// \returns *this after shifting left by ShiftAmt
+ APInt &operator<<=(const APInt &ShiftAmt);
+
+ /// @}
+ /// \name Binary Operators
+ /// @{
+
+ /// Multiplication operator.
+ ///
+ /// Multiplies this APInt by RHS and returns the result.
+ APInt operator*(const APInt &RHS) const;
+
+ /// Left logical shift operator.
+ ///
+ /// Shifts this APInt left by \p Bits and returns the result.
+ APInt operator<<(unsigned Bits) const { return shl(Bits); }
+
+ /// Left logical shift operator.
+ ///
+ /// Shifts this APInt left by \p Bits and returns the result.
+ APInt operator<<(const APInt &Bits) const { return shl(Bits); }
+
+ /// Arithmetic right-shift function.
+ ///
+ /// Arithmetic right-shift this APInt by shiftAmt.
+ APInt ashr(unsigned ShiftAmt) const {
+ APInt R(*this);
+ R.ashrInPlace(ShiftAmt);
+ return R;
+ }
+
+ /// Arithmetic right-shift this APInt by ShiftAmt in place.
+ void ashrInPlace(unsigned ShiftAmt) {
+ assert(ShiftAmt <= BitWidth && "Invalid shift amount");
+ if (isSingleWord()) {
+ int64_t SExtVAL = SignExtend64(U.VAL, BitWidth);
+ if (ShiftAmt == BitWidth)
+ U.VAL = SExtVAL >> (APINT_BITS_PER_WORD - 1); // Fill with sign bit.
+ else
+ U.VAL = SExtVAL >> ShiftAmt;
+ clearUnusedBits();
+ return;
+ }
+ ashrSlowCase(ShiftAmt);
+ }
+
+ /// Logical right-shift function.
+ ///
+ /// Logical right-shift this APInt by shiftAmt.
+ APInt lshr(unsigned shiftAmt) const {
+ APInt R(*this);
+ R.lshrInPlace(shiftAmt);
+ return R;
+ }
+
+ /// Logical right-shift this APInt by ShiftAmt in place.
+ void lshrInPlace(unsigned ShiftAmt) {
+ assert(ShiftAmt <= BitWidth && "Invalid shift amount");
+ if (isSingleWord()) {
+ if (ShiftAmt == BitWidth)
+ U.VAL = 0;
+ else
+ U.VAL >>= ShiftAmt;
+ return;
+ }
+ lshrSlowCase(ShiftAmt);
+ }
+
+ /// Left-shift function.
+ ///
+ /// Left-shift this APInt by shiftAmt.
+ APInt shl(unsigned shiftAmt) const {
+ APInt R(*this);
+ R <<= shiftAmt;
+ return R;
+ }
+
+ /// Rotate left by rotateAmt.
+ APInt rotl(unsigned rotateAmt) const;
+
+ /// Rotate right by rotateAmt.
+ APInt rotr(unsigned rotateAmt) const;
+
+ /// Arithmetic right-shift function.
+ ///
+ /// Arithmetic right-shift this APInt by shiftAmt.
+ APInt ashr(const APInt &ShiftAmt) const {
+ APInt R(*this);
+ R.ashrInPlace(ShiftAmt);
+ return R;
+ }
+
+ /// Arithmetic right-shift this APInt by shiftAmt in place.
+ void ashrInPlace(const APInt &shiftAmt);
+
+ /// Logical right-shift function.
+ ///
+ /// Logical right-shift this APInt by shiftAmt.
+ APInt lshr(const APInt &ShiftAmt) const {
+ APInt R(*this);
+ R.lshrInPlace(ShiftAmt);
+ return R;
+ }
+
+ /// Logical right-shift this APInt by ShiftAmt in place.
+ void lshrInPlace(const APInt &ShiftAmt);
+
+ /// Left-shift function.
+ ///
+ /// Left-shift this APInt by shiftAmt.
+ APInt shl(const APInt &ShiftAmt) const {
+ APInt R(*this);
+ R <<= ShiftAmt;
+ return R;
+ }
+
+ /// Rotate left by rotateAmt.
+ APInt rotl(const APInt &rotateAmt) const;
+
+ /// Rotate right by rotateAmt.
+ APInt rotr(const APInt &rotateAmt) const;
+
+ /// Unsigned division operation.
+ ///
+ /// Perform an unsigned divide operation on this APInt by RHS. Both this and
+ /// RHS are treated as unsigned quantities for purposes of this division.
+ ///
+ /// \returns a new APInt value containing the division result, rounded towards
+ /// zero.
+ APInt udiv(const APInt &RHS) const;
+ APInt udiv(uint64_t RHS) const;
+
+ /// Signed division function for APInt.
+ ///
+ /// Signed divide this APInt by APInt RHS.
+ ///
+ /// The result is rounded towards zero.
+ APInt sdiv(const APInt &RHS) const;
+ APInt sdiv(int64_t RHS) const;
+
+ /// Unsigned remainder operation.
+ ///
+ /// Perform an unsigned remainder operation on this APInt with RHS being the
+ /// divisor. Both this and RHS are treated as unsigned quantities for purposes
+ /// of this operation. Note that this is a true remainder operation and not a
+ /// modulo operation because the sign follows the sign of the dividend which
+ /// is *this.
+ ///
+ /// \returns a new APInt value containing the remainder result
+ APInt urem(const APInt &RHS) const;
+ uint64_t urem(uint64_t RHS) const;
+
+ /// Function for signed remainder operation.
+ ///
+ /// Signed remainder operation on APInt.
+ APInt srem(const APInt &RHS) const;
+ int64_t srem(int64_t RHS) const;
+
+ /// Dual division/remainder interface.
+ ///
+ /// Sometimes it is convenient to divide two APInt values and obtain both the
+ /// quotient and remainder. This function does both operations in the same
+ /// computation making it a little more efficient. The pair of input arguments
+ /// may overlap with the pair of output arguments. It is safe to call
+ /// udivrem(X, Y, X, Y), for example.
+ static void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient,
+ APInt &Remainder);
+ static void udivrem(const APInt &LHS, uint64_t RHS, APInt &Quotient,
+ uint64_t &Remainder);
+
+ static void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient,
+ APInt &Remainder);
+ static void sdivrem(const APInt &LHS, int64_t RHS, APInt &Quotient,
+ int64_t &Remainder);
+
+ // Operations that return overflow indicators.
+ APInt sadd_ov(const APInt &RHS, bool &Overflow) const;
+ APInt uadd_ov(const APInt &RHS, bool &Overflow) const;
+ APInt ssub_ov(const APInt &RHS, bool &Overflow) const;
+ APInt usub_ov(const APInt &RHS, bool &Overflow) const;
+ APInt sdiv_ov(const APInt &RHS, bool &Overflow) const;
+ APInt smul_ov(const APInt &RHS, bool &Overflow) const;
+ APInt umul_ov(const APInt &RHS, bool &Overflow) const;
+ APInt sshl_ov(const APInt &Amt, bool &Overflow) const;
+ APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
+
+ // Operations that saturate
+ APInt sadd_sat(const APInt &RHS) const;
+ APInt uadd_sat(const APInt &RHS) const;
+ APInt ssub_sat(const APInt &RHS) const;
+ APInt usub_sat(const APInt &RHS) const;
+ APInt smul_sat(const APInt &RHS) const;
+ APInt umul_sat(const APInt &RHS) const;
+ APInt sshl_sat(const APInt &RHS) const;
+ APInt ushl_sat(const APInt &RHS) const;
+
+ /// Array-indexing support.
+ ///
+ /// \returns the bit value at bitPosition
+ bool operator[](unsigned bitPosition) const {
+ assert(bitPosition < getBitWidth() && "Bit position out of bounds!");
+ return (maskBit(bitPosition) & getWord(bitPosition)) != 0;
+ }
+
+ /// @}
+ /// \name Comparison Operators
+ /// @{
+
+ /// Equality operator.
+ ///
+ /// Compares this APInt with RHS for the validity of the equality
+ /// relationship.
+ bool operator==(const APInt &RHS) const {
+ assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths");
+ if (isSingleWord())
+ return U.VAL == RHS.U.VAL;
+ return EqualSlowCase(RHS);
+ }
+
+ /// Equality operator.
+ ///
+ /// Compares this APInt with a uint64_t for the validity of the equality
+ /// relationship.
+ ///
+ /// \returns true if *this == Val
+ bool operator==(uint64_t Val) const {
+ return (isSingleWord() || getActiveBits() <= 64) && getZExtValue() == Val;
+ }
+
+ /// Equality comparison.
+ ///
+ /// Compares this APInt with RHS for the validity of the equality
+ /// relationship.
+ ///
+ /// \returns true if *this == Val
+ bool eq(const APInt &RHS) const { return (*this) == RHS; }
+
+ /// Inequality operator.
+ ///
+ /// Compares this APInt with RHS for the validity of the inequality
+ /// relationship.
+ ///
+ /// \returns true if *this != Val
+ bool operator!=(const APInt &RHS) const { return !((*this) == RHS); }
+
+ /// Inequality operator.
+ ///
+ /// Compares this APInt with a uint64_t for the validity of the inequality
+ /// relationship.
+ ///
+ /// \returns true if *this != Val
+ bool operator!=(uint64_t Val) const { return !((*this) == Val); }
+
+ /// Inequality comparison
+ ///
+ /// Compares this APInt with RHS for the validity of the inequality
+ /// relationship.
+ ///
+ /// \returns true if *this != Val
+ bool ne(const APInt &RHS) const { return !((*this) == RHS); }
+
+ /// Unsigned less than comparison
+ ///
+ /// Regards both *this and RHS as unsigned quantities and compares them for
+ /// the validity of the less-than relationship.
+ ///
+ /// \returns true if *this < RHS when both are considered unsigned.
+ bool ult(const APInt &RHS) const { return compare(RHS) < 0; }
+
+ /// Unsigned less than comparison
+ ///
+ /// Regards both *this as an unsigned quantity and compares it with RHS for
+ /// the validity of the less-than relationship.
+ ///
+ /// \returns true if *this < RHS when considered unsigned.
+ bool ult(uint64_t RHS) const {
+ // Only need to check active bits if not a single word.
+ return (isSingleWord() || getActiveBits() <= 64) && getZExtValue() < RHS;
+ }
+
+ /// Signed less than comparison
+ ///
+ /// Regards both *this and RHS as signed quantities and compares them for
+ /// validity of the less-than relationship.
+ ///
+ /// \returns true if *this < RHS when both are considered signed.
+ bool slt(const APInt &RHS) const { return compareSigned(RHS) < 0; }
+
+ /// Signed less than comparison
+ ///
+ /// Regards both *this as a signed quantity and compares it with RHS for
+ /// the validity of the less-than relationship.
+ ///
+ /// \returns true if *this < RHS when considered signed.
+ bool slt(int64_t RHS) const {
+ return (!isSingleWord() && getMinSignedBits() > 64) ? isNegative()
+ : getSExtValue() < RHS;
+ }
+
+ /// Unsigned less or equal comparison
+ ///
+ /// Regards both *this and RHS as unsigned quantities and compares them for
+ /// validity of the less-or-equal relationship.
+ ///
+ /// \returns true if *this <= RHS when both are considered unsigned.
+ bool ule(const APInt &RHS) const { return compare(RHS) <= 0; }
+
+ /// Unsigned less or equal comparison
+ ///
+ /// Regards both *this as an unsigned quantity and compares it with RHS for
+ /// the validity of the less-or-equal relationship.
+ ///
+ /// \returns true if *this <= RHS when considered unsigned.
+ bool ule(uint64_t RHS) const { return !ugt(RHS); }
+
+ /// Signed less or equal comparison
+ ///
+ /// Regards both *this and RHS as signed quantities and compares them for
+ /// validity of the less-or-equal relationship.
+ ///
+ /// \returns true if *this <= RHS when both are considered signed.
+ bool sle(const APInt &RHS) const { return compareSigned(RHS) <= 0; }
+
+ /// Signed less or equal comparison
+ ///
+ /// Regards both *this as a signed quantity and compares it with RHS for the
+ /// validity of the less-or-equal relationship.
+ ///
+ /// \returns true if *this <= RHS when considered signed.
+ bool sle(uint64_t RHS) const { return !sgt(RHS); }
+
+ /// Unsigned greater than comparison
+ ///
+ /// Regards both *this and RHS as unsigned quantities and compares them for
+ /// the validity of the greater-than relationship.
+ ///
+ /// \returns true if *this > RHS when both are considered unsigned.
+ bool ugt(const APInt &RHS) const { return !ule(RHS); }
+
+ /// Unsigned greater than comparison
+ ///
+ /// Regards both *this as an unsigned quantity and compares it with RHS for
+ /// the validity of the greater-than relationship.
+ ///
+ /// \returns true if *this > RHS when considered unsigned.
+ bool ugt(uint64_t RHS) const {
+ // Only need to check active bits if not a single word.
+ return (!isSingleWord() && getActiveBits() > 64) || getZExtValue() > RHS;
+ }
+
+ /// Signed greater than comparison
+ ///
+ /// Regards both *this and RHS as signed quantities and compares them for the
+ /// validity of the greater-than relationship.
+ ///
+ /// \returns true if *this > RHS when both are considered signed.
+ bool sgt(const APInt &RHS) const { return !sle(RHS); }
+
+ /// Signed greater than comparison
+ ///
+ /// Regards both *this as a signed quantity and compares it with RHS for
+ /// the validity of the greater-than relationship.
+ ///
+ /// \returns true if *this > RHS when considered signed.
+ bool sgt(int64_t RHS) const {
+ return (!isSingleWord() && getMinSignedBits() > 64) ? !isNegative()
+ : getSExtValue() > RHS;
+ }
+
+ /// Unsigned greater or equal comparison
+ ///
+ /// Regards both *this and RHS as unsigned quantities and compares them for
+ /// validity of the greater-or-equal relationship.
+ ///
+ /// \returns true if *this >= RHS when both are considered unsigned.
+ bool uge(const APInt &RHS) const { return !ult(RHS); }
+
+ /// Unsigned greater or equal comparison
+ ///
+ /// Regards both *this as an unsigned quantity and compares it with RHS for
+ /// the validity of the greater-or-equal relationship.
+ ///
+ /// \returns true if *this >= RHS when considered unsigned.
+ bool uge(uint64_t RHS) const { return !ult(RHS); }
+
+ /// Signed greater or equal comparison
+ ///
+ /// Regards both *this and RHS as signed quantities and compares them for
+ /// validity of the greater-or-equal relationship.
+ ///
+ /// \returns true if *this >= RHS when both are considered signed.
+ bool sge(const APInt &RHS) const { return !slt(RHS); }
+
+ /// Signed greater or equal comparison
+ ///
+ /// Regards both *this as a signed quantity and compares it with RHS for
+ /// the validity of the greater-or-equal relationship.
+ ///
+ /// \returns true if *this >= RHS when considered signed.
+ bool sge(int64_t RHS) const { return !slt(RHS); }
+
+ /// This operation tests if there are any pairs of corresponding bits
+ /// between this APInt and RHS that are both set.
+ bool intersects(const APInt &RHS) const {
+ assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+ if (isSingleWord())
+ return (U.VAL & RHS.U.VAL) != 0;
+ return intersectsSlowCase(RHS);
+ }
+
+ /// This operation checks that all bits set in this APInt are also set in RHS.
+ bool isSubsetOf(const APInt &RHS) const {
+ assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+ if (isSingleWord())
+ return (U.VAL & ~RHS.U.VAL) == 0;
+ return isSubsetOfSlowCase(RHS);
+ }
+
+ /// @}
+ /// \name Resizing Operators
+ /// @{
+
+ /// Truncate to new width.
+ ///
+ /// Truncate the APInt to a specified width. It is an error to specify a width
+ /// that is greater than or equal to the current width.
+ APInt trunc(unsigned width) const;
+
+ /// Truncate to new width with unsigned saturation.
+ ///
+ /// If the APInt, treated as unsigned integer, can be losslessly truncated to
+ /// the new bitwidth, then return truncated APInt. Else, return max value.
+ APInt truncUSat(unsigned width) const;
+
+ /// Truncate to new width with signed saturation.
+ ///
+ /// If this APInt, treated as signed integer, can be losslessly truncated to
+ /// the new bitwidth, then return truncated APInt. Else, return either
+ /// signed min value if the APInt was negative, or signed max value.
+ APInt truncSSat(unsigned width) const;
+
+ /// Sign extend to a new width.
+ ///
+ /// This operation sign extends the APInt to a new width. If the high order
+ /// bit is set, the fill on the left will be done with 1 bits, otherwise zero.
+ /// It is an error to specify a width that is less than or equal to the
+ /// current width.
+ APInt sext(unsigned width) const;
+
+ /// Zero extend to a new width.
+ ///
+ /// This operation zero extends the APInt to a new width. The high order bits
+ /// are filled with 0 bits. It is an error to specify a width that is less
+ /// than or equal to the current width.
+ APInt zext(unsigned width) const;
+
+ /// Sign extend or truncate to width
+ ///
+ /// Make this APInt have the bit width given by \p width. The value is sign
+ /// extended, truncated, or left alone to make it that width.
+ APInt sextOrTrunc(unsigned width) const;
+
+ /// Zero extend or truncate to width
+ ///
+ /// Make this APInt have the bit width given by \p width. The value is zero
+ /// extended, truncated, or left alone to make it that width.
+ APInt zextOrTrunc(unsigned width) const;
+
+ /// Sign extend or truncate to width
+ ///
+ /// Make this APInt have the bit width given by \p width. The value is sign
+ /// extended, or left alone to make it that width.
+ APInt sextOrSelf(unsigned width) const;
+
+ /// Zero extend or truncate to width
+ ///
+ /// Make this APInt have the bit width given by \p width. The value is zero
+ /// extended, or left alone to make it that width.
+ APInt zextOrSelf(unsigned width) const;
+
+ /// @}
+ /// \name Bit Manipulation Operators
+ /// @{
+
+ /// Set every bit to 1.
+ void setAllBits() {
+ if (isSingleWord())
+ U.VAL = WORDTYPE_MAX;
+ else
+ // Set all the bits in all the words.
+ memset(U.pVal, -1, getNumWords() * APINT_WORD_SIZE);
+ // Clear the unused ones
+ clearUnusedBits();
+ }
+
+ /// Set a given bit to 1.
+ ///
+ /// Set the given bit to 1 whose position is given as "bitPosition".
+ void setBit(unsigned BitPosition) {
+ assert(BitPosition < BitWidth && "BitPosition out of range");
+ WordType Mask = maskBit(BitPosition);
+ if (isSingleWord())
+ U.VAL |= Mask;
+ else
+ U.pVal[whichWord(BitPosition)] |= Mask;
+ }
+
+ /// Set the sign bit to 1.
+ void setSignBit() {
+ setBit(BitWidth - 1);
+ }
+
+ /// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1.
+ void setBits(unsigned loBit, unsigned hiBit) {
+ assert(hiBit <= BitWidth && "hiBit out of range");
+ assert(loBit <= BitWidth && "loBit out of range");
+ assert(loBit <= hiBit && "loBit greater than hiBit");
+ if (loBit == hiBit)
+ return;
+ if (loBit < APINT_BITS_PER_WORD && hiBit <= APINT_BITS_PER_WORD) {
+ uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit));
+ mask <<= loBit;
+ if (isSingleWord())
+ U.VAL |= mask;
+ else
+ U.pVal[0] |= mask;
+ } else {
+ setBitsSlowCase(loBit, hiBit);
+ }
+ }
+
+ /// Set the top bits starting from loBit.
+ void setBitsFrom(unsigned loBit) {
+ return setBits(loBit, BitWidth);
+ }
+
+ /// Set the bottom loBits bits.
+ void setLowBits(unsigned loBits) {
+ return setBits(0, loBits);
+ }
+
+ /// Set the top hiBits bits.
+ void setHighBits(unsigned hiBits) {
+ return setBits(BitWidth - hiBits, BitWidth);
+ }
+
+ /// Set every bit to 0.
+ void clearAllBits() {
+ if (isSingleWord())
+ U.VAL = 0;
+ else
+ memset(U.pVal, 0, getNumWords() * APINT_WORD_SIZE);
+ }
+
+ /// Set a given bit to 0.
+ ///
+ /// Set the given bit to 0 whose position is given as "bitPosition".
+ void clearBit(unsigned BitPosition) {
+ assert(BitPosition < BitWidth && "BitPosition out of range");
+ WordType Mask = ~maskBit(BitPosition);
+ if (isSingleWord())
+ U.VAL &= Mask;
+ else
+ U.pVal[whichWord(BitPosition)] &= Mask;
+ }
+
+ /// Set bottom loBits bits to 0.
+ void clearLowBits(unsigned loBits) {
+ assert(loBits <= BitWidth && "More bits than bitwidth");
+ APInt Keep = getHighBitsSet(BitWidth, BitWidth - loBits);
+ *this &= Keep;
+ }
+
+ /// Set the sign bit to 0.
+ void clearSignBit() {
+ clearBit(BitWidth - 1);
+ }
+
+ /// Toggle every bit to its opposite value.
+ void flipAllBits() {
+ if (isSingleWord()) {
+ U.VAL ^= WORDTYPE_MAX;
+ clearUnusedBits();
+ } else {
+ flipAllBitsSlowCase();
+ }
+ }
+
+ /// Toggles a given bit to its opposite value.
+ ///
+ /// Toggle a given bit to its opposite value whose position is given
+ /// as "bitPosition".
+ void flipBit(unsigned bitPosition);
+
+ /// Negate this APInt in place.
+ void negate() {
+ flipAllBits();
+ ++(*this);
+ }
+
+ /// Insert the bits from a smaller APInt starting at bitPosition.
+ void insertBits(const APInt &SubBits, unsigned bitPosition);
+ void insertBits(uint64_t SubBits, unsigned bitPosition, unsigned numBits);
+
+ /// Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
+ APInt extractBits(unsigned numBits, unsigned bitPosition) const;
+ uint64_t extractBitsAsZExtValue(unsigned numBits, unsigned bitPosition) const;
+
+ /// @}
+ /// \name Value Characterization Functions
+ /// @{
+
+ /// Return the number of bits in the APInt.
+ unsigned getBitWidth() const { return BitWidth; }
+
+ /// Get the number of words.
+ ///
+ /// Here one word's bitwidth equals to that of uint64_t.
+ ///
+ /// \returns the number of words to hold the integer value of this APInt.
+ unsigned getNumWords() const { return getNumWords(BitWidth); }
+
+ /// Get the number of words.
+ ///
+ /// *NOTE* Here one word's bitwidth equals to that of uint64_t.
+ ///
+ /// \returns the number of words to hold the integer value with a given bit
+ /// width.
+ static unsigned getNumWords(unsigned BitWidth) {
+ return ((uint64_t)BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
+ }
+
+ /// Compute the number of active bits in the value
+ ///
+ /// This function returns the number of active bits which is defined as the
+ /// bit width minus the number of leading zeros. This is used in several
+ /// computations to see how "wide" the value is.
+ unsigned getActiveBits() const { return BitWidth - countLeadingZeros(); }
+
+ /// Compute the number of active words in the value of this APInt.
+ ///
+ /// This is used in conjunction with getActiveData to extract the raw value of
+ /// the APInt.
+ unsigned getActiveWords() const {
+ unsigned numActiveBits = getActiveBits();
+ return numActiveBits ? whichWord(numActiveBits - 1) + 1 : 1;
+ }
+
+ /// Get the minimum bit size for this signed APInt
+ ///
+ /// Computes the minimum bit width for this APInt while considering it to be a
+ /// signed (and probably negative) value. If the value is not negative, this
+ /// function returns the same value as getActiveBits()+1. Otherwise, it
+ /// returns the smallest bit width that will retain the negative value. For
+ /// example, -1 can be written as 0b1 or 0xFFFFFFFFFF. 0b1 is shorter and so
+ /// for -1, this function will always return 1.
+ unsigned getMinSignedBits() const {
+ if (isNegative())
+ return BitWidth - countLeadingOnes() + 1;
+ return getActiveBits() + 1;
+ }
+
+ /// Get zero extended value
+ ///
+ /// This method attempts to return the value of this APInt as a zero extended
+ /// uint64_t. The bitwidth must be <= 64 or the value must fit within a
+ /// uint64_t. Otherwise an assertion will result.
+ uint64_t getZExtValue() const {
+ if (isSingleWord())
+ return U.VAL;
+ assert(getActiveBits() <= 64 && "Too many bits for uint64_t");
+ return U.pVal[0];
+ }
+
+ /// Get sign extended value
+ ///
+ /// This method attempts to return the value of this APInt as a sign extended
+ /// int64_t. The bit width must be <= 64 or the value must fit within an
+ /// int64_t. Otherwise an assertion will result.
+ int64_t getSExtValue() const {
+ if (isSingleWord())
+ return SignExtend64(U.VAL, BitWidth);
+ assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");
+ return int64_t(U.pVal[0]);
+ }
+
+ /// Get bits required for string value.
+ ///
+ /// This method determines how many bits are required to hold the APInt
+ /// equivalent of the string given by \p str.
+ static unsigned getBitsNeeded(StringRef str, uint8_t radix);
+
+ /// The APInt version of the countLeadingZeros functions in
+ /// MathExtras.h.
+ ///
+ /// It counts the number of zeros from the most significant bit to the first
+ /// one bit.
+ ///
+ /// \returns BitWidth if the value is zero, otherwise returns the number of
+ /// zeros from the most significant bit to the first one bits.
+ unsigned countLeadingZeros() const {
+ if (isSingleWord()) {
+ unsigned unusedBits = APINT_BITS_PER_WORD - BitWidth;
+ return llvm::countLeadingZeros(U.VAL) - unusedBits;
+ }
+ return countLeadingZerosSlowCase();
+ }
+
+ /// Count the number of leading one bits.
+ ///
+ /// This function is an APInt version of the countLeadingOnes
+ /// functions in MathExtras.h. It counts the number of ones from the most
+ /// significant bit to the first zero bit.
+ ///
+ /// \returns 0 if the high order bit is not set, otherwise returns the number
+ /// of 1 bits from the most significant to the least
+ unsigned countLeadingOnes() const {
+ if (isSingleWord())
+ return llvm::countLeadingOnes(U.VAL << (APINT_BITS_PER_WORD - BitWidth));
+ return countLeadingOnesSlowCase();
+ }
+
+ /// Computes the number of leading bits of this APInt that are equal to its
+ /// sign bit.
+ unsigned getNumSignBits() const {
+ return isNegative() ? countLeadingOnes() : countLeadingZeros();
+ }
+
+ /// Count the number of trailing zero bits.
+ ///
+ /// This function is an APInt version of the countTrailingZeros
+ /// functions in MathExtras.h. It counts the number of zeros from the least
+ /// significant bit to the first set bit.
+ ///
+ /// \returns BitWidth if the value is zero, otherwise returns the number of
+ /// zeros from the least significant bit to the first one bit.
+ unsigned countTrailingZeros() const {
+ if (isSingleWord())
+ return std::min(unsigned(llvm::countTrailingZeros(U.VAL)), BitWidth);
+ return countTrailingZerosSlowCase();
+ }
+
+ /// Count the number of trailing one bits.
+ ///
+ /// This function is an APInt version of the countTrailingOnes
+ /// functions in MathExtras.h. It counts the number of ones from the least
+ /// significant bit to the first zero bit.
+ ///
+ /// \returns BitWidth if the value is all ones, otherwise returns the number
+ /// of ones from the least significant bit to the first zero bit.
+ unsigned countTrailingOnes() const {
+ if (isSingleWord())
+ return llvm::countTrailingOnes(U.VAL);
+ return countTrailingOnesSlowCase();
+ }
+
+ /// Count the number of bits set.
+ ///
+ /// This function is an APInt version of the countPopulation functions
+ /// in MathExtras.h. It counts the number of 1 bits in the APInt value.
+ ///
+ /// \returns 0 if the value is zero, otherwise returns the number of set bits.
+ unsigned countPopulation() const {
+ if (isSingleWord())
+ return llvm::countPopulation(U.VAL);
+ return countPopulationSlowCase();
+ }
+
+ /// @}
+ /// \name Conversion Functions
+ /// @{
+ void print(raw_ostream &OS, bool isSigned) const;
+
+ /// Converts an APInt to a string and append it to Str. Str is commonly a
+ /// SmallString.
+ void toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed,
+ bool formatAsCLiteral = false) const;
+
+ /// Considers the APInt to be unsigned and converts it into a string in the
+ /// radix given. The radix can be 2, 8, 10 16, or 36.
+ void toStringUnsigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
+ toString(Str, Radix, false, false);
+ }
+
+ /// Considers the APInt to be signed and converts it into a string in the
+ /// radix given. The radix can be 2, 8, 10, 16, or 36.
+ void toStringSigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
+ toString(Str, Radix, true, false);
+ }
+
+ /// Return 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 to avoid thrashing the heap
+ /// for the string.
+ std::string toString(unsigned Radix, bool Signed) const;
+
+ /// \returns a byte-swapped representation of this APInt Value.
+ APInt byteSwap() const;
+
+ /// \returns the value with the bit representation reversed of this APInt
+ /// Value.
+ APInt reverseBits() const;
+
+ /// Converts this APInt to a double value.
+ double roundToDouble(bool isSigned) const;
+
+ /// Converts this unsigned APInt to a double value.
+ double roundToDouble() const { return roundToDouble(false); }
+
+ /// Converts this signed APInt to a double value.
+ double signedRoundToDouble() const { return roundToDouble(true); }
+
+ /// Converts APInt bits to a double
+ ///
+ /// The conversion does not do a translation from integer to double, it just
+ /// re-interprets the bits as a double. Note that it is valid to do this on
+ /// any bit width. Exactly 64 bits will be translated.
+ double bitsToDouble() const {
+ return BitsToDouble(getWord(0));
+ }
+
+ /// Converts APInt bits to a float
+ ///
+ /// The conversion does not do a translation from integer to float, it just
+ /// re-interprets the bits as a float. Note that it is valid to do this on
+ /// any bit width. Exactly 32 bits will be translated.
+ float bitsToFloat() const {
+ return BitsToFloat(static_cast<uint32_t>(getWord(0)));
+ }
+
+ /// Converts a double to APInt bits.
+ ///
+ /// The conversion does not do a translation from double to integer, it just
+ /// re-interprets the bits of the double.
+ static APInt doubleToBits(double V) {
+ return APInt(sizeof(double) * CHAR_BIT, DoubleToBits(V));
+ }
+
+ /// Converts a float to APInt bits.
+ ///
+ /// The conversion does not do a translation from float to integer, it just
+ /// re-interprets the bits of the float.
+ static APInt floatToBits(float V) {
+ return APInt(sizeof(float) * CHAR_BIT, FloatToBits(V));
+ }
+
+ /// @}
+ /// \name Mathematics Operations
+ /// @{
+
+ /// \returns the floor log base 2 of this APInt.
+ unsigned logBase2() const { return getActiveBits() - 1; }
+
+ /// \returns the ceil log base 2 of this APInt.
+ unsigned ceilLogBase2() const {
+ APInt temp(*this);
+ --temp;
+ return temp.getActiveBits();
+ }
+
+ /// \returns the nearest log base 2 of this APInt. Ties round up.
+ ///
+ /// NOTE: When we have a BitWidth of 1, we define:
+ ///
+ /// log2(0) = UINT32_MAX
+ /// log2(1) = 0
+ ///
+ /// to get around any mathematical concerns resulting from
+ /// referencing 2 in a space where 2 does no exist.
+ unsigned nearestLogBase2() const {
+ // Special case when we have a bitwidth of 1. If VAL is 1, then we
+ // get 0. If VAL is 0, we get WORDTYPE_MAX which gets truncated to
+ // UINT32_MAX.
+ if (BitWidth == 1)
+ return U.VAL - 1;
+
+ // Handle the zero case.
+ if (isNullValue())
+ return UINT32_MAX;
+
+ // The non-zero case is handled by computing:
+ //
+ // nearestLogBase2(x) = logBase2(x) + x[logBase2(x)-1].
+ //
+ // where x[i] is referring to the value of the ith bit of x.
+ unsigned lg = logBase2();
+ return lg + unsigned((*this)[lg - 1]);
+ }
+
+ /// \returns the log base 2 of this APInt if its an exact power of two, -1
+ /// otherwise
+ int32_t exactLogBase2() const {
+ if (!isPowerOf2())
+ return -1;
+ return logBase2();
+ }
+
+ /// Compute the square root
+ APInt sqrt() const;
+
+ /// Get the absolute value;
+ ///
+ /// If *this is < 0 then return -(*this), otherwise *this;
+ APInt abs() const {
+ if (isNegative())
+ return -(*this);
+ return *this;
+ }
+
+ /// \returns the multiplicative inverse for a given modulo.
+ APInt multiplicativeInverse(const APInt &modulo) const;
+
+ /// @}
+ /// \name Support for division by constant
+ /// @{
+
+ /// Calculate the magic number for signed division by a constant.
+ struct ms;
+ ms magic() const;
+
+ /// Calculate the magic number for unsigned division by a constant.
+ struct mu;
+ mu magicu(unsigned LeadingZeros = 0) const;
+
+ /// @}
+ /// \name Building-block Operations for APInt and APFloat
+ /// @{
+
+ // These building block operations operate on a representation of arbitrary
+ // precision, two's-complement, bignum integer values. They should be
+ // sufficient to implement APInt and APFloat bignum requirements. Inputs are
+ // generally a pointer to the base of an array of integer parts, representing
+ // an unsigned bignum, and a count of how many parts there are.
+
+ /// Sets the least significant part of a bignum to the input value, and zeroes
+ /// out higher parts.
+ static void tcSet(WordType *, WordType, unsigned);
+
+ /// Assign one bignum to another.
+ static void tcAssign(WordType *, const WordType *, unsigned);
+
+ /// Returns true if a bignum is zero, false otherwise.
+ static bool tcIsZero(const WordType *, unsigned);
+
+ /// Extract the given bit of a bignum; returns 0 or 1. Zero-based.
+ static int tcExtractBit(const WordType *, unsigned bit);
+
+ /// 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.
+ static void tcExtract(WordType *, unsigned dstCount,
+ const WordType *, unsigned srcBits,
+ unsigned srcLSB);
+
+ /// Set the given bit of a bignum. Zero-based.
+ static void tcSetBit(WordType *, unsigned bit);
+
+ /// Clear the given bit of a bignum. Zero-based.
+ static void tcClearBit(WordType *, unsigned bit);
+
+ /// Returns the bit number of the least or most significant set bit of a
+ /// number. If the input number has no bits set -1U is returned.
+ static unsigned tcLSB(const WordType *, unsigned n);
+ static unsigned tcMSB(const WordType *parts, unsigned n);
+
+ /// Negate a bignum in-place.
+ static void tcNegate(WordType *, unsigned);
+
+ /// DST += RHS + CARRY where CARRY is zero or one. Returns the carry flag.
+ static WordType tcAdd(WordType *, const WordType *,
+ WordType carry, unsigned);
+ /// DST += RHS. Returns the carry flag.
+ static WordType tcAddPart(WordType *, WordType, unsigned);
+
+ /// DST -= RHS + CARRY where CARRY is zero or one. Returns the carry flag.
+ static WordType tcSubtract(WordType *, const WordType *,
+ WordType carry, unsigned);
+ /// DST -= RHS. Returns the carry flag.
+ static WordType tcSubtractPart(WordType *, WordType, unsigned);
+
+ /// DST += SRC * MULTIPLIER + PART if add is true
+ /// DST = SRC * MULTIPLIER + PART 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 == SRC_PARTS + 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.
+ static int tcMultiplyPart(WordType *dst, const WordType *src,
+ WordType multiplier, WordType carry,
+ unsigned srcParts, unsigned dstParts,
+ bool add);
+
+ /// 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.
+ static int tcMultiply(WordType *, const WordType *, const WordType *,
+ unsigned);
+
+ /// 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.
+ static void tcFullMultiply(WordType *, const WordType *,
+ const WordType *, unsigned, unsigned);
+
+ /// 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.
+ static int tcDivide(WordType *lhs, const WordType *rhs,
+ WordType *remainder, WordType *scratch,
+ unsigned parts);
+
+ /// Shift a bignum left Count bits. Shifted in bits are zero. There are no
+ /// restrictions on Count.
+ static void tcShiftLeft(WordType *, unsigned Words, unsigned Count);
+
+ /// Shift a bignum right Count bits. Shifted in bits are zero. There are no
+ /// restrictions on Count.
+ static void tcShiftRight(WordType *, unsigned Words, unsigned Count);
+
+ /// The obvious AND, OR and XOR and complement operations.
+ static void tcAnd(WordType *, const WordType *, unsigned);
+ static void tcOr(WordType *, const WordType *, unsigned);
+ static void tcXor(WordType *, const WordType *, unsigned);
+ static void tcComplement(WordType *, unsigned);
+
+ /// Comparison (unsigned) of two bignums.
+ static int tcCompare(const WordType *, const WordType *, unsigned);
+
+ /// Increment a bignum in-place. Return the carry flag.
+ static WordType tcIncrement(WordType *dst, unsigned parts) {
+ return tcAddPart(dst, 1, parts);
+ }
+
+ /// Decrement a bignum in-place. Return the borrow flag.
+ static WordType tcDecrement(WordType *dst, unsigned parts) {
+ return tcSubtractPart(dst, 1, parts);
+ }
+
+ /// Set the least significant BITS and clear the rest.
+ static void tcSetLeastSignificantBits(WordType *, unsigned, unsigned bits);
+
+ /// debug method
+ void dump() const;
+
+ /// @}
+};
+
+/// Magic data for optimising signed division by a constant.
+struct APInt::ms {
+ APInt m; ///< magic number
+ unsigned s; ///< shift amount
+};
+
+/// Magic data for optimising unsigned division by a constant.
+struct APInt::mu {
+ APInt m; ///< magic number
+ bool a; ///< add indicator
+ unsigned s; ///< shift amount
+};
+
+inline bool operator==(uint64_t V1, const APInt &V2) { return V2 == V1; }
+
+inline bool operator!=(uint64_t V1, const APInt &V2) { return V2 != V1; }
+
+/// Unary bitwise complement operator.
+///
+/// \returns an APInt that is the bitwise complement of \p v.
+inline APInt operator~(APInt v) {
+ v.flipAllBits();
+ return v;
+}
+
+inline APInt operator&(APInt a, const APInt &b) {
+ a &= b;
+ return a;
+}
+
+inline APInt operator&(const APInt &a, APInt &&b) {
+ b &= a;
+ return std::move(b);
+}
+
+inline APInt operator&(APInt a, uint64_t RHS) {
+ a &= RHS;
+ return a;
+}
+
+inline APInt operator&(uint64_t LHS, APInt b) {
+ b &= LHS;
+ return b;
+}
+
+inline APInt operator|(APInt a, const APInt &b) {
+ a |= b;
+ return a;
+}
+
+inline APInt operator|(const APInt &a, APInt &&b) {
+ b |= a;
+ return std::move(b);
+}
+
+inline APInt operator|(APInt a, uint64_t RHS) {
+ a |= RHS;
+ return a;
+}
+
+inline APInt operator|(uint64_t LHS, APInt b) {
+ b |= LHS;
+ return b;
+}
+
+inline APInt operator^(APInt a, const APInt &b) {
+ a ^= b;
+ return a;
+}
+
+inline APInt operator^(const APInt &a, APInt &&b) {
+ b ^= a;
+ return std::move(b);
+}
+
+inline APInt operator^(APInt a, uint64_t RHS) {
+ a ^= RHS;
+ return a;
+}
+
+inline APInt operator^(uint64_t LHS, APInt b) {
+ b ^= LHS;
+ return b;
+}
+
+inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) {
+ I.print(OS, true);
+ return OS;
+}
+
+inline APInt operator-(APInt v) {
+ v.negate();
+ return v;
+}
+
+inline APInt operator+(APInt a, const APInt &b) {
+ a += b;
+ return a;
+}
+
+inline APInt operator+(const APInt &a, APInt &&b) {
+ b += a;
+ return std::move(b);
+}
+
+inline APInt operator+(APInt a, uint64_t RHS) {
+ a += RHS;
+ return a;
+}
+
+inline APInt operator+(uint64_t LHS, APInt b) {
+ b += LHS;
+ return b;
+}
+
+inline APInt operator-(APInt a, const APInt &b) {
+ a -= b;
+ return a;
+}
+
+inline APInt operator-(const APInt &a, APInt &&b) {
+ b.negate();
+ b += a;
+ return std::move(b);
+}
+
+inline APInt operator-(APInt a, uint64_t RHS) {
+ a -= RHS;
+ return a;
+}
+
+inline APInt operator-(uint64_t LHS, APInt b) {
+ b.negate();
+ b += LHS;
+ return b;
+}
+
+inline APInt operator*(APInt a, uint64_t RHS) {
+ a *= RHS;
+ return a;
+}
+
+inline APInt operator*(uint64_t LHS, APInt b) {
+ b *= LHS;
+ return b;
+}
+
+
+namespace APIntOps {
+
+/// Determine the smaller of two APInts considered to be signed.
+inline const APInt &smin(const APInt &A, const APInt &B) {
+ return A.slt(B) ? A : B;
+}
+
+/// Determine the larger of two APInts considered to be signed.
+inline const APInt &smax(const APInt &A, const APInt &B) {
+ return A.sgt(B) ? A : B;
+}
+
+/// Determine the smaller of two APInts considered to be signed.
+inline const APInt &umin(const APInt &A, const APInt &B) {
+ return A.ult(B) ? A : B;
+}
+
+/// Determine the larger of two APInts considered to be unsigned.
+inline const APInt &umax(const APInt &A, const APInt &B) {
+ return A.ugt(B) ? A : B;
+}
+
+/// Compute GCD of two unsigned APInt values.
+///
+/// This function returns the greatest common divisor of the two APInt values
+/// using Stein's algorithm.
+///
+/// \returns the greatest common divisor of A and B.
+APInt GreatestCommonDivisor(APInt A, APInt B);
+
+/// Converts the given APInt to a double value.
+///
+/// Treats the APInt as an unsigned value for conversion purposes.
+inline double RoundAPIntToDouble(const APInt &APIVal) {
+ return APIVal.roundToDouble();
+}
+
+/// Converts the given APInt to a double value.
+///
+/// Treats the APInt as a signed value for conversion purposes.
+inline double RoundSignedAPIntToDouble(const APInt &APIVal) {
+ return APIVal.signedRoundToDouble();
+}
+
+/// Converts the given APInt to a float vlalue.
+inline float RoundAPIntToFloat(const APInt &APIVal) {
+ return float(RoundAPIntToDouble(APIVal));
+}
+
+/// Converts the given APInt to a float value.
+///
+/// Treats the APInt as a signed value for conversion purposes.
+inline float RoundSignedAPIntToFloat(const APInt &APIVal) {
+ return float(APIVal.signedRoundToDouble());
+}
+
+/// Converts the given double value into a APInt.
+///
+/// This function convert a double value to an APInt value.
+APInt RoundDoubleToAPInt(double Double, unsigned width);
+
+/// Converts a float value into a APInt.
+///
+/// Converts a float value into an APInt value.
+inline APInt RoundFloatToAPInt(float Float, unsigned width) {
+ return RoundDoubleToAPInt(double(Float), width);
+}
+
+/// Return A unsign-divided by B, rounded by the given rounding mode.
+APInt RoundingUDiv(const APInt &A, const APInt &B, APInt::Rounding RM);
+
+/// Return A sign-divided by B, rounded by the given rounding mode.
+APInt RoundingSDiv(const APInt &A, const APInt &B, APInt::Rounding RM);
+
+/// Let q(n) = An^2 + Bn + C, and BW = bit width of the value range
+/// (e.g. 32 for i32).
+/// This function finds the smallest number n, such that
+/// (a) n >= 0 and q(n) = 0, or
+/// (b) n >= 1 and q(n-1) and q(n), when evaluated in the set of all
+/// integers, belong to two different intervals [Rk, Rk+R),
+/// where R = 2^BW, and k is an integer.
+/// The idea here is to find when q(n) "overflows" 2^BW, while at the
+/// same time "allowing" subtraction. In unsigned modulo arithmetic a
+/// subtraction (treated as addition of negated numbers) would always
+/// count as an overflow, but here we want to allow values to decrease
+/// and increase as long as they are within the same interval.
+/// Specifically, adding of two negative numbers should not cause an
+/// overflow (as long as the magnitude does not exceed the bit width).
+/// On the other hand, given a positive number, adding a negative
+/// number to it can give a negative result, which would cause the
+/// value to go from [-2^BW, 0) to [0, 2^BW). In that sense, zero is
+/// treated as a special case of an overflow.
+///
+/// This function returns None if after finding k that minimizes the
+/// positive solution to q(n) = kR, both solutions are contained between
+/// two consecutive integers.
+///
+/// There are cases where q(n) > T, and q(n+1) < T (assuming evaluation
+/// in arithmetic modulo 2^BW, and treating the values as signed) by the
+/// virtue of *signed* overflow. This function will *not* find such an n,
+/// however it may find a value of n satisfying the inequalities due to
+/// an *unsigned* overflow (if the values are treated as unsigned).
+/// To find a solution for a signed overflow, treat it as a problem of
+/// finding an unsigned overflow with a range with of BW-1.
+///
+/// The returned value may have a different bit width from the input
+/// coefficients.
+Optional<APInt> SolveQuadraticEquationWrap(APInt A, APInt B, APInt C,
+ unsigned RangeWidth);
+
+/// Compare two values, and if they are different, return the position of the
+/// most significant bit that is different in the values.
+Optional<unsigned> GetMostSignificantDifferentBit(const APInt &A,
+ const APInt &B);
+
+} // End of APIntOps namespace
+
+// See friend declaration above. This additional declaration is required in
+// order to compile LLVM with IBM xlC compiler.
+hash_code hash_value(const APInt &Arg);
+
+/// StoreIntToMemory - Fills the StoreBytes bytes of memory starting from Dst
+/// with the integer held in IntVal.
+void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, unsigned StoreBytes);
+
+/// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting
+/// from Src into IntVal, which is assumed to be wide enough and to hold zero.
+void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes);
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/ADT/APSInt.h b/third_party/llvm-project/include/llvm/ADT/APSInt.h
new file mode 100644
index 000000000..0f991826c
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/APSInt.h
@@ -0,0 +1,353 @@
+//===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the APSInt class, which is a simple class that
+// represents an arbitrary sized integer that knows its signedness.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_APSINT_H
+#define LLVM_ADT_APSINT_H
+
+#include "llvm/ADT/APInt.h"
+
+namespace llvm {
+
+class LLVM_NODISCARD APSInt : public APInt {
+ bool IsUnsigned;
+
+public:
+ /// Default constructor that creates an uninitialized APInt.
+ explicit APSInt() : IsUnsigned(false) {}
+
+ /// APSInt ctor - Create an APSInt with the specified width, default to
+ /// unsigned.
+ explicit APSInt(uint32_t BitWidth, bool isUnsigned = true)
+ : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {}
+
+ explicit APSInt(APInt I, bool isUnsigned = true)
+ : APInt(std::move(I)), IsUnsigned(isUnsigned) {}
+
+ /// Construct an APSInt from a string representation.
+ ///
+ /// This constructor interprets the string \p Str using the radix of 10.
+ /// The interpretation stops at the end of the string. The bit width of the
+ /// constructed APSInt is determined automatically.
+ ///
+ /// \param Str the string to be interpreted.
+ explicit APSInt(StringRef Str);
+
+ /// Determine sign of this APSInt.
+ ///
+ /// \returns true if this APSInt is negative, false otherwise
+ bool isNegative() const { return isSigned() && APInt::isNegative(); }
+
+ /// Determine if this APSInt Value is non-negative (>= 0)
+ ///
+ /// \returns true if this APSInt is non-negative, false otherwise
+ bool isNonNegative() const { return !isNegative(); }
+
+ /// Determine if this APSInt Value is positive.
+ ///
+ /// This tests if the value of this APSInt is positive (> 0). Note
+ /// that 0 is not a positive value.
+ ///
+ /// \returns true if this APSInt is positive.
+ bool isStrictlyPositive() const { return isNonNegative() && !isNullValue(); }
+
+ APSInt &operator=(APInt RHS) {
+ // Retain our current sign.
+ APInt::operator=(std::move(RHS));
+ return *this;
+ }
+
+ APSInt &operator=(uint64_t RHS) {
+ // Retain our current sign.
+ APInt::operator=(RHS);
+ return *this;
+ }
+
+ // Query sign information.
+ bool isSigned() const { return !IsUnsigned; }
+ bool isUnsigned() const { return IsUnsigned; }
+ void setIsUnsigned(bool Val) { IsUnsigned = Val; }
+ void setIsSigned(bool Val) { IsUnsigned = !Val; }
+
+ /// toString - Append this APSInt to the specified SmallString.
+ void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
+ APInt::toString(Str, Radix, isSigned());
+ }
+ /// toString - Converts an APInt to a std::string. This is an inefficient
+ /// method; you should prefer passing in a SmallString instead.
+ std::string toString(unsigned Radix) const {
+ return APInt::toString(Radix, isSigned());
+ }
+ using APInt::toString;
+
+ /// Get the correctly-extended \c int64_t value.
+ int64_t getExtValue() const {
+ assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");
+ return isSigned() ? getSExtValue() : getZExtValue();
+ }
+
+ APSInt trunc(uint32_t width) const {
+ return APSInt(APInt::trunc(width), IsUnsigned);
+ }
+
+ APSInt extend(uint32_t width) const {
+ if (IsUnsigned)
+ return APSInt(zext(width), IsUnsigned);
+ else
+ return APSInt(sext(width), IsUnsigned);
+ }
+
+ APSInt extOrTrunc(uint32_t width) const {
+ if (IsUnsigned)
+ return APSInt(zextOrTrunc(width), IsUnsigned);
+ else
+ return APSInt(sextOrTrunc(width), IsUnsigned);
+ }
+
+ const APSInt &operator%=(const APSInt &RHS) {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ if (IsUnsigned)
+ *this = urem(RHS);
+ else
+ *this = srem(RHS);
+ return *this;
+ }
+ const APSInt &operator/=(const APSInt &RHS) {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ if (IsUnsigned)
+ *this = udiv(RHS);
+ else
+ *this = sdiv(RHS);
+ return *this;
+ }
+ APSInt operator%(const APSInt &RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false);
+ }
+ APSInt operator/(const APSInt &RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false);
+ }
+
+ APSInt operator>>(unsigned Amt) const {
+ return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false);
+ }
+ APSInt& operator>>=(unsigned Amt) {
+ if (IsUnsigned)
+ lshrInPlace(Amt);
+ else
+ ashrInPlace(Amt);
+ return *this;
+ }
+
+ inline bool operator<(const APSInt& RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return IsUnsigned ? ult(RHS) : slt(RHS);
+ }
+ inline bool operator>(const APSInt& RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return IsUnsigned ? ugt(RHS) : sgt(RHS);
+ }
+ inline bool operator<=(const APSInt& RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return IsUnsigned ? ule(RHS) : sle(RHS);
+ }
+ inline bool operator>=(const APSInt& RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return IsUnsigned ? uge(RHS) : sge(RHS);
+ }
+ inline bool operator==(const APSInt& RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return eq(RHS);
+ }
+ inline bool operator!=(const APSInt& RHS) const {
+ return !((*this) == RHS);
+ }
+
+ bool operator==(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) == 0;
+ }
+ bool operator!=(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) != 0;
+ }
+ bool operator<=(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) <= 0;
+ }
+ bool operator>=(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) >= 0;
+ }
+ bool operator<(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) < 0;
+ }
+ bool operator>(int64_t RHS) const {
+ return compareValues(*this, get(RHS)) > 0;
+ }
+
+ // The remaining operators just wrap the logic of APInt, but retain the
+ // signedness information.
+
+ APSInt operator<<(unsigned Bits) const {
+ return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned);
+ }
+ APSInt& operator<<=(unsigned Amt) {
+ static_cast<APInt&>(*this) <<= Amt;
+ return *this;
+ }
+
+ APSInt& operator++() {
+ ++(static_cast<APInt&>(*this));
+ return *this;
+ }
+ APSInt& operator--() {
+ --(static_cast<APInt&>(*this));
+ return *this;
+ }
+ APSInt operator++(int) {
+ return APSInt(++static_cast<APInt&>(*this), IsUnsigned);
+ }
+ APSInt operator--(int) {
+ return APSInt(--static_cast<APInt&>(*this), IsUnsigned);
+ }
+ APSInt operator-() const {
+ return APSInt(-static_cast<const APInt&>(*this), IsUnsigned);
+ }
+ APSInt& operator+=(const APSInt& RHS) {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ static_cast<APInt&>(*this) += RHS;
+ return *this;
+ }
+ APSInt& operator-=(const APSInt& RHS) {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ static_cast<APInt&>(*this) -= RHS;
+ return *this;
+ }
+ APSInt& operator*=(const APSInt& RHS) {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ static_cast<APInt&>(*this) *= RHS;
+ return *this;
+ }
+ APSInt& operator&=(const APSInt& RHS) {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ static_cast<APInt&>(*this) &= RHS;
+ return *this;
+ }
+ APSInt& operator|=(const APSInt& RHS) {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ static_cast<APInt&>(*this) |= RHS;
+ return *this;
+ }
+ APSInt& operator^=(const APSInt& RHS) {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ static_cast<APInt&>(*this) ^= RHS;
+ return *this;
+ }
+
+ APSInt operator&(const APSInt& RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned);
+ }
+
+ APSInt operator|(const APSInt& RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned);
+ }
+
+ APSInt operator^(const APSInt &RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned);
+ }
+
+ APSInt operator*(const APSInt& RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned);
+ }
+ APSInt operator+(const APSInt& RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned);
+ }
+ APSInt operator-(const APSInt& RHS) const {
+ assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
+ return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned);
+ }
+ APSInt operator~() const {
+ return APSInt(~static_cast<const APInt&>(*this), IsUnsigned);
+ }
+
+ /// getMaxValue - Return the APSInt representing the maximum integer value
+ /// with the given bit width and signedness.
+ static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
+ return APSInt(Unsigned ? APInt::getMaxValue(numBits)
+ : APInt::getSignedMaxValue(numBits), Unsigned);
+ }
+
+ /// getMinValue - Return the APSInt representing the minimum integer value
+ /// with the given bit width and signedness.
+ static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
+ return APSInt(Unsigned ? APInt::getMinValue(numBits)
+ : APInt::getSignedMinValue(numBits), Unsigned);
+ }
+
+ /// Determine if two APSInts have the same value, zero- or
+ /// sign-extending as needed.
+ static bool isSameValue(const APSInt &I1, const APSInt &I2) {
+ return !compareValues(I1, I2);
+ }
+
+ /// Compare underlying values of two numbers.
+ static int compareValues(const APSInt &I1, const APSInt &I2) {
+ if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
+ return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2);
+
+ // Check for a bit-width mismatch.
+ if (I1.getBitWidth() > I2.getBitWidth())
+ return compareValues(I1, I2.extend(I1.getBitWidth()));
+ if (I2.getBitWidth() > I1.getBitWidth())
+ return compareValues(I1.extend(I2.getBitWidth()), I2);
+
+ // We have a signedness mismatch. Check for negative values and do an
+ // unsigned compare if both are positive.
+ if (I1.isSigned()) {
+ assert(!I2.isSigned() && "Expected signed mismatch");
+ if (I1.isNegative())
+ return -1;
+ } else {
+ assert(I2.isSigned() && "Expected signed mismatch");
+ if (I2.isNegative())
+ return 1;
+ }
+
+ return I1.compare(I2);
+ }
+
+ static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
+ static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); }
+
+ /// Profile - Used to insert APSInt objects, or objects that contain APSInt
+ /// objects, into FoldingSets.
+ void Profile(FoldingSetNodeID& ID) const;
+};
+
+inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; }
+inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; }
+inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
+inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; }
+inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; }
+inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; }
+
+inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
+ I.print(OS, I.isSigned());
+ return OS;
+}
+
+} // end namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/ADT/AllocatorList.h b/third_party/llvm-project/include/llvm/ADT/AllocatorList.h
new file mode 100644
index 000000000..405a2e426
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/AllocatorList.h
@@ -0,0 +1,240 @@
+//===- llvm/ADT/AllocatorList.h - Custom allocator list ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ALLOCATORLIST_H
+#define LLVM_ADT_ALLOCATORLIST_H
+
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/simple_ilist.h"
+#include "llvm/Support/Allocator.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+
+namespace llvm {
+
+/// A linked-list with a custom, local allocator.
+///
+/// Expose a std::list-like interface that owns and uses a custom LLVM-style
+/// allocator (e.g., BumpPtrAllocator), leveraging \a simple_ilist for the
+/// implementation details.
+///
+/// Because this list owns the allocator, calling \a splice() with a different
+/// list isn't generally safe. As such, \a splice has been left out of the
+/// interface entirely.
+template <class T, class AllocatorT> class AllocatorList : AllocatorT {
+ struct Node : ilist_node<Node> {
+ Node(Node &&) = delete;
+ Node(const Node &) = delete;
+ Node &operator=(Node &&) = delete;
+ Node &operator=(const Node &) = delete;
+
+ Node(T &&V) : V(std::move(V)) {}
+ Node(const T &V) : V(V) {}
+ template <class... Ts> Node(Ts &&... Vs) : V(std::forward<Ts>(Vs)...) {}
+ T V;
+ };
+
+ using list_type = simple_ilist<Node>;
+
+ list_type List;
+
+ AllocatorT &getAlloc() { return *this; }
+ const AllocatorT &getAlloc() const { return *this; }
+
+ template <class... ArgTs> Node *create(ArgTs &&... Args) {
+ return new (getAlloc()) Node(std::forward<ArgTs>(Args)...);
+ }
+
+ struct Cloner {
+ AllocatorList &AL;
+
+ Cloner(AllocatorList &AL) : AL(AL) {}
+
+ Node *operator()(const Node &N) const { return AL.create(N.V); }
+ };
+
+ struct Disposer {
+ AllocatorList &AL;
+
+ Disposer(AllocatorList &AL) : AL(AL) {}
+
+ void operator()(Node *N) const {
+ N->~Node();
+ AL.getAlloc().Deallocate(N);
+ }
+ };
+
+public:
+ using value_type = T;
+ using pointer = T *;
+ using reference = T &;
+ using const_pointer = const T *;
+ using const_reference = const T &;
+ using size_type = typename list_type::size_type;
+ using difference_type = typename list_type::difference_type;
+
+private:
+ template <class ValueT, class IteratorBase>
+ class IteratorImpl
+ : public iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>,
+ IteratorBase,
+ std::bidirectional_iterator_tag, ValueT> {
+ template <class OtherValueT, class OtherIteratorBase>
+ friend class IteratorImpl;
+ friend AllocatorList;
+
+ using base_type =
+ iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>, IteratorBase,
+ std::bidirectional_iterator_tag, ValueT>;
+
+ public:
+ using value_type = ValueT;
+ using pointer = ValueT *;
+ using reference = ValueT &;
+
+ IteratorImpl() = default;
+ IteratorImpl(const IteratorImpl &) = default;
+ IteratorImpl &operator=(const IteratorImpl &) = default;
+
+ explicit IteratorImpl(const IteratorBase &I) : base_type(I) {}
+
+ template <class OtherValueT, class OtherIteratorBase>
+ IteratorImpl(const IteratorImpl<OtherValueT, OtherIteratorBase> &X,
+ typename std::enable_if<std::is_convertible<
+ OtherIteratorBase, IteratorBase>::value>::type * = nullptr)
+ : base_type(X.wrapped()) {}
+
+ ~IteratorImpl() = default;
+
+ reference operator*() const { return base_type::wrapped()->V; }
+ pointer operator->() const { return &operator*(); }
+
+ friend bool operator==(const IteratorImpl &L, const IteratorImpl &R) {
+ return L.wrapped() == R.wrapped();
+ }
+ friend bool operator!=(const IteratorImpl &L, const IteratorImpl &R) {
+ return !(L == R);
+ }
+ };
+
+public:
+ using iterator = IteratorImpl<T, typename list_type::iterator>;
+ using reverse_iterator =
+ IteratorImpl<T, typename list_type::reverse_iterator>;
+ using const_iterator =
+ IteratorImpl<const T, typename list_type::const_iterator>;
+ using const_reverse_iterator =
+ IteratorImpl<const T, typename list_type::const_reverse_iterator>;
+
+ AllocatorList() = default;
+ AllocatorList(AllocatorList &&X)
+ : AllocatorT(std::move(X.getAlloc())), List(std::move(X.List)) {}
+
+ AllocatorList(const AllocatorList &X) {
+ List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
+ }
+
+ AllocatorList &operator=(AllocatorList &&X) {
+ clear(); // Dispose of current nodes explicitly.
+ List = std::move(X.List);
+ getAlloc() = std::move(X.getAlloc());
+ return *this;
+ }
+
+ AllocatorList &operator=(const AllocatorList &X) {
+ List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
+ return *this;
+ }
+
+ ~AllocatorList() { clear(); }
+
+ void swap(AllocatorList &RHS) {
+ List.swap(RHS.List);
+ std::swap(getAlloc(), RHS.getAlloc());
+ }
+
+ bool empty() { return List.empty(); }
+ size_t size() { return List.size(); }
+
+ iterator begin() { return iterator(List.begin()); }
+ iterator end() { return iterator(List.end()); }
+ const_iterator begin() const { return const_iterator(List.begin()); }
+ const_iterator end() const { return const_iterator(List.end()); }
+ reverse_iterator rbegin() { return reverse_iterator(List.rbegin()); }
+ reverse_iterator rend() { return reverse_iterator(List.rend()); }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(List.rbegin());
+ }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(List.rend());
+ }
+
+ T &back() { return List.back().V; }
+ T &front() { return List.front().V; }
+ const T &back() const { return List.back().V; }
+ const T &front() const { return List.front().V; }
+
+ template <class... Ts> iterator emplace(iterator I, Ts &&... Vs) {
+ return iterator(List.insert(I.wrapped(), *create(std::forward<Ts>(Vs)...)));
+ }
+
+ iterator insert(iterator I, T &&V) {
+ return iterator(List.insert(I.wrapped(), *create(std::move(V))));
+ }
+ iterator insert(iterator I, const T &V) {
+ return iterator(List.insert(I.wrapped(), *create(V)));
+ }
+
+ template <class Iterator>
+ void insert(iterator I, Iterator First, Iterator Last) {
+ for (; First != Last; ++First)
+ List.insert(I.wrapped(), *create(*First));
+ }
+
+ iterator erase(iterator I) {
+ return iterator(List.eraseAndDispose(I.wrapped(), Disposer(*this)));
+ }
+
+ iterator erase(iterator First, iterator Last) {
+ return iterator(
+ List.eraseAndDispose(First.wrapped(), Last.wrapped(), Disposer(*this)));
+ }
+
+ void clear() { List.clearAndDispose(Disposer(*this)); }
+ void pop_back() { List.eraseAndDispose(--List.end(), Disposer(*this)); }
+ void pop_front() { List.eraseAndDispose(List.begin(), Disposer(*this)); }
+ void push_back(T &&V) { insert(end(), std::move(V)); }
+ void push_front(T &&V) { insert(begin(), std::move(V)); }
+ void push_back(const T &V) { insert(end(), V); }
+ void push_front(const T &V) { insert(begin(), V); }
+ template <class... Ts> void emplace_back(Ts &&... Vs) {
+ emplace(end(), std::forward<Ts>(Vs)...);
+ }
+ template <class... Ts> void emplace_front(Ts &&... Vs) {
+ emplace(begin(), std::forward<Ts>(Vs)...);
+ }
+
+ /// Reset the underlying allocator.
+ ///
+ /// \pre \c empty()
+ void resetAlloc() {
+ assert(empty() && "Cannot reset allocator if not empty");
+ getAlloc().Reset();
+ }
+};
+
+template <class T> using BumpPtrList = AllocatorList<T, BumpPtrAllocator>;
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_ALLOCATORLIST_H
diff --git a/third_party/llvm-project/include/llvm/ADT/ArrayRef.h b/third_party/llvm-project/include/llvm/ADT/ArrayRef.h
new file mode 100644
index 000000000..f6455d3fa
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/ArrayRef.h
@@ -0,0 +1,540 @@
+//===- ArrayRef.h - Array Reference Wrapper ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ARRAYREF_H
+#define LLVM_ADT_ARRAYREF_H
+
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Compiler.h"
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <initializer_list>
+#include <iterator>
+#include <memory>
+#include <type_traits>
+#include <vector>
+
+namespace llvm {
+
+ /// ArrayRef - Represent a constant reference to an array (0 or more elements
+ /// consecutively in memory), i.e. a start pointer and a length. It allows
+ /// various APIs to take consecutive elements easily and conveniently.
+ ///
+ /// This class does not own the underlying data, it is expected to be used in
+ /// situations where the data resides in some other buffer, whose lifetime
+ /// extends past that of the ArrayRef. For this reason, it is not in general
+ /// safe to store an ArrayRef.
+ ///
+ /// This is intended to be trivially copyable, so it should be passed by
+ /// value.
+ template<typename T>
+ class LLVM_NODISCARD ArrayRef {
+ public:
+ using iterator = const T *;
+ using const_iterator = const T *;
+ using size_type = size_t;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+
+ private:
+ /// The start of the array, in an external buffer.
+ const T *Data = nullptr;
+
+ /// The number of elements.
+ size_type Length = 0;
+
+ public:
+ /// @name Constructors
+ /// @{
+
+ /// Construct an empty ArrayRef.
+ /*implicit*/ ArrayRef() = default;
+
+ /// Construct an empty ArrayRef from None.
+ /*implicit*/ ArrayRef(NoneType) {}
+
+ /// Construct an ArrayRef from a single element.
+ /*implicit*/ ArrayRef(const T &OneElt)
+ : Data(&OneElt), Length(1) {}
+
+ /// Construct an ArrayRef from a pointer and length.
+ /*implicit*/ ArrayRef(const T *data, size_t length)
+ : Data(data), Length(length) {}
+
+ /// Construct an ArrayRef from a range.
+ ArrayRef(const T *begin, const T *end)
+ : Data(begin), Length(end - begin) {}
+
+ /// Construct an ArrayRef from a SmallVector. This is templated in order to
+ /// avoid instantiating SmallVectorTemplateCommon<T> whenever we
+ /// copy-construct an ArrayRef.
+ template<typename U>
+ /*implicit*/ ArrayRef(const SmallVectorTemplateCommon<T, U> &Vec)
+ : Data(Vec.data()), Length(Vec.size()) {
+ }
+
+ /// Construct an ArrayRef from a std::vector.
+ template<typename A>
+ /*implicit*/ ArrayRef(const std::vector<T, A> &Vec)
+ : Data(Vec.data()), Length(Vec.size()) {}
+
+ /// Construct an ArrayRef from a std::array
+ template <size_t N>
+ /*implicit*/ constexpr ArrayRef(const std::array<T, N> &Arr)
+ : Data(Arr.data()), Length(N) {}
+
+ /// Construct an ArrayRef from a C array.
+ template <size_t N>
+ /*implicit*/ constexpr ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {}
+
+ /// Construct an ArrayRef from a std::initializer_list.
+ /*implicit*/ ArrayRef(const std::initializer_list<T> &Vec)
+ : Data(Vec.begin() == Vec.end() ? (T*)nullptr : Vec.begin()),
+ Length(Vec.size()) {}
+
+ /// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
+ /// ensure that only ArrayRefs of pointers can be converted.
+ template <typename U>
+ ArrayRef(
+ const ArrayRef<U *> &A,
+ typename std::enable_if<
+ std::is_convertible<U *const *, T const *>::value>::type * = nullptr)
+ : Data(A.data()), Length(A.size()) {}
+
+ /// Construct an ArrayRef<const T*> from a SmallVector<T*>. This is
+ /// templated in order to avoid instantiating SmallVectorTemplateCommon<T>
+ /// whenever we copy-construct an ArrayRef.
+ template<typename U, typename DummyT>
+ /*implicit*/ ArrayRef(
+ const SmallVectorTemplateCommon<U *, DummyT> &Vec,
+ typename std::enable_if<
+ std::is_convertible<U *const *, T const *>::value>::type * = nullptr)
+ : Data(Vec.data()), Length(Vec.size()) {
+ }
+
+ /// Construct an ArrayRef<const T*> from std::vector<T*>. This uses SFINAE
+ /// to ensure that only vectors of pointers can be converted.
+ template<typename U, typename A>
+ ArrayRef(const std::vector<U *, A> &Vec,
+ typename std::enable_if<
+ std::is_convertible<U *const *, T const *>::value>::type* = 0)
+ : Data(Vec.data()), Length(Vec.size()) {}
+
+ /// @}
+ /// @name Simple Operations
+ /// @{
+
+ iterator begin() const { return Data; }
+ iterator end() const { return Data + Length; }
+
+ reverse_iterator rbegin() const { return reverse_iterator(end()); }
+ reverse_iterator rend() const { return reverse_iterator(begin()); }
+
+ /// empty - Check if the array is empty.
+ bool empty() const { return Length == 0; }
+
+ const T *data() const { return Data; }
+
+ /// size - Get the array size.
+ size_t size() const { return Length; }
+
+ /// front - Get the first element.
+ const T &front() const {
+ assert(!empty());
+ return Data[0];
+ }
+
+ /// back - Get the last element.
+ const T &back() const {
+ assert(!empty());
+ return Data[Length-1];
+ }
+
+ // copy - Allocate copy in Allocator and return ArrayRef<T> to it.
+ template <typename Allocator> ArrayRef<T> copy(Allocator &A) {
+ T *Buff = A.template Allocate<T>(Length);
+ std::uninitialized_copy(begin(), end(), Buff);
+ return ArrayRef<T>(Buff, Length);
+ }
+
+ /// equals - Check for element-wise equality.
+ bool equals(ArrayRef RHS) const {
+ if (Length != RHS.Length)
+ return false;
+ return std::equal(begin(), end(), RHS.begin());
+ }
+
+ /// slice(n, m) - Chop off the first N elements of the array, and keep M
+ /// elements in the array.
+ ArrayRef<T> slice(size_t N, size_t M) const {
+ assert(N+M <= size() && "Invalid specifier");
+ return ArrayRef<T>(data()+N, M);
+ }
+
+ /// slice(n) - Chop off the first N elements of the array.
+ ArrayRef<T> slice(size_t N) const { return slice(N, size() - N); }
+
+ /// Drop the first \p N elements of the array.
+ ArrayRef<T> drop_front(size_t N = 1) const {
+ assert(size() >= N && "Dropping more elements than exist");
+ return slice(N, size() - N);
+ }
+
+ /// Drop the last \p N elements of the array.
+ ArrayRef<T> drop_back(size_t N = 1) const {
+ assert(size() >= N && "Dropping more elements than exist");
+ return slice(0, size() - N);
+ }
+
+ /// Return a copy of *this with the first N elements satisfying the
+ /// given predicate removed.
+ template <class PredicateT> ArrayRef<T> drop_while(PredicateT Pred) const {
+ return ArrayRef<T>(find_if_not(*this, Pred), end());
+ }
+
+ /// Return a copy of *this with the first N elements not satisfying
+ /// the given predicate removed.
+ template <class PredicateT> ArrayRef<T> drop_until(PredicateT Pred) const {
+ return ArrayRef<T>(find_if(*this, Pred), end());
+ }
+
+ /// Return a copy of *this with only the first \p N elements.
+ ArrayRef<T> take_front(size_t N = 1) const {
+ if (N >= size())
+ return *this;
+ return drop_back(size() - N);
+ }
+
+ /// Return a copy of *this with only the last \p N elements.
+ ArrayRef<T> take_back(size_t N = 1) const {
+ if (N >= size())
+ return *this;
+ return drop_front(size() - N);
+ }
+
+ /// Return the first N elements of this Array that satisfy the given
+ /// predicate.
+ template <class PredicateT> ArrayRef<T> take_while(PredicateT Pred) const {
+ return ArrayRef<T>(begin(), find_if_not(*this, Pred));
+ }
+
+ /// Return the first N elements of this Array that don't satisfy the
+ /// given predicate.
+ template <class PredicateT> ArrayRef<T> take_until(PredicateT Pred) const {
+ return ArrayRef<T>(begin(), find_if(*this, Pred));
+ }
+
+ /// @}
+ /// @name Operator Overloads
+ /// @{
+ const T &operator[](size_t Index) const {
+ assert(Index < Length && "Invalid index!");
+ return Data[Index];
+ }
+
+ /// Disallow accidental assignment from a temporary.
+ ///
+ /// The declaration here is extra complicated so that "arrayRef = {}"
+ /// continues to select the move assignment operator.
+ template <typename U>
+ typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type &
+ operator=(U &&Temporary) = delete;
+
+ /// Disallow accidental assignment from a temporary.
+ ///
+ /// The declaration here is extra complicated so that "arrayRef = {}"
+ /// continues to select the move assignment operator.
+ template <typename U>
+ typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type &
+ operator=(std::initializer_list<U>) = delete;
+
+ /// @}
+ /// @name Expensive Operations
+ /// @{
+ std::vector<T> vec() const {
+ return std::vector<T>(Data, Data+Length);
+ }
+
+ /// @}
+ /// @name Conversion operators
+ /// @{
+ operator std::vector<T>() const {
+ return std::vector<T>(Data, Data+Length);
+ }
+
+ /// @}
+ };
+
+ /// MutableArrayRef - Represent a mutable reference to an array (0 or more
+ /// elements consecutively in memory), i.e. a start pointer and a length. It
+ /// allows various APIs to take and modify consecutive elements easily and
+ /// conveniently.
+ ///
+ /// This class does not own the underlying data, it is expected to be used in
+ /// situations where the data resides in some other buffer, whose lifetime
+ /// extends past that of the MutableArrayRef. For this reason, it is not in
+ /// general safe to store a MutableArrayRef.
+ ///
+ /// This is intended to be trivially copyable, so it should be passed by
+ /// value.
+ template<typename T>
+ class LLVM_NODISCARD MutableArrayRef : public ArrayRef<T> {
+ public:
+ using iterator = T *;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+
+ /// Construct an empty MutableArrayRef.
+ /*implicit*/ MutableArrayRef() = default;
+
+ /// Construct an empty MutableArrayRef from None.
+ /*implicit*/ MutableArrayRef(NoneType) : ArrayRef<T>() {}
+
+ /// Construct an MutableArrayRef from a single element.
+ /*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef<T>(OneElt) {}
+
+ /// Construct an MutableArrayRef from a pointer and length.
+ /*implicit*/ MutableArrayRef(T *data, size_t length)
+ : ArrayRef<T>(data, length) {}
+
+ /// Construct an MutableArrayRef from a range.
+ MutableArrayRef(T *begin, T *end) : ArrayRef<T>(begin, end) {}
+
+ /// Construct an MutableArrayRef from a SmallVector.
+ /*implicit*/ MutableArrayRef(SmallVectorImpl<T> &Vec)
+ : ArrayRef<T>(Vec) {}
+
+ /// Construct a MutableArrayRef from a std::vector.
+ /*implicit*/ MutableArrayRef(std::vector<T> &Vec)
+ : ArrayRef<T>(Vec) {}
+
+ /// Construct an ArrayRef from a std::array
+ template <size_t N>
+ /*implicit*/ constexpr MutableArrayRef(std::array<T, N> &Arr)
+ : ArrayRef<T>(Arr) {}
+
+ /// Construct an MutableArrayRef from a C array.
+ template <size_t N>
+ /*implicit*/ constexpr MutableArrayRef(T (&Arr)[N]) : ArrayRef<T>(Arr) {}
+
+ T *data() const { return const_cast<T*>(ArrayRef<T>::data()); }
+
+ iterator begin() const { return data(); }
+ iterator end() const { return data() + this->size(); }
+
+ reverse_iterator rbegin() const { return reverse_iterator(end()); }
+ reverse_iterator rend() const { return reverse_iterator(begin()); }
+
+ /// front - Get the first element.
+ T &front() const {
+ assert(!this->empty());
+ return data()[0];
+ }
+
+ /// back - Get the last element.
+ T &back() const {
+ assert(!this->empty());
+ return data()[this->size()-1];
+ }
+
+ /// slice(n, m) - Chop off the first N elements of the array, and keep M
+ /// elements in the array.
+ MutableArrayRef<T> slice(size_t N, size_t M) const {
+ assert(N + M <= this->size() && "Invalid specifier");
+ return MutableArrayRef<T>(this->data() + N, M);
+ }
+
+ /// slice(n) - Chop off the first N elements of the array.
+ MutableArrayRef<T> slice(size_t N) const {
+ return slice(N, this->size() - N);
+ }
+
+ /// Drop the first \p N elements of the array.
+ MutableArrayRef<T> drop_front(size_t N = 1) const {
+ assert(this->size() >= N && "Dropping more elements than exist");
+ return slice(N, this->size() - N);
+ }
+
+ MutableArrayRef<T> drop_back(size_t N = 1) const {
+ assert(this->size() >= N && "Dropping more elements than exist");
+ return slice(0, this->size() - N);
+ }
+
+ /// Return a copy of *this with the first N elements satisfying the
+ /// given predicate removed.
+ template <class PredicateT>
+ MutableArrayRef<T> drop_while(PredicateT Pred) const {
+ return MutableArrayRef<T>(find_if_not(*this, Pred), end());
+ }
+
+ /// Return a copy of *this with the first N elements not satisfying
+ /// the given predicate removed.
+ template <class PredicateT>
+ MutableArrayRef<T> drop_until(PredicateT Pred) const {
+ return MutableArrayRef<T>(find_if(*this, Pred), end());
+ }
+
+ /// Return a copy of *this with only the first \p N elements.
+ MutableArrayRef<T> take_front(size_t N = 1) const {
+ if (N >= this->size())
+ return *this;
+ return drop_back(this->size() - N);
+ }
+
+ /// Return a copy of *this with only the last \p N elements.
+ MutableArrayRef<T> take_back(size_t N = 1) const {
+ if (N >= this->size())
+ return *this;
+ return drop_front(this->size() - N);
+ }
+
+ /// Return the first N elements of this Array that satisfy the given
+ /// predicate.
+ template <class PredicateT>
+ MutableArrayRef<T> take_while(PredicateT Pred) const {
+ return MutableArrayRef<T>(begin(), find_if_not(*this, Pred));
+ }
+
+ /// Return the first N elements of this Array that don't satisfy the
+ /// given predicate.
+ template <class PredicateT>
+ MutableArrayRef<T> take_until(PredicateT Pred) const {
+ return MutableArrayRef<T>(begin(), find_if(*this, Pred));
+ }
+
+ /// @}
+ /// @name Operator Overloads
+ /// @{
+ T &operator[](size_t Index) const {
+ assert(Index < this->size() && "Invalid index!");
+ return data()[Index];
+ }
+ };
+
+ /// This is a MutableArrayRef that owns its array.
+ template <typename T> class OwningArrayRef : public MutableArrayRef<T> {
+ public:
+ OwningArrayRef() = default;
+ OwningArrayRef(size_t Size) : MutableArrayRef<T>(new T[Size], Size) {}
+
+ OwningArrayRef(ArrayRef<T> Data)
+ : MutableArrayRef<T>(new T[Data.size()], Data.size()) {
+ std::copy(Data.begin(), Data.end(), this->begin());
+ }
+
+ OwningArrayRef(OwningArrayRef &&Other) { *this = std::move(Other); }
+
+ OwningArrayRef &operator=(OwningArrayRef &&Other) {
+ delete[] this->data();
+ this->MutableArrayRef<T>::operator=(Other);
+ Other.MutableArrayRef<T>::operator=(MutableArrayRef<T>());
+ return *this;
+ }
+
+ ~OwningArrayRef() { delete[] this->data(); }
+ };
+
+ /// @name ArrayRef Convenience constructors
+ /// @{
+
+ /// Construct an ArrayRef from a single element.
+ template<typename T>
+ ArrayRef<T> makeArrayRef(const T &OneElt) {
+ return OneElt;
+ }
+
+ /// Construct an ArrayRef from a pointer and length.
+ template<typename T>
+ ArrayRef<T> makeArrayRef(const T *data, size_t length) {
+ return ArrayRef<T>(data, length);
+ }
+
+ /// Construct an ArrayRef from a range.
+ template<typename T>
+ ArrayRef<T> makeArrayRef(const T *begin, const T *end) {
+ return ArrayRef<T>(begin, end);
+ }
+
+ /// Construct an ArrayRef from a SmallVector.
+ template <typename T>
+ ArrayRef<T> makeArrayRef(const SmallVectorImpl<T> &Vec) {
+ return Vec;
+ }
+
+ /// Construct an ArrayRef from a SmallVector.
+ template <typename T, unsigned N>
+ ArrayRef<T> makeArrayRef(const SmallVector<T, N> &Vec) {
+ return Vec;
+ }
+
+ /// Construct an ArrayRef from a std::vector.
+ template<typename T>
+ ArrayRef<T> makeArrayRef(const std::vector<T> &Vec) {
+ return Vec;
+ }
+
+ /// Construct an ArrayRef from a std::array.
+ template <typename T, std::size_t N>
+ ArrayRef<T> makeArrayRef(const std::array<T, N> &Arr) {
+ return Arr;
+ }
+
+ /// Construct an ArrayRef from an ArrayRef (no-op) (const)
+ template <typename T> ArrayRef<T> makeArrayRef(const ArrayRef<T> &Vec) {
+ return Vec;
+ }
+
+ /// Construct an ArrayRef from an ArrayRef (no-op)
+ template <typename T> ArrayRef<T> &makeArrayRef(ArrayRef<T> &Vec) {
+ return Vec;
+ }
+
+ /// Construct an ArrayRef from a C array.
+ template<typename T, size_t N>
+ ArrayRef<T> makeArrayRef(const T (&Arr)[N]) {
+ return ArrayRef<T>(Arr);
+ }
+
+ /// Construct a MutableArrayRef from a single element.
+ template<typename T>
+ MutableArrayRef<T> makeMutableArrayRef(T &OneElt) {
+ return OneElt;
+ }
+
+ /// Construct a MutableArrayRef from a pointer and length.
+ template<typename T>
+ MutableArrayRef<T> makeMutableArrayRef(T *data, size_t length) {
+ return MutableArrayRef<T>(data, length);
+ }
+
+ /// @}
+ /// @name ArrayRef Comparison Operators
+ /// @{
+
+ template<typename T>
+ inline bool operator==(ArrayRef<T> LHS, ArrayRef<T> RHS) {
+ return LHS.equals(RHS);
+ }
+
+ template<typename T>
+ inline bool operator!=(ArrayRef<T> LHS, ArrayRef<T> RHS) {
+ return !(LHS == RHS);
+ }
+
+ /// @}
+
+ template <typename T> hash_code hash_value(ArrayRef<T> S) {
+ return hash_combine_range(S.begin(), S.end());
+ }
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_ARRAYREF_H
diff --git a/third_party/llvm-project/include/llvm/ADT/BitmaskEnum.h b/third_party/llvm-project/include/llvm/ADT/BitmaskEnum.h
new file mode 100644
index 000000000..1a18bc721
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/BitmaskEnum.h
@@ -0,0 +1,152 @@
+//===-- llvm/ADT/BitmaskEnum.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_BITMASKENUM_H
+#define LLVM_ADT_BITMASKENUM_H
+
+#include <cassert>
+#include <type_traits>
+#include <utility>
+
+#include "llvm/Support/MathExtras.h"
+
+/// LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can
+/// perform bitwise operations on it without putting static_cast everywhere.
+///
+/// \code
+/// enum MyEnum {
+/// E1 = 1, E2 = 2, E3 = 4, E4 = 8,
+/// LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ E4)
+/// };
+///
+/// void Foo() {
+/// MyEnum A = (E1 | E2) & E3 ^ ~E4; // Look, ma: No static_cast!
+/// }
+/// \endcode
+///
+/// Normally when you do a bitwise operation on an enum value, you get back an
+/// instance of the underlying type (e.g. int). But using this macro, bitwise
+/// ops on your enum will return you back instances of the enum. This is
+/// particularly useful for enums which represent a combination of flags.
+///
+/// The parameter to LLVM_MARK_AS_BITMASK_ENUM should be the largest individual
+/// value in your enum.
+///
+/// All of the enum's values must be non-negative.
+#define LLVM_MARK_AS_BITMASK_ENUM(LargestValue) \
+ LLVM_BITMASK_LARGEST_ENUMERATOR = LargestValue
+
+/// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() pulls the operator overloads used
+/// by LLVM_MARK_AS_BITMASK_ENUM into the current namespace.
+///
+/// Suppose you have an enum foo::bar::MyEnum. Before using
+/// LLVM_MARK_AS_BITMASK_ENUM on MyEnum, you must put
+/// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() somewhere inside namespace foo or
+/// namespace foo::bar. This allows the relevant operator overloads to be found
+/// by ADL.
+///
+/// You don't need to use this macro in namespace llvm; it's done at the bottom
+/// of this file.
+#define LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() \
+ using ::llvm::BitmaskEnumDetail::operator~; \
+ using ::llvm::BitmaskEnumDetail::operator|; \
+ using ::llvm::BitmaskEnumDetail::operator&; \
+ using ::llvm::BitmaskEnumDetail::operator^; \
+ using ::llvm::BitmaskEnumDetail::operator|=; \
+ using ::llvm::BitmaskEnumDetail::operator&=; \
+ /* Force a semicolon at the end of this macro. */ \
+ using ::llvm::BitmaskEnumDetail::operator^=
+
+namespace llvm {
+
+/// Traits class to determine whether an enum has a
+/// LLVM_BITMASK_LARGEST_ENUMERATOR enumerator.
+template <typename E, typename Enable = void>
+struct is_bitmask_enum : std::false_type {};
+
+template <typename E>
+struct is_bitmask_enum<
+ E, typename std::enable_if<sizeof(E::LLVM_BITMASK_LARGEST_ENUMERATOR) >=
+ 0>::type> : std::true_type {};
+namespace BitmaskEnumDetail {
+
+/// Get a bitmask with 1s in all places up to the high-order bit of E's largest
+/// value.
+template <typename E> typename std::underlying_type<E>::type Mask() {
+ // On overflow, NextPowerOf2 returns zero with the type uint64_t, so
+ // subtracting 1 gives us the mask with all bits set, like we want.
+ return NextPowerOf2(static_cast<typename std::underlying_type<E>::type>(
+ E::LLVM_BITMASK_LARGEST_ENUMERATOR)) -
+ 1;
+}
+
+/// Check that Val is in range for E, and return Val cast to E's underlying
+/// type.
+template <typename E> typename std::underlying_type<E>::type Underlying(E Val) {
+ auto U = static_cast<typename std::underlying_type<E>::type>(Val);
+ assert(U >= 0 && "Negative enum values are not allowed.");
+ assert(U <= Mask<E>() && "Enum value too large (or largest val too small?)");
+ return U;
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E operator~(E Val) {
+ return static_cast<E>(~Underlying(Val) & Mask<E>());
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E operator|(E LHS, E RHS) {
+ return static_cast<E>(Underlying(LHS) | Underlying(RHS));
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E operator&(E LHS, E RHS) {
+ return static_cast<E>(Underlying(LHS) & Underlying(RHS));
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E operator^(E LHS, E RHS) {
+ return static_cast<E>(Underlying(LHS) ^ Underlying(RHS));
+}
+
+// |=, &=, and ^= return a reference to LHS, to match the behavior of the
+// operators on builtin types.
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E &operator|=(E &LHS, E RHS) {
+ LHS = LHS | RHS;
+ return LHS;
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E &operator&=(E &LHS, E RHS) {
+ LHS = LHS & RHS;
+ return LHS;
+}
+
+template <typename E,
+ typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
+E &operator^=(E &LHS, E RHS) {
+ LHS = LHS ^ RHS;
+ return LHS;
+}
+
+} // namespace BitmaskEnumDetail
+
+// Enable bitmask enums in namespace ::llvm and all nested namespaces.
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/ADT/DenseMap.h b/third_party/llvm-project/include/llvm/ADT/DenseMap.h
new file mode 100644
index 000000000..948a6e6bf
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/DenseMap.h
@@ -0,0 +1,1275 @@
+//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DenseMap class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_DENSEMAP_H
+#define LLVM_ADT_DENSEMAP_H
+
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/EpochTracker.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/ReverseIteration.h"
+#include "llvm/Support/type_traits.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <initializer_list>
+#include <iterator>
+#include <new>
+#include <type_traits>
+#include <utility>
+
+namespace llvm {
+
+namespace detail {
+
+// We extend a pair to allow users to override the bucket type with their own
+// implementation without requiring two members.
+template <typename KeyT, typename ValueT>
+struct DenseMapPair : public std::pair<KeyT, ValueT> {
+ using std::pair<KeyT, ValueT>::pair;
+
+ KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; }
+ const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; }
+ ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; }
+ const ValueT &getSecond() const { return std::pair<KeyT, ValueT>::second; }
+};
+
+} // end namespace detail
+
+template <typename KeyT, typename ValueT,
+ typename KeyInfoT = DenseMapInfo<KeyT>,
+ typename Bucket = llvm::detail::DenseMapPair<KeyT, ValueT>,
+ bool IsConst = false>
+class DenseMapIterator;
+
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
+ typename BucketT>
+class DenseMapBase : public DebugEpochBase {
+ template <typename T>
+ using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
+
+public:
+ using size_type = unsigned;
+ using key_type = KeyT;
+ using mapped_type = ValueT;
+ using value_type = BucketT;
+
+ using iterator = DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT>;
+ using const_iterator =
+ DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true>;
+
+ inline iterator begin() {
+ // When the map is empty, avoid the overhead of advancing/retreating past
+ // empty buckets.
+ if (empty())
+ return end();
+ if (shouldReverseIterate<KeyT>())
+ return makeIterator(getBucketsEnd() - 1, getBuckets(), *this);
+ return makeIterator(getBuckets(), getBucketsEnd(), *this);
+ }
+ inline iterator end() {
+ return makeIterator(getBucketsEnd(), getBucketsEnd(), *this, true);
+ }
+ inline const_iterator begin() const {
+ if (empty())
+ return end();
+ if (shouldReverseIterate<KeyT>())
+ return makeConstIterator(getBucketsEnd() - 1, getBuckets(), *this);
+ return makeConstIterator(getBuckets(), getBucketsEnd(), *this);
+ }
+ inline const_iterator end() const {
+ return makeConstIterator(getBucketsEnd(), getBucketsEnd(), *this, true);
+ }
+
+ LLVM_NODISCARD bool empty() const {
+ return getNumEntries() == 0;
+ }
+ unsigned size() const { return getNumEntries(); }
+
+ /// Grow the densemap so that it can contain at least \p NumEntries items
+ /// before resizing again.
+ void reserve(size_type NumEntries) {
+ auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
+ incrementEpoch();
+ if (NumBuckets > getNumBuckets())
+ grow(NumBuckets);
+ }
+
+ void clear() {
+ incrementEpoch();
+ if (getNumEntries() == 0 && getNumTombstones() == 0) return;
+
+ // If the capacity of the array is huge, and the # elements used is small,
+ // shrink the array.
+ if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) {
+ shrink_and_clear();
+ return;
+ }
+
+ const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
+ if (is_trivially_copyable<KeyT>::value &&
+ is_trivially_copyable<ValueT>::value) {
+ // Use a simpler loop when these are trivial types.
+ for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P)
+ P->getFirst() = EmptyKey;
+ } else {
+ unsigned NumEntries = getNumEntries();
+ for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
+ if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
+ if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
+ P->getSecond().~ValueT();
+ --NumEntries;
+ }
+ P->getFirst() = EmptyKey;
+ }
+ }
+ assert(NumEntries == 0 && "Node count imbalance!");
+ }
+ setNumEntries(0);
+ setNumTombstones(0);
+ }
+
+ /// Return 1 if the specified key is in the map, 0 otherwise.
+ size_type count(const_arg_type_t<KeyT> Val) const {
+ const BucketT *TheBucket;
+ return LookupBucketFor(Val, TheBucket) ? 1 : 0;
+ }
+
+ iterator find(const_arg_type_t<KeyT> Val) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Val, TheBucket))
+ return makeIterator(TheBucket, getBucketsEnd(), *this, true);
+ return end();
+ }
+ const_iterator find(const_arg_type_t<KeyT> Val) const {
+ const BucketT *TheBucket;
+ if (LookupBucketFor(Val, TheBucket))
+ return makeConstIterator(TheBucket, getBucketsEnd(), *this, true);
+ return end();
+ }
+
+ /// Alternate version of find() which allows a different, and possibly
+ /// less expensive, key type.
+ /// The DenseMapInfo is responsible for supplying methods
+ /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
+ /// type used.
+ template<class LookupKeyT>
+ iterator find_as(const LookupKeyT &Val) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Val, TheBucket))
+ return makeIterator(TheBucket, getBucketsEnd(), *this, true);
+ return end();
+ }
+ template<class LookupKeyT>
+ const_iterator find_as(const LookupKeyT &Val) const {
+ const BucketT *TheBucket;
+ if (LookupBucketFor(Val, TheBucket))
+ return makeConstIterator(TheBucket, getBucketsEnd(), *this, true);
+ return end();
+ }
+
+ /// lookup - Return the entry for the specified key, or a default
+ /// constructed value if no such entry exists.
+ ValueT lookup(const_arg_type_t<KeyT> Val) const {
+ const BucketT *TheBucket;
+ if (LookupBucketFor(Val, TheBucket))
+ return TheBucket->getSecond();
+ return ValueT();
+ }
+
+ // Inserts key,value pair into the map if the key isn't already in the map.
+ // If the key is already in the map, it returns false and doesn't update the
+ // value.
+ std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
+ return try_emplace(KV.first, KV.second);
+ }
+
+ // Inserts key,value pair into the map if the key isn't already in the map.
+ // If the key is already in the map, it returns false and doesn't update the
+ // value.
+ std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
+ return try_emplace(std::move(KV.first), std::move(KV.second));
+ }
+
+ // Inserts key,value pair into the map if the key isn't already in the map.
+ // The value is constructed in-place if the key is not in the map, otherwise
+ // it is not moved.
+ template <typename... Ts>
+ std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&... Args) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return std::make_pair(
+ makeIterator(TheBucket, getBucketsEnd(), *this, true),
+ false); // Already in map.
+
+ // Otherwise, insert the new element.
+ TheBucket =
+ InsertIntoBucket(TheBucket, std::move(Key), std::forward<Ts>(Args)...);
+ return std::make_pair(
+ makeIterator(TheBucket, getBucketsEnd(), *this, true),
+ true);
+ }
+
+ // Inserts key,value pair into the map if the key isn't already in the map.
+ // The value is constructed in-place if the key is not in the map, otherwise
+ // it is not moved.
+ template <typename... Ts>
+ std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&... Args) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return std::make_pair(
+ makeIterator(TheBucket, getBucketsEnd(), *this, true),
+ false); // Already in map.
+
+ // Otherwise, insert the new element.
+ TheBucket = InsertIntoBucket(TheBucket, Key, std::forward<Ts>(Args)...);
+ return std::make_pair(
+ makeIterator(TheBucket, getBucketsEnd(), *this, true),
+ true);
+ }
+
+ /// Alternate version of insert() which allows a different, and possibly
+ /// less expensive, key type.
+ /// The DenseMapInfo is responsible for supplying methods
+ /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
+ /// type used.
+ template <typename LookupKeyT>
+ std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV,
+ const LookupKeyT &Val) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Val, TheBucket))
+ return std::make_pair(
+ makeIterator(TheBucket, getBucketsEnd(), *this, true),
+ false); // Already in map.
+
+ // Otherwise, insert the new element.
+ TheBucket = InsertIntoBucketWithLookup(TheBucket, std::move(KV.first),
+ std::move(KV.second), Val);
+ return std::make_pair(
+ makeIterator(TheBucket, getBucketsEnd(), *this, true),
+ true);
+ }
+
+ /// insert - Range insertion of pairs.
+ template<typename InputIt>
+ void insert(InputIt I, InputIt E) {
+ for (; I != E; ++I)
+ insert(*I);
+ }
+
+ bool erase(const KeyT &Val) {
+ BucketT *TheBucket;
+ if (!LookupBucketFor(Val, TheBucket))
+ return false; // not in map.
+
+ TheBucket->getSecond().~ValueT();
+ TheBucket->getFirst() = getTombstoneKey();
+ decrementNumEntries();
+ incrementNumTombstones();
+ return true;
+ }
+ void erase(iterator I) {
+ BucketT *TheBucket = &*I;
+ TheBucket->getSecond().~ValueT();
+ TheBucket->getFirst() = getTombstoneKey();
+ decrementNumEntries();
+ incrementNumTombstones();
+ }
+
+ value_type& FindAndConstruct(const KeyT &Key) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return *TheBucket;
+
+ return *InsertIntoBucket(TheBucket, Key);
+ }
+
+ ValueT &operator[](const KeyT &Key) {
+ return FindAndConstruct(Key).second;
+ }
+
+ value_type& FindAndConstruct(KeyT &&Key) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return *TheBucket;
+
+ return *InsertIntoBucket(TheBucket, std::move(Key));
+ }
+
+ ValueT &operator[](KeyT &&Key) {
+ return FindAndConstruct(std::move(Key)).second;
+ }
+
+ /// isPointerIntoBucketsArray - Return true if the specified pointer points
+ /// somewhere into the DenseMap's array of buckets (i.e. either to a key or
+ /// value in the DenseMap).
+ bool isPointerIntoBucketsArray(const void *Ptr) const {
+ return Ptr >= getBuckets() && Ptr < getBucketsEnd();
+ }
+
+ /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets
+ /// array. In conjunction with the previous method, this can be used to
+ /// determine whether an insertion caused the DenseMap to reallocate.
+ const void *getPointerIntoBucketsArray() const { return getBuckets(); }
+
+protected:
+ DenseMapBase() = default;
+
+ void destroyAll() {
+ if (getNumBuckets() == 0) // Nothing to do.
+ return;
+
+ const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
+ for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
+ if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(P->getFirst(), TombstoneKey))
+ P->getSecond().~ValueT();
+ P->getFirst().~KeyT();
+ }
+ }
+
+ void initEmpty() {
+ setNumEntries(0);
+ setNumTombstones(0);
+
+ assert((getNumBuckets() & (getNumBuckets()-1)) == 0 &&
+ "# initial buckets must be a power of two!");
+ const KeyT EmptyKey = getEmptyKey();
+ for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B)
+ ::new (&B->getFirst()) KeyT(EmptyKey);
+ }
+
+ /// Returns the number of buckets to allocate to ensure that the DenseMap can
+ /// accommodate \p NumEntries without need to grow().
+ 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);
+ }
+
+ void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {
+ initEmpty();
+
+ // Insert all the old elements.
+ const KeyT EmptyKey = getEmptyKey();
+ const KeyT TombstoneKey = getTombstoneKey();
+ for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) {
+ if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) {
+ // Insert the key/value into the new table.
+ BucketT *DestBucket;
+ bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket);
+ (void)FoundVal; // silence warning.
+ assert(!FoundVal && "Key already in new map?");
+ DestBucket->getFirst() = std::move(B->getFirst());
+ ::new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond()));
+ incrementNumEntries();
+
+ // Free the value.
+ B->getSecond().~ValueT();
+ }
+ B->getFirst().~KeyT();
+ }
+ }
+
+ template <typename OtherBaseT>
+ void copyFrom(
+ const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) {
+ assert(&other != this);
+ assert(getNumBuckets() == other.getNumBuckets());
+
+ setNumEntries(other.getNumEntries());
+ setNumTombstones(other.getNumTombstones());
+
+ if (is_trivially_copyable<KeyT>::value &&
+ is_trivially_copyable<ValueT>::value)
+ memcpy(reinterpret_cast<void *>(getBuckets()), other.getBuckets(),
+ getNumBuckets() * sizeof(BucketT));
+ else
+ for (size_t i = 0; i < getNumBuckets(); ++i) {
+ ::new (&getBuckets()[i].getFirst())
+ KeyT(other.getBuckets()[i].getFirst());
+ if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) &&
+ !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey()))
+ ::new (&getBuckets()[i].getSecond())
+ ValueT(other.getBuckets()[i].getSecond());
+ }
+ }
+
+ static unsigned getHashValue(const KeyT &Val) {
+ return KeyInfoT::getHashValue(Val);
+ }
+
+ template<typename LookupKeyT>
+ static unsigned getHashValue(const LookupKeyT &Val) {
+ return KeyInfoT::getHashValue(Val);
+ }
+
+ static const KeyT getEmptyKey() {
+ static_assert(std::is_base_of<DenseMapBase, DerivedT>::value,
+ "Must pass the derived type to this template!");
+ return KeyInfoT::getEmptyKey();
+ }
+
+ static const KeyT getTombstoneKey() {
+ return KeyInfoT::getTombstoneKey();
+ }
+
+private:
+ iterator makeIterator(BucketT *P, BucketT *E,
+ DebugEpochBase &Epoch,
+ bool NoAdvance=false) {
+ if (shouldReverseIterate<KeyT>()) {
+ BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1;
+ return iterator(B, E, Epoch, NoAdvance);
+ }
+ return iterator(P, E, Epoch, NoAdvance);
+ }
+
+ const_iterator makeConstIterator(const BucketT *P, const BucketT *E,
+ const DebugEpochBase &Epoch,
+ const bool NoAdvance=false) const {
+ if (shouldReverseIterate<KeyT>()) {
+ const BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1;
+ return const_iterator(B, E, Epoch, NoAdvance);
+ }
+ return const_iterator(P, E, Epoch, NoAdvance);
+ }
+
+ unsigned getNumEntries() const {
+ return static_cast<const DerivedT *>(this)->getNumEntries();
+ }
+
+ void setNumEntries(unsigned Num) {
+ static_cast<DerivedT *>(this)->setNumEntries(Num);
+ }
+
+ void incrementNumEntries() {
+ setNumEntries(getNumEntries() + 1);
+ }
+
+ void decrementNumEntries() {
+ setNumEntries(getNumEntries() - 1);
+ }
+
+ unsigned getNumTombstones() const {
+ return static_cast<const DerivedT *>(this)->getNumTombstones();
+ }
+
+ void setNumTombstones(unsigned Num) {
+ static_cast<DerivedT *>(this)->setNumTombstones(Num);
+ }
+
+ void incrementNumTombstones() {
+ setNumTombstones(getNumTombstones() + 1);
+ }
+
+ void decrementNumTombstones() {
+ setNumTombstones(getNumTombstones() - 1);
+ }
+
+ const BucketT *getBuckets() const {
+ return static_cast<const DerivedT *>(this)->getBuckets();
+ }
+
+ BucketT *getBuckets() {
+ return static_cast<DerivedT *>(this)->getBuckets();
+ }
+
+ unsigned getNumBuckets() const {
+ return static_cast<const DerivedT *>(this)->getNumBuckets();
+ }
+
+ BucketT *getBucketsEnd() {
+ return getBuckets() + getNumBuckets();
+ }
+
+ const BucketT *getBucketsEnd() const {
+ return getBuckets() + getNumBuckets();
+ }
+
+ void grow(unsigned AtLeast) {
+ static_cast<DerivedT *>(this)->grow(AtLeast);
+ }
+
+ void shrink_and_clear() {
+ static_cast<DerivedT *>(this)->shrink_and_clear();
+ }
+
+ template <typename KeyArg, typename... ValueArgs>
+ BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key,
+ ValueArgs &&... Values) {
+ TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
+
+ TheBucket->getFirst() = std::forward<KeyArg>(Key);
+ ::new (&TheBucket->getSecond()) ValueT(std::forward<ValueArgs>(Values)...);
+ return TheBucket;
+ }
+
+ template <typename LookupKeyT>
+ BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket, KeyT &&Key,
+ ValueT &&Value, LookupKeyT &Lookup) {
+ TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket);
+
+ TheBucket->getFirst() = std::move(Key);
+ ::new (&TheBucket->getSecond()) ValueT(std::move(Value));
+ return TheBucket;
+ }
+
+ template <typename LookupKeyT>
+ BucketT *InsertIntoBucketImpl(const KeyT &Key, const LookupKeyT &Lookup,
+ BucketT *TheBucket) {
+ incrementEpoch();
+
+ // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
+ // the buckets are empty (meaning that many are filled with tombstones),
+ // grow the table.
+ //
+ // The later case is tricky. For example, if we had one empty bucket with
+ // tons of tombstones, failing lookups (e.g. for insertion) would have to
+ // probe almost the entire table until it found the empty bucket. If the
+ // table completely filled with tombstones, no lookup would ever succeed,
+ // causing infinite loops in lookup.
+ unsigned NewNumEntries = getNumEntries() + 1;
+ unsigned NumBuckets = getNumBuckets();
+ if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
+ this->grow(NumBuckets * 2);
+ LookupBucketFor(Lookup, TheBucket);
+ NumBuckets = getNumBuckets();
+ } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <=
+ NumBuckets/8)) {
+ this->grow(NumBuckets);
+ LookupBucketFor(Lookup, TheBucket);
+ }
+ assert(TheBucket);
+
+ // Only update the state after we've grown our bucket space appropriately
+ // so that when growing buckets we have self-consistent entry count.
+ incrementNumEntries();
+
+ // If we are writing over a tombstone, remember this.
+ const KeyT EmptyKey = getEmptyKey();
+ if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey))
+ decrementNumTombstones();
+
+ return TheBucket;
+ }
+
+ /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
+ /// FoundBucket. If the bucket contains the key and a value, this returns
+ /// true, otherwise it returns a bucket with an empty marker or tombstone and
+ /// returns false.
+ template<typename LookupKeyT>
+ bool LookupBucketFor(const LookupKeyT &Val,
+ const BucketT *&FoundBucket) const {
+ const BucketT *BucketsPtr = getBuckets();
+ const unsigned NumBuckets = getNumBuckets();
+
+ if (NumBuckets == 0) {
+ FoundBucket = nullptr;
+ return false;
+ }
+
+ // FoundTombstone - Keep track of whether we find a tombstone while probing.
+ const BucketT *FoundTombstone = nullptr;
+ const KeyT EmptyKey = getEmptyKey();
+ const KeyT TombstoneKey = getTombstoneKey();
+ assert(!KeyInfoT::isEqual(Val, EmptyKey) &&
+ !KeyInfoT::isEqual(Val, TombstoneKey) &&
+ "Empty/Tombstone value shouldn't be inserted into map!");
+
+ unsigned BucketNo = getHashValue(Val) & (NumBuckets-1);
+ unsigned ProbeAmt = 1;
+ while (true) {
+ const BucketT *ThisBucket = BucketsPtr + BucketNo;
+ // Found Val's bucket? If so, return it.
+ if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
+ FoundBucket = ThisBucket;
+ return true;
+ }
+
+ // If we found an empty bucket, the key doesn't exist in the set.
+ // Insert it and return the default value.
+ if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
+ // If we've already seen a tombstone while probing, fill it in instead
+ // of the empty bucket we eventually probed to.
+ FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
+ return false;
+ }
+
+ // If this is a tombstone, remember it. If Val ends up not in the map, we
+ // prefer to return it than something that would require more probing.
+ if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) &&
+ !FoundTombstone)
+ FoundTombstone = ThisBucket; // Remember the first tombstone found.
+
+ // Otherwise, it's a hash collision or a tombstone, continue quadratic
+ // probing.
+ BucketNo += ProbeAmt++;
+ BucketNo &= (NumBuckets-1);
+ }
+ }
+
+ template <typename LookupKeyT>
+ bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) {
+ const BucketT *ConstFoundBucket;
+ bool Result = const_cast<const DenseMapBase *>(this)
+ ->LookupBucketFor(Val, ConstFoundBucket);
+ FoundBucket = const_cast<BucketT *>(ConstFoundBucket);
+ return Result;
+ }
+
+public:
+ /// Return the approximate size (in bytes) of the actual map.
+ /// This is just the raw memory used by DenseMap.
+ /// If entries are pointers to objects, the size of the referenced objects
+ /// are not included.
+ size_t getMemorySize() const {
+ return getNumBuckets() * sizeof(BucketT);
+ }
+};
+
+/// Equality comparison for DenseMap.
+///
+/// Iterates over elements of LHS confirming that each (key, value) pair in LHS
+/// is also in RHS, and that no additional pairs are in RHS.
+/// Equivalent to N calls to RHS.find and N value comparisons. Amortized
+/// complexity is linear, worst case is O(N^2) (if every hash collides).
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
+ typename BucketT>
+bool operator==(
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
+ if (LHS.size() != RHS.size())
+ return false;
+
+ for (auto &KV : LHS) {
+ auto I = RHS.find(KV.first);
+ if (I == RHS.end() || I->second != KV.second)
+ return false;
+ }
+
+ return true;
+}
+
+/// Inequality comparison for DenseMap.
+///
+/// Equivalent to !(LHS == RHS). See operator== for performance notes.
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
+ typename BucketT>
+bool operator!=(
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
+ return !(LHS == RHS);
+}
+
+template <typename KeyT, typename ValueT,
+ typename KeyInfoT = DenseMapInfo<KeyT>,
+ typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>>
+class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
+ KeyT, ValueT, KeyInfoT, BucketT> {
+ friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+
+ // Lift some types from the dependent base class into this class for
+ // simplicity of referring to them.
+ using BaseT = DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+
+ BucketT *Buckets;
+ unsigned NumEntries;
+ unsigned NumTombstones;
+ unsigned NumBuckets;
+
+public:
+ /// Create a DenseMap wth an optional \p InitialReserve that guarantee that
+ /// this number of elements can be inserted in the map without grow()
+ explicit DenseMap(unsigned InitialReserve = 0) { init(InitialReserve); }
+
+ DenseMap(const DenseMap &other) : BaseT() {
+ init(0);
+ copyFrom(other);
+ }
+
+ DenseMap(DenseMap &&other) : BaseT() {
+ init(0);
+ swap(other);
+ }
+
+ template<typename InputIt>
+ DenseMap(const InputIt &I, const InputIt &E) {
+ init(std::distance(I, E));
+ this->insert(I, E);
+ }
+
+ DenseMap(std::initializer_list<typename BaseT::value_type> Vals) {
+ init(Vals.size());
+ this->insert(Vals.begin(), Vals.end());
+ }
+
+ ~DenseMap() {
+ this->destroyAll();
+ deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
+ }
+
+ void swap(DenseMap& RHS) {
+ this->incrementEpoch();
+ RHS.incrementEpoch();
+ std::swap(Buckets, RHS.Buckets);
+ std::swap(NumEntries, RHS.NumEntries);
+ std::swap(NumTombstones, RHS.NumTombstones);
+ std::swap(NumBuckets, RHS.NumBuckets);
+ }
+
+ DenseMap& operator=(const DenseMap& other) {
+ if (&other != this)
+ copyFrom(other);
+ return *this;
+ }
+
+ DenseMap& operator=(DenseMap &&other) {
+ this->destroyAll();
+ deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
+ init(0);
+ swap(other);
+ return *this;
+ }
+
+ void copyFrom(const DenseMap& other) {
+ this->destroyAll();
+ deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
+ if (allocateBuckets(other.NumBuckets)) {
+ this->BaseT::copyFrom(other);
+ } else {
+ NumEntries = 0;
+ NumTombstones = 0;
+ }
+ }
+
+ void init(unsigned InitNumEntries) {
+ auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
+ if (allocateBuckets(InitBuckets)) {
+ this->BaseT::initEmpty();
+ } else {
+ NumEntries = 0;
+ NumTombstones = 0;
+ }
+ }
+
+ void grow(unsigned AtLeast) {
+ unsigned OldNumBuckets = NumBuckets;
+ BucketT *OldBuckets = Buckets;
+
+ allocateBuckets(std::max<unsigned>(64, static_cast<unsigned>(NextPowerOf2(AtLeast-1))));
+ assert(Buckets);
+ if (!OldBuckets) {
+ this->BaseT::initEmpty();
+ return;
+ }
+
+ this->moveFromOldBuckets(OldBuckets, OldBuckets+OldNumBuckets);
+
+ // Free the old table.
+ deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets,
+ alignof(BucketT));
+ }
+
+ void shrink_and_clear() {
+ unsigned OldNumBuckets = NumBuckets;
+ unsigned OldNumEntries = NumEntries;
+ this->destroyAll();
+
+ // Reduce the number of buckets.
+ unsigned NewNumBuckets = 0;
+ if (OldNumEntries)
+ NewNumBuckets = std::max(64, 1 << (Log2_32_Ceil(OldNumEntries) + 1));
+ if (NewNumBuckets == NumBuckets) {
+ this->BaseT::initEmpty();
+ return;
+ }
+
+ deallocate_buffer(Buckets, sizeof(BucketT) * OldNumBuckets,
+ alignof(BucketT));
+ init(NewNumBuckets);
+ }
+
+private:
+ unsigned getNumEntries() const {
+ return NumEntries;
+ }
+
+ void setNumEntries(unsigned Num) {
+ NumEntries = Num;
+ }
+
+ unsigned getNumTombstones() const {
+ return NumTombstones;
+ }
+
+ void setNumTombstones(unsigned Num) {
+ NumTombstones = Num;
+ }
+
+ BucketT *getBuckets() const {
+ return Buckets;
+ }
+
+ unsigned getNumBuckets() const {
+ return NumBuckets;
+ }
+
+ bool allocateBuckets(unsigned Num) {
+ NumBuckets = Num;
+ if (NumBuckets == 0) {
+ Buckets = nullptr;
+ return false;
+ }
+
+ Buckets = static_cast<BucketT *>(
+ allocate_buffer(sizeof(BucketT) * NumBuckets, alignof(BucketT)));
+ return true;
+ }
+};
+
+template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4,
+ typename KeyInfoT = DenseMapInfo<KeyT>,
+ typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>>
+class SmallDenseMap
+ : public DenseMapBase<
+ SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
+ ValueT, KeyInfoT, BucketT> {
+ friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+
+ // Lift some types from the dependent base class into this class for
+ // simplicity of referring to them.
+ using BaseT = DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+
+ static_assert(isPowerOf2_64(InlineBuckets),
+ "InlineBuckets must be a power of 2.");
+
+ unsigned Small : 1;
+ unsigned NumEntries : 31;
+ unsigned NumTombstones;
+
+ struct LargeRep {
+ BucketT *Buckets;
+ unsigned NumBuckets;
+ };
+
+ /// A "union" of an inline bucket array and the struct representing
+ /// a large bucket. This union will be discriminated by the 'Small' bit.
+ AlignedCharArrayUnion<BucketT[InlineBuckets], LargeRep> storage;
+
+public:
+ explicit SmallDenseMap(unsigned NumInitBuckets = 0) {
+ init(NumInitBuckets);
+ }
+
+ SmallDenseMap(const SmallDenseMap &other) : BaseT() {
+ init(0);
+ copyFrom(other);
+ }
+
+ SmallDenseMap(SmallDenseMap &&other) : BaseT() {
+ init(0);
+ swap(other);
+ }
+
+ template<typename InputIt>
+ SmallDenseMap(const InputIt &I, const InputIt &E) {
+ init(NextPowerOf2(std::distance(I, E)));
+ this->insert(I, E);
+ }
+
+ ~SmallDenseMap() {
+ this->destroyAll();
+ deallocateBuckets();
+ }
+
+ void swap(SmallDenseMap& RHS) {
+ unsigned TmpNumEntries = RHS.NumEntries;
+ RHS.NumEntries = NumEntries;
+ NumEntries = TmpNumEntries;
+ std::swap(NumTombstones, RHS.NumTombstones);
+
+ const KeyT EmptyKey = this->getEmptyKey();
+ const KeyT TombstoneKey = this->getTombstoneKey();
+ if (Small && RHS.Small) {
+ // If we're swapping inline bucket arrays, we have to cope with some of
+ // the tricky bits of DenseMap's storage system: the buckets are not
+ // fully initialized. Thus we swap every key, but we may have
+ // a one-directional move of the value.
+ for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
+ BucketT *LHSB = &getInlineBuckets()[i],
+ *RHSB = &RHS.getInlineBuckets()[i];
+ bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey));
+ bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey));
+ if (hasLHSValue && hasRHSValue) {
+ // Swap together if we can...
+ std::swap(*LHSB, *RHSB);
+ continue;
+ }
+ // Swap separately and handle any assymetry.
+ std::swap(LHSB->getFirst(), RHSB->getFirst());
+ if (hasLHSValue) {
+ ::new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond()));
+ LHSB->getSecond().~ValueT();
+ } else if (hasRHSValue) {
+ ::new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond()));
+ RHSB->getSecond().~ValueT();
+ }
+ }
+ return;
+ }
+ if (!Small && !RHS.Small) {
+ std::swap(getLargeRep()->Buckets, RHS.getLargeRep()->Buckets);
+ std::swap(getLargeRep()->NumBuckets, RHS.getLargeRep()->NumBuckets);
+ return;
+ }
+
+ SmallDenseMap &SmallSide = Small ? *this : RHS;
+ SmallDenseMap &LargeSide = Small ? RHS : *this;
+
+ // First stash the large side's rep and move the small side across.
+ LargeRep TmpRep = std::move(*LargeSide.getLargeRep());
+ LargeSide.getLargeRep()->~LargeRep();
+ LargeSide.Small = true;
+ // This is similar to the standard move-from-old-buckets, but the bucket
+ // count hasn't actually rotated in this case. So we have to carefully
+ // move construct the keys and values into their new locations, but there
+ // is no need to re-hash things.
+ for (unsigned i = 0, e = InlineBuckets; i != e; ++i) {
+ BucketT *NewB = &LargeSide.getInlineBuckets()[i],
+ *OldB = &SmallSide.getInlineBuckets()[i];
+ ::new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst()));
+ OldB->getFirst().~KeyT();
+ if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) {
+ ::new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond()));
+ OldB->getSecond().~ValueT();
+ }
+ }
+
+ // The hard part of moving the small buckets across is done, just move
+ // the TmpRep into its new home.
+ SmallSide.Small = false;
+ new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep));
+ }
+
+ SmallDenseMap& operator=(const SmallDenseMap& other) {
+ if (&other != this)
+ copyFrom(other);
+ return *this;
+ }
+
+ SmallDenseMap& operator=(SmallDenseMap &&other) {
+ this->destroyAll();
+ deallocateBuckets();
+ init(0);
+ swap(other);
+ return *this;
+ }
+
+ void copyFrom(const SmallDenseMap& other) {
+ this->destroyAll();
+ deallocateBuckets();
+ Small = true;
+ if (other.getNumBuckets() > InlineBuckets) {
+ Small = false;
+ new (getLargeRep()) LargeRep(allocateBuckets(other.getNumBuckets()));
+ }
+ this->BaseT::copyFrom(other);
+ }
+
+ void init(unsigned InitBuckets) {
+ Small = true;
+ if (InitBuckets > InlineBuckets) {
+ Small = false;
+ new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets));
+ }
+ this->BaseT::initEmpty();
+ }
+
+ void grow(unsigned AtLeast) {
+ if (AtLeast >= InlineBuckets)
+ AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast-1));
+
+ if (Small) {
+ if (AtLeast < InlineBuckets)
+ return; // Nothing to do.
+
+ // First move the inline buckets into a temporary storage.
+ AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage;
+ BucketT *TmpBegin = reinterpret_cast<BucketT *>(TmpStorage.buffer);
+ BucketT *TmpEnd = TmpBegin;
+
+ // Loop over the buckets, moving non-empty, non-tombstones into the
+ // temporary storage. Have the loop move the TmpEnd forward as it goes.
+ const KeyT EmptyKey = this->getEmptyKey();
+ const KeyT TombstoneKey = this->getTombstoneKey();
+ for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) {
+ if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
+ assert(size_t(TmpEnd - TmpBegin) < InlineBuckets &&
+ "Too many inline buckets!");
+ ::new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst()));
+ ::new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond()));
+ ++TmpEnd;
+ P->getSecond().~ValueT();
+ }
+ P->getFirst().~KeyT();
+ }
+
+ // Now make this map use the large rep, and move all the entries back
+ // into it.
+ Small = false;
+ new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
+ this->moveFromOldBuckets(TmpBegin, TmpEnd);
+ return;
+ }
+
+ LargeRep OldRep = std::move(*getLargeRep());
+ getLargeRep()->~LargeRep();
+ if (AtLeast <= InlineBuckets) {
+ Small = true;
+ } else {
+ new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
+ }
+
+ this->moveFromOldBuckets(OldRep.Buckets, OldRep.Buckets+OldRep.NumBuckets);
+
+ // Free the old table.
+ deallocate_buffer(OldRep.Buckets, sizeof(BucketT) * OldRep.NumBuckets,
+ alignof(BucketT));
+ }
+
+ void shrink_and_clear() {
+ unsigned OldSize = this->size();
+ this->destroyAll();
+
+ // Reduce the number of buckets.
+ unsigned NewNumBuckets = 0;
+ if (OldSize) {
+ NewNumBuckets = 1 << (Log2_32_Ceil(OldSize) + 1);
+ if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u)
+ NewNumBuckets = 64;
+ }
+ if ((Small && NewNumBuckets <= InlineBuckets) ||
+ (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) {
+ this->BaseT::initEmpty();
+ return;
+ }
+
+ deallocateBuckets();
+ init(NewNumBuckets);
+ }
+
+private:
+ unsigned getNumEntries() const {
+ return NumEntries;
+ }
+
+ void setNumEntries(unsigned Num) {
+ // NumEntries is hardcoded to be 31 bits wide.
+ assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries");
+ NumEntries = Num;
+ }
+
+ unsigned getNumTombstones() const {
+ return NumTombstones;
+ }
+
+ void setNumTombstones(unsigned Num) {
+ NumTombstones = Num;
+ }
+
+ const BucketT *getInlineBuckets() const {
+ assert(Small);
+ // Note that this cast does not violate aliasing rules as we assert that
+ // the memory's dynamic type is the small, inline bucket buffer, and the
+ // 'storage.buffer' static type is 'char *'.
+ return reinterpret_cast<const BucketT *>(storage.buffer);
+ }
+
+ BucketT *getInlineBuckets() {
+ return const_cast<BucketT *>(
+ const_cast<const SmallDenseMap *>(this)->getInlineBuckets());
+ }
+
+ const LargeRep *getLargeRep() const {
+ assert(!Small);
+ // Note, same rule about aliasing as with getInlineBuckets.
+ return reinterpret_cast<const LargeRep *>(storage.buffer);
+ }
+
+ LargeRep *getLargeRep() {
+ return const_cast<LargeRep *>(
+ const_cast<const SmallDenseMap *>(this)->getLargeRep());
+ }
+
+ const BucketT *getBuckets() const {
+ return Small ? getInlineBuckets() : getLargeRep()->Buckets;
+ }
+
+ BucketT *getBuckets() {
+ return const_cast<BucketT *>(
+ const_cast<const SmallDenseMap *>(this)->getBuckets());
+ }
+
+ unsigned getNumBuckets() const {
+ return Small ? InlineBuckets : getLargeRep()->NumBuckets;
+ }
+
+ void deallocateBuckets() {
+ if (Small)
+ return;
+
+ deallocate_buffer(getLargeRep()->Buckets,
+ sizeof(BucketT) * getLargeRep()->NumBuckets,
+ alignof(BucketT));
+ getLargeRep()->~LargeRep();
+ }
+
+ LargeRep allocateBuckets(unsigned Num) {
+ assert(Num > InlineBuckets && "Must allocate more buckets than are inline");
+ LargeRep Rep = {static_cast<BucketT *>(allocate_buffer(
+ sizeof(BucketT) * Num, alignof(BucketT))),
+ Num};
+ return Rep;
+ }
+};
+
+template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
+ bool IsConst>
+class DenseMapIterator : DebugEpochBase::HandleBase {
+ friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
+ friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
+
+ using ConstIterator = DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
+
+public:
+ using difference_type = ptrdiff_t;
+ using value_type =
+ typename std::conditional<IsConst, const Bucket, Bucket>::type;
+ using pointer = value_type *;
+ using reference = value_type &;
+ using iterator_category = std::forward_iterator_tag;
+
+private:
+ pointer Ptr = nullptr;
+ pointer End = nullptr;
+
+public:
+ DenseMapIterator() = default;
+
+ DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch,
+ bool NoAdvance = false)
+ : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) {
+ assert(isHandleInSync() && "invalid construction!");
+
+ if (NoAdvance) return;
+ if (shouldReverseIterate<KeyT>()) {
+ RetreatPastEmptyBuckets();
+ return;
+ }
+ AdvancePastEmptyBuckets();
+ }
+
+ // Converting ctor from non-const iterators to const iterators. SFINAE'd out
+ // for const iterator destinations so it doesn't end up as a user defined copy
+ // constructor.
+ template <bool IsConstSrc,
+ typename = typename std::enable_if<!IsConstSrc && IsConst>::type>
+ DenseMapIterator(
+ const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
+ : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {}
+
+ reference operator*() const {
+ assert(isHandleInSync() && "invalid iterator access!");
+ if (shouldReverseIterate<KeyT>())
+ return Ptr[-1];
+ return *Ptr;
+ }
+ pointer operator->() const {
+ assert(isHandleInSync() && "invalid iterator access!");
+ if (shouldReverseIterate<KeyT>())
+ return &(Ptr[-1]);
+ return Ptr;
+ }
+
+ bool operator==(const ConstIterator &RHS) const {
+ assert((!Ptr || isHandleInSync()) && "handle not in sync!");
+ assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
+ assert(getEpochAddress() == RHS.getEpochAddress() &&
+ "comparing incomparable iterators!");
+ return Ptr == RHS.Ptr;
+ }
+ bool operator!=(const ConstIterator &RHS) const {
+ assert((!Ptr || isHandleInSync()) && "handle not in sync!");
+ assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
+ assert(getEpochAddress() == RHS.getEpochAddress() &&
+ "comparing incomparable iterators!");
+ return Ptr != RHS.Ptr;
+ }
+
+ inline DenseMapIterator& operator++() { // Preincrement
+ assert(isHandleInSync() && "invalid iterator access!");
+ if (shouldReverseIterate<KeyT>()) {
+ --Ptr;
+ RetreatPastEmptyBuckets();
+ return *this;
+ }
+ ++Ptr;
+ AdvancePastEmptyBuckets();
+ return *this;
+ }
+ DenseMapIterator operator++(int) { // Postincrement
+ assert(isHandleInSync() && "invalid iterator access!");
+ DenseMapIterator tmp = *this; ++*this; return tmp;
+ }
+
+private:
+ void AdvancePastEmptyBuckets() {
+ assert(Ptr <= End);
+ const KeyT Empty = KeyInfoT::getEmptyKey();
+ const KeyT Tombstone = KeyInfoT::getTombstoneKey();
+
+ while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) ||
+ KeyInfoT::isEqual(Ptr->getFirst(), Tombstone)))
+ ++Ptr;
+ }
+
+ void RetreatPastEmptyBuckets() {
+ assert(Ptr >= End);
+ const KeyT Empty = KeyInfoT::getEmptyKey();
+ const KeyT Tombstone = KeyInfoT::getTombstoneKey();
+
+ while (Ptr != End && (KeyInfoT::isEqual(Ptr[-1].getFirst(), Empty) ||
+ KeyInfoT::isEqual(Ptr[-1].getFirst(), Tombstone)))
+ --Ptr;
+ }
+};
+
+template <typename KeyT, typename ValueT, typename KeyInfoT>
+inline size_t capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) {
+ return X.getMemorySize();
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_DENSEMAP_H
diff --git a/third_party/llvm-project/include/llvm/ADT/DenseMapInfo.h b/third_party/llvm-project/include/llvm/ADT/DenseMapInfo.h
new file mode 100644
index 000000000..bd4c60c8f
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/DenseMapInfo.h
@@ -0,0 +1,300 @@
+//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines DenseMapInfo traits for DenseMap.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_DENSEMAPINFO_H
+#define LLVM_ADT_DENSEMAPINFO_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm/Support/TypeSize.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <utility>
+
+namespace llvm {
+
+template<typename T>
+struct DenseMapInfo {
+ //static inline T getEmptyKey();
+ //static inline T getTombstoneKey();
+ //static unsigned getHashValue(const T &Val);
+ //static bool isEqual(const T &LHS, const T &RHS);
+};
+
+// Provide DenseMapInfo for all pointers.
+template<typename T>
+struct DenseMapInfo<T*> {
+ static inline T* getEmptyKey() {
+ uintptr_t Val = static_cast<uintptr_t>(-1);
+ Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
+ return reinterpret_cast<T*>(Val);
+ }
+
+ static inline T* getTombstoneKey() {
+ uintptr_t Val = static_cast<uintptr_t>(-2);
+ Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
+ return reinterpret_cast<T*>(Val);
+ }
+
+ static unsigned getHashValue(const T *PtrVal) {
+ return (unsigned((uintptr_t)PtrVal) >> 4) ^
+ (unsigned((uintptr_t)PtrVal) >> 9);
+ }
+
+ static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
+};
+
+// Provide DenseMapInfo for chars.
+template<> struct DenseMapInfo<char> {
+ static inline char getEmptyKey() { return ~0; }
+ static inline char getTombstoneKey() { return ~0 - 1; }
+ static unsigned getHashValue(const char& Val) { return Val * 37U; }
+
+ static bool isEqual(const char &LHS, const char &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for unsigned chars.
+template <> struct DenseMapInfo<unsigned char> {
+ static inline unsigned char getEmptyKey() { return ~0; }
+ static inline unsigned char getTombstoneKey() { return ~0 - 1; }
+ static unsigned getHashValue(const unsigned char &Val) { return Val * 37U; }
+
+ static bool isEqual(const unsigned char &LHS, const unsigned char &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for unsigned shorts.
+template <> struct DenseMapInfo<unsigned short> {
+ static inline unsigned short getEmptyKey() { return 0xFFFF; }
+ static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; }
+ static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
+
+ static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for unsigned ints.
+template<> struct DenseMapInfo<unsigned> {
+ static inline unsigned getEmptyKey() { return ~0U; }
+ static inline unsigned getTombstoneKey() { return ~0U - 1; }
+ static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
+
+ static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for unsigned longs.
+template<> struct DenseMapInfo<unsigned long> {
+ static inline unsigned long getEmptyKey() { return ~0UL; }
+ static inline unsigned long getTombstoneKey() { return ~0UL - 1L; }
+
+ static unsigned getHashValue(const unsigned long& Val) {
+ return (unsigned)(Val * 37UL);
+ }
+
+ static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for unsigned long longs.
+template<> struct DenseMapInfo<unsigned long long> {
+ static inline unsigned long long getEmptyKey() { return ~0ULL; }
+ static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
+
+ static unsigned getHashValue(const unsigned long long& Val) {
+ return (unsigned)(Val * 37ULL);
+ }
+
+ static bool isEqual(const unsigned long long& LHS,
+ const unsigned long long& RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for shorts.
+template <> struct DenseMapInfo<short> {
+ static inline short getEmptyKey() { return 0x7FFF; }
+ static inline short getTombstoneKey() { return -0x7FFF - 1; }
+ static unsigned getHashValue(const short &Val) { return Val * 37U; }
+ static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; }
+};
+
+// Provide DenseMapInfo for ints.
+template<> struct DenseMapInfo<int> {
+ static inline int getEmptyKey() { return 0x7fffffff; }
+ static inline int getTombstoneKey() { return -0x7fffffff - 1; }
+ static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
+
+ static bool isEqual(const int& LHS, const int& RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for longs.
+template<> struct DenseMapInfo<long> {
+ static inline long getEmptyKey() {
+ return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
+ }
+
+ static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
+
+ static unsigned getHashValue(const long& Val) {
+ return (unsigned)(Val * 37UL);
+ }
+
+ static bool isEqual(const long& LHS, const long& RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for long longs.
+template<> struct DenseMapInfo<long long> {
+ static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
+ static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
+
+ static unsigned getHashValue(const long long& Val) {
+ return (unsigned)(Val * 37ULL);
+ }
+
+ static bool isEqual(const long long& LHS,
+ const long long& RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for all pairs whose members have info.
+template<typename T, typename U>
+struct DenseMapInfo<std::pair<T, U>> {
+ using Pair = std::pair<T, U>;
+ using FirstInfo = DenseMapInfo<T>;
+ using SecondInfo = DenseMapInfo<U>;
+
+ static inline Pair getEmptyKey() {
+ return std::make_pair(FirstInfo::getEmptyKey(),
+ SecondInfo::getEmptyKey());
+ }
+
+ static inline Pair getTombstoneKey() {
+ return std::make_pair(FirstInfo::getTombstoneKey(),
+ SecondInfo::getTombstoneKey());
+ }
+
+ static unsigned getHashValue(const Pair& PairVal) {
+ uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32
+ | (uint64_t)SecondInfo::getHashValue(PairVal.second);
+ key += ~(key << 32);
+ key ^= (key >> 22);
+ key += ~(key << 13);
+ key ^= (key >> 8);
+ key += (key << 3);
+ key ^= (key >> 15);
+ key += ~(key << 27);
+ key ^= (key >> 31);
+ return (unsigned)key;
+ }
+
+ static bool isEqual(const Pair &LHS, const Pair &RHS) {
+ return FirstInfo::isEqual(LHS.first, RHS.first) &&
+ SecondInfo::isEqual(LHS.second, RHS.second);
+ }
+};
+
+// Provide DenseMapInfo for StringRefs.
+template <> struct DenseMapInfo<StringRef> {
+ static inline StringRef getEmptyKey() {
+ return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
+ 0);
+ }
+
+ static inline StringRef getTombstoneKey() {
+ return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)),
+ 0);
+ }
+
+ static unsigned getHashValue(StringRef Val) {
+ assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
+ assert(Val.data() != getTombstoneKey().data() &&
+ "Cannot hash the tombstone key!");
+ return (unsigned)(hash_value(Val));
+ }
+
+ static bool isEqual(StringRef LHS, StringRef RHS) {
+ if (RHS.data() == getEmptyKey().data())
+ return LHS.data() == getEmptyKey().data();
+ if (RHS.data() == getTombstoneKey().data())
+ return LHS.data() == getTombstoneKey().data();
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for ArrayRefs.
+template <typename T> struct DenseMapInfo<ArrayRef<T>> {
+ static inline ArrayRef<T> getEmptyKey() {
+ return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)),
+ size_t(0));
+ }
+
+ static inline ArrayRef<T> getTombstoneKey() {
+ return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)),
+ size_t(0));
+ }
+
+ static unsigned getHashValue(ArrayRef<T> Val) {
+ assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
+ assert(Val.data() != getTombstoneKey().data() &&
+ "Cannot hash the tombstone key!");
+ return (unsigned)(hash_value(Val));
+ }
+
+ static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) {
+ if (RHS.data() == getEmptyKey().data())
+ return LHS.data() == getEmptyKey().data();
+ if (RHS.data() == getTombstoneKey().data())
+ return LHS.data() == getTombstoneKey().data();
+ return LHS == RHS;
+ }
+};
+
+template <> struct DenseMapInfo<hash_code> {
+ static inline hash_code getEmptyKey() { return hash_code(-1); }
+ static inline hash_code getTombstoneKey() { return hash_code(-2); }
+ static unsigned getHashValue(hash_code val) { return val; }
+ static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
+};
+
+template <> struct DenseMapInfo<ElementCount> {
+ static inline ElementCount getEmptyKey() { return {~0U, true}; }
+ static inline ElementCount getTombstoneKey() { return {~0U - 1, false}; }
+ static unsigned getHashValue(const ElementCount& EltCnt) {
+ if (EltCnt.Scalable)
+ return (EltCnt.Min * 37U) - 1U;
+
+ return EltCnt.Min * 37U;
+ }
+
+ static bool isEqual(const ElementCount& LHS, const ElementCount& RHS) {
+ return LHS == RHS;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_DENSEMAPINFO_H
diff --git a/third_party/llvm-project/include/llvm/ADT/DenseSet.h b/third_party/llvm-project/include/llvm/ADT/DenseSet.h
new file mode 100644
index 000000000..9afb715ae
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/DenseSet.h
@@ -0,0 +1,283 @@
+//===- llvm/ADT/DenseSet.h - Dense probed hash table ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DenseSet and SmallDenseSet classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_DENSESET_H
+#define LLVM_ADT_DENSESET_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/type_traits.h"
+#include <algorithm>
+#include <cstddef>
+#include <initializer_list>
+#include <iterator>
+#include <utility>
+
+namespace llvm {
+
+namespace detail {
+
+struct DenseSetEmpty {};
+
+// Use the empty base class trick so we can create a DenseMap where the buckets
+// contain only a single item.
+template <typename KeyT> class DenseSetPair : public DenseSetEmpty {
+ KeyT key;
+
+public:
+ KeyT &getFirst() { return key; }
+ const KeyT &getFirst() const { return key; }
+ DenseSetEmpty &getSecond() { return *this; }
+ const DenseSetEmpty &getSecond() const { return *this; }
+};
+
+/// Base class for DenseSet and DenseSmallSet.
+///
+/// MapTy should be either
+///
+/// DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
+/// detail::DenseSetPair<ValueT>>
+///
+/// or the equivalent SmallDenseMap type. ValueInfoT must implement the
+/// DenseMapInfo "concept".
+template <typename ValueT, typename MapTy, typename ValueInfoT>
+class DenseSetImpl {
+ static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
+ "DenseMap buckets unexpectedly large!");
+ MapTy TheMap;
+
+ template <typename T>
+ using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
+
+public:
+ using key_type = ValueT;
+ using value_type = ValueT;
+ using size_type = unsigned;
+
+ explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {}
+
+ DenseSetImpl(std::initializer_list<ValueT> Elems)
+ : DenseSetImpl(PowerOf2Ceil(Elems.size())) {
+ insert(Elems.begin(), Elems.end());
+ }
+
+ bool empty() const { return TheMap.empty(); }
+ size_type size() const { return TheMap.size(); }
+ size_t getMemorySize() const { return TheMap.getMemorySize(); }
+
+ /// Grow the DenseSet so that it has at least Size buckets. Will not shrink
+ /// the Size of the set.
+ void resize(size_t Size) { TheMap.resize(Size); }
+
+ /// Grow the DenseSet so that it can contain at least \p NumEntries items
+ /// before resizing again.
+ void reserve(size_t Size) { TheMap.reserve(Size); }
+
+ void clear() {
+ TheMap.clear();
+ }
+
+ /// Return 1 if the specified key is in the set, 0 otherwise.
+ size_type count(const_arg_type_t<ValueT> V) const {
+ return TheMap.count(V);
+ }
+
+ bool erase(const ValueT &V) {
+ return TheMap.erase(V);
+ }
+
+ void swap(DenseSetImpl &RHS) { TheMap.swap(RHS.TheMap); }
+
+ // Iterators.
+
+ class ConstIterator;
+
+ class Iterator {
+ typename MapTy::iterator I;
+ friend class DenseSetImpl;
+ friend class ConstIterator;
+
+ public:
+ using difference_type = typename MapTy::iterator::difference_type;
+ using value_type = ValueT;
+ using pointer = value_type *;
+ using reference = value_type &;
+ using iterator_category = std::forward_iterator_tag;
+
+ Iterator() = default;
+ Iterator(const typename MapTy::iterator &i) : I(i) {}
+
+ ValueT &operator*() { return I->getFirst(); }
+ const ValueT &operator*() const { return I->getFirst(); }
+ ValueT *operator->() { return &I->getFirst(); }
+ const ValueT *operator->() const { return &I->getFirst(); }
+
+ Iterator& operator++() { ++I; return *this; }
+ Iterator operator++(int) { auto T = *this; ++I; return T; }
+ bool operator==(const ConstIterator& X) const { return I == X.I; }
+ bool operator!=(const ConstIterator& X) const { return I != X.I; }
+ };
+
+ class ConstIterator {
+ typename MapTy::const_iterator I;
+ friend class DenseSetImpl;
+ friend class Iterator;
+
+ public:
+ using difference_type = typename MapTy::const_iterator::difference_type;
+ using value_type = ValueT;
+ using pointer = const value_type *;
+ using reference = const value_type &;
+ using iterator_category = std::forward_iterator_tag;
+
+ ConstIterator() = default;
+ ConstIterator(const Iterator &B) : I(B.I) {}
+ ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}
+
+ const ValueT &operator*() const { return I->getFirst(); }
+ const ValueT *operator->() const { return &I->getFirst(); }
+
+ ConstIterator& operator++() { ++I; return *this; }
+ ConstIterator operator++(int) { auto T = *this; ++I; return T; }
+ bool operator==(const ConstIterator& X) const { return I == X.I; }
+ bool operator!=(const ConstIterator& X) const { return I != X.I; }
+ };
+
+ using iterator = Iterator;
+ using const_iterator = ConstIterator;
+
+ iterator begin() { return Iterator(TheMap.begin()); }
+ iterator end() { return Iterator(TheMap.end()); }
+
+ const_iterator begin() const { return ConstIterator(TheMap.begin()); }
+ const_iterator end() const { return ConstIterator(TheMap.end()); }
+
+ iterator find(const_arg_type_t<ValueT> V) { return Iterator(TheMap.find(V)); }
+ const_iterator find(const_arg_type_t<ValueT> V) const {
+ return ConstIterator(TheMap.find(V));
+ }
+
+ /// Alternative version of find() which allows a different, and possibly less
+ /// expensive, key type.
+ /// The DenseMapInfo is responsible for supplying methods
+ /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key type
+ /// used.
+ template <class LookupKeyT>
+ iterator find_as(const LookupKeyT &Val) {
+ return Iterator(TheMap.find_as(Val));
+ }
+ template <class LookupKeyT>
+ const_iterator find_as(const LookupKeyT &Val) const {
+ return ConstIterator(TheMap.find_as(Val));
+ }
+
+ void erase(Iterator I) { return TheMap.erase(I.I); }
+ void erase(ConstIterator CI) { return TheMap.erase(CI.I); }
+
+ std::pair<iterator, bool> insert(const ValueT &V) {
+ detail::DenseSetEmpty Empty;
+ return TheMap.try_emplace(V, Empty);
+ }
+
+ std::pair<iterator, bool> insert(ValueT &&V) {
+ detail::DenseSetEmpty Empty;
+ return TheMap.try_emplace(std::move(V), Empty);
+ }
+
+ /// Alternative version of insert that uses a different (and possibly less
+ /// expensive) key type.
+ template <typename LookupKeyT>
+ std::pair<iterator, bool> insert_as(const ValueT &V,
+ const LookupKeyT &LookupKey) {
+ return TheMap.insert_as({V, detail::DenseSetEmpty()}, LookupKey);
+ }
+ template <typename LookupKeyT>
+ std::pair<iterator, bool> insert_as(ValueT &&V, const LookupKeyT &LookupKey) {
+ return TheMap.insert_as({std::move(V), detail::DenseSetEmpty()}, LookupKey);
+ }
+
+ // Range insertion of values.
+ template<typename InputIt>
+ void insert(InputIt I, InputIt E) {
+ for (; I != E; ++I)
+ insert(*I);
+ }
+};
+
+/// Equality comparison for DenseSet.
+///
+/// Iterates over elements of LHS confirming that each element is also a member
+/// of RHS, and that RHS contains no additional values.
+/// Equivalent to N calls to RHS.count. Amortized complexity is linear, worst
+/// case is O(N^2) (if every hash collides).
+template <typename ValueT, typename MapTy, typename ValueInfoT>
+bool operator==(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
+ const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
+ if (LHS.size() != RHS.size())
+ return false;
+
+ for (auto &E : LHS)
+ if (!RHS.count(E))
+ return false;
+
+ return true;
+}
+
+/// Inequality comparison for DenseSet.
+///
+/// Equivalent to !(LHS == RHS). See operator== for performance notes.
+template <typename ValueT, typename MapTy, typename ValueInfoT>
+bool operator!=(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
+ const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
+ return !(LHS == RHS);
+}
+
+} // end namespace detail
+
+/// Implements a dense probed hash-table based set.
+template <typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT>>
+class DenseSet : public detail::DenseSetImpl<
+ ValueT, DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
+ detail::DenseSetPair<ValueT>>,
+ ValueInfoT> {
+ using BaseT =
+ detail::DenseSetImpl<ValueT,
+ DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
+ detail::DenseSetPair<ValueT>>,
+ ValueInfoT>;
+
+public:
+ using BaseT::BaseT;
+};
+
+/// Implements a dense probed hash-table based set with some number of buckets
+/// stored inline.
+template <typename ValueT, unsigned InlineBuckets = 4,
+ typename ValueInfoT = DenseMapInfo<ValueT>>
+class SmallDenseSet
+ : public detail::DenseSetImpl<
+ ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets,
+ ValueInfoT, detail::DenseSetPair<ValueT>>,
+ ValueInfoT> {
+ using BaseT = detail::DenseSetImpl<
+ ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets,
+ ValueInfoT, detail::DenseSetPair<ValueT>>,
+ ValueInfoT>;
+
+public:
+ using BaseT::BaseT;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_DENSESET_H
diff --git a/third_party/llvm-project/include/llvm/ADT/EpochTracker.h b/third_party/llvm-project/include/llvm/ADT/EpochTracker.h
new file mode 100644
index 000000000..a782b4756
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/EpochTracker.h
@@ -0,0 +1,98 @@
+//===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
+// These can be used to write iterators that are fail-fast when LLVM is built
+// with asserts enabled.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_EPOCH_TRACKER_H
+#define LLVM_ADT_EPOCH_TRACKER_H
+
+#include "llvm/Config/abi-breaking.h"
+
+#include <cstdint>
+
+namespace llvm {
+
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+
+/// A base class for data structure classes wishing to make iterators
+/// ("handles") pointing into themselves fail-fast. When building without
+/// asserts, this class is empty and does nothing.
+///
+/// DebugEpochBase does not by itself track handles pointing into itself. The
+/// expectation is that routines touching the handles will poll on
+/// isHandleInSync at appropriate points to assert that the handle they're using
+/// is still valid.
+///
+class DebugEpochBase {
+ uint64_t Epoch;
+
+public:
+ DebugEpochBase() : Epoch(0) {}
+
+ /// Calling incrementEpoch invalidates all handles pointing into the
+ /// calling instance.
+ void incrementEpoch() { ++Epoch; }
+
+ /// The destructor calls incrementEpoch to make use-after-free bugs
+ /// more likely to crash deterministically.
+ ~DebugEpochBase() { incrementEpoch(); }
+
+ /// A base class for iterator classes ("handles") that wish to poll for
+ /// iterator invalidating modifications in the underlying data structure.
+ /// When LLVM is built without asserts, this class is empty and does nothing.
+ ///
+ /// HandleBase does not track the parent data structure by itself. It expects
+ /// the routines modifying the data structure to call incrementEpoch when they
+ /// make an iterator-invalidating modification.
+ ///
+ class HandleBase {
+ const uint64_t *EpochAddress;
+ uint64_t EpochAtCreation;
+
+ public:
+ HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {}
+
+ explicit HandleBase(const DebugEpochBase *Parent)
+ : EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {}
+
+ /// Returns true if the DebugEpochBase this Handle is linked to has
+ /// not called incrementEpoch on itself since the creation of this
+ /// HandleBase instance.
+ bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; }
+
+ /// Returns a pointer to the epoch word stored in the data structure
+ /// this handle points into. Can be used to check if two iterators point
+ /// into the same data structure.
+ const void *getEpochAddress() const { return EpochAddress; }
+ };
+};
+
+#else
+
+class DebugEpochBase {
+public:
+ void incrementEpoch() {}
+
+ class HandleBase {
+ public:
+ HandleBase() = default;
+ explicit HandleBase(const DebugEpochBase *) {}
+ bool isHandleInSync() const { return true; }
+ const void *getEpochAddress() const { return nullptr; }
+ };
+};
+
+#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/ADT/FoldingSet.h b/third_party/llvm-project/include/llvm/ADT/FoldingSet.h
new file mode 100644
index 000000000..d5837e51b
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/FoldingSet.h
@@ -0,0 +1,761 @@
+//===- llvm/ADT/FoldingSet.h - Uniquing Hash Set ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a hash set that can be used to remove duplication of nodes
+// in a graph. This code was originally created by Chris Lattner for use with
+// SelectionDAGCSEMap, but was isolated to provide use across the llvm code set.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_FOLDINGSET_H
+#define LLVM_ADT_FOLDINGSET_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <utility>
+
+namespace llvm {
+
+/// This folding set used for two purposes:
+/// 1. Given information about a node we want to create, look up the unique
+/// instance of the node in the set. If the node already exists, return
+/// it, otherwise return the bucket it should be inserted into.
+/// 2. Given a node that has already been created, remove it from the set.
+///
+/// This class is implemented as a single-link chained hash table, where the
+/// "buckets" are actually the nodes themselves (the next pointer is in the
+/// node). The last node points back to the bucket to simplify node removal.
+///
+/// Any node that is to be included in the folding set must be a subclass of
+/// FoldingSetNode. The node class must also define a Profile method used to
+/// establish the unique bits of data for the node. The Profile method is
+/// passed a FoldingSetNodeID object which is used to gather the bits. Just
+/// call one of the Add* functions defined in the FoldingSetBase::NodeID class.
+/// NOTE: That the folding set does not own the nodes and it is the
+/// responsibility of the user to dispose of the nodes.
+///
+/// Eg.
+/// class MyNode : public FoldingSetNode {
+/// private:
+/// std::string Name;
+/// unsigned Value;
+/// public:
+/// MyNode(const char *N, unsigned V) : Name(N), Value(V) {}
+/// ...
+/// void Profile(FoldingSetNodeID &ID) const {
+/// ID.AddString(Name);
+/// ID.AddInteger(Value);
+/// }
+/// ...
+/// };
+///
+/// To define the folding set itself use the FoldingSet template;
+///
+/// Eg.
+/// FoldingSet<MyNode> MyFoldingSet;
+///
+/// Four public methods are available to manipulate the folding set;
+///
+/// 1) If you have an existing node that you want add to the set but unsure
+/// that the node might already exist then call;
+///
+/// MyNode *M = MyFoldingSet.GetOrInsertNode(N);
+///
+/// If The result is equal to the input then the node has been inserted.
+/// Otherwise, the result is the node existing in the folding set, and the
+/// input can be discarded (use the result instead.)
+///
+/// 2) If you are ready to construct a node but want to check if it already
+/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to
+/// check;
+///
+/// FoldingSetNodeID ID;
+/// ID.AddString(Name);
+/// ID.AddInteger(Value);
+/// void *InsertPoint;
+///
+/// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint);
+///
+/// If found then M with be non-NULL, else InsertPoint will point to where it
+/// should be inserted using InsertNode.
+///
+/// 3) If you get a NULL result from FindNodeOrInsertPos then you can as a new
+/// node with FindNodeOrInsertPos;
+///
+/// InsertNode(N, InsertPoint);
+///
+/// 4) Finally, if you want to remove a node from the folding set call;
+///
+/// bool WasRemoved = RemoveNode(N);
+///
+/// The result indicates whether the node existed in the folding set.
+
+class FoldingSetNodeID;
+class StringRef;
+
+//===----------------------------------------------------------------------===//
+/// FoldingSetBase - Implements the folding set functionality. The main
+/// structure is an array of buckets. Each bucket is indexed by the hash of
+/// the nodes it contains. The bucket itself points to the nodes contained
+/// in the bucket via a singly linked list. The last node in the list points
+/// back to the bucket to facilitate node removal.
+///
+class FoldingSetBase {
+ virtual void anchor(); // Out of line virtual method.
+
+protected:
+ /// Buckets - Array of bucket chains.
+ void **Buckets;
+
+ /// NumBuckets - Length of the Buckets array. Always a power of 2.
+ unsigned NumBuckets;
+
+ /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes
+ /// is greater than twice the number of buckets.
+ unsigned NumNodes;
+
+ explicit FoldingSetBase(unsigned Log2InitSize = 6);
+ FoldingSetBase(FoldingSetBase &&Arg);
+ FoldingSetBase &operator=(FoldingSetBase &&RHS);
+ ~FoldingSetBase();
+
+public:
+ //===--------------------------------------------------------------------===//
+ /// Node - This class is used to maintain the singly linked bucket list in
+ /// a folding set.
+ class Node {
+ private:
+ // NextInFoldingSetBucket - next link in the bucket list.
+ void *NextInFoldingSetBucket = nullptr;
+
+ public:
+ Node() = default;
+
+ // Accessors
+ void *getNextInBucket() const { return NextInFoldingSetBucket; }
+ void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; }
+ };
+
+ /// clear - Remove all nodes from the folding set.
+ void clear();
+
+ /// size - Returns the number of nodes in the folding set.
+ unsigned size() const { return NumNodes; }
+
+ /// empty - Returns true if there are no nodes in the folding set.
+ bool empty() const { return NumNodes == 0; }
+
+ /// reserve - Increase the number of buckets such that adding the
+ /// EltCount-th node won't cause a rebucket operation. reserve is permitted
+ /// to allocate more space than requested by EltCount.
+ void reserve(unsigned EltCount);
+
+ /// capacity - Returns the number of nodes permitted in the folding set
+ /// before a rebucket operation is performed.
+ unsigned capacity() {
+ // We allow a load factor of up to 2.0,
+ // so that means our capacity is NumBuckets * 2
+ return NumBuckets * 2;
+ }
+
+private:
+ /// GrowHashTable - Double the size of the hash table and rehash everything.
+ void GrowHashTable();
+
+ /// GrowBucketCount - resize the hash table and rehash everything.
+ /// NewBucketCount must be a power of two, and must be greater than the old
+ /// bucket count.
+ void GrowBucketCount(unsigned NewBucketCount);
+
+protected:
+ /// GetNodeProfile - Instantiations of the FoldingSet template implement
+ /// this function to gather data bits for the given node.
+ virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const = 0;
+
+ /// NodeEquals - Instantiations of the FoldingSet template implement
+ /// this function to compare the given node with the given ID.
+ virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
+ FoldingSetNodeID &TempID) const=0;
+
+ /// ComputeNodeHash - Instantiations of the FoldingSet template implement
+ /// this function to compute a hash value for the given node.
+ virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const = 0;
+
+ // The below methods are protected to encourage subclasses to provide a more
+ // type-safe API.
+
+ /// 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 RemoveNode(Node *N);
+
+ /// GetOrInsertNode - If there is an existing simple Node exactly
+ /// equal to the specified node, return it. Otherwise, insert 'N' and return
+ /// it instead.
+ Node *GetOrInsertNode(Node *N);
+
+ /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
+ /// return it. If not, return the insertion token that will make insertion
+ /// faster.
+ Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos);
+
+ /// InsertNode - Insert the specified node into the folding set, knowing that
+ /// it is not already in the folding set. InsertPos must be obtained from
+ /// FindNodeOrInsertPos.
+ void InsertNode(Node *N, void *InsertPos);
+};
+
+//===----------------------------------------------------------------------===//
+
+/// DefaultFoldingSetTrait - This class provides default implementations
+/// for FoldingSetTrait implementations.
+template<typename T> struct DefaultFoldingSetTrait {
+ static void Profile(const T &X, FoldingSetNodeID &ID) {
+ X.Profile(ID);
+ }
+ static void Profile(T &X, FoldingSetNodeID &ID) {
+ X.Profile(ID);
+ }
+
+ // Equals - Test if the profile for X would match ID, using TempID
+ // to compute a temporary ID if necessary. The default implementation
+ // just calls Profile and does a regular comparison. Implementations
+ // can override this to provide more efficient implementations.
+ static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
+ FoldingSetNodeID &TempID);
+
+ // ComputeHash - Compute a hash value for X, using TempID to
+ // compute a temporary ID if necessary. The default implementation
+ // just calls Profile and does a regular hash computation.
+ // Implementations can override this to provide more efficient
+ // implementations.
+ static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID);
+};
+
+/// FoldingSetTrait - This trait class is used to define behavior of how
+/// to "profile" (in the FoldingSet parlance) an object of a given type.
+/// The default behavior is to invoke a 'Profile' method on an object, but
+/// through template specialization the behavior can be tailored for specific
+/// types. Combined with the FoldingSetNodeWrapper class, one can add objects
+/// to FoldingSets that were not originally designed to have that behavior.
+template<typename T> struct FoldingSetTrait
+ : public DefaultFoldingSetTrait<T> {};
+
+/// DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but
+/// for ContextualFoldingSets.
+template<typename T, typename Ctx>
+struct DefaultContextualFoldingSetTrait {
+ static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
+ X.Profile(ID, Context);
+ }
+
+ static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
+ FoldingSetNodeID &TempID, Ctx Context);
+ static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID,
+ Ctx Context);
+};
+
+/// ContextualFoldingSetTrait - Like FoldingSetTrait, but for
+/// ContextualFoldingSets.
+template<typename T, typename Ctx> struct ContextualFoldingSetTrait
+ : public DefaultContextualFoldingSetTrait<T, Ctx> {};
+
+//===--------------------------------------------------------------------===//
+/// FoldingSetNodeIDRef - This class describes a reference to an interned
+/// FoldingSetNodeID, which can be a useful to store node id data rather
+/// than using plain FoldingSetNodeIDs, since the 32-element SmallVector
+/// is often much larger than necessary, and the possibility of heap
+/// allocation means it requires a non-trivial destructor call.
+class FoldingSetNodeIDRef {
+ const unsigned *Data = nullptr;
+ size_t Size = 0;
+
+public:
+ FoldingSetNodeIDRef() = default;
+ FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {}
+
+ /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
+ /// used to lookup the node in the FoldingSetBase.
+ unsigned ComputeHash() const;
+
+ bool operator==(FoldingSetNodeIDRef) const;
+
+ bool operator!=(FoldingSetNodeIDRef RHS) const { return !(*this == RHS); }
+
+ /// Used to compare the "ordering" of two nodes as defined by the
+ /// profiled bits and their ordering defined by memcmp().
+ bool operator<(FoldingSetNodeIDRef) const;
+
+ const unsigned *getData() const { return Data; }
+ size_t getSize() const { return Size; }
+};
+
+//===--------------------------------------------------------------------===//
+/// FoldingSetNodeID - This class is used to gather all the unique data bits of
+/// a node. When all the bits are gathered this class is used to produce a
+/// hash value for the node.
+class FoldingSetNodeID {
+ /// Bits - Vector of all the data bits that make the node unique.
+ /// Use a SmallVector to avoid a heap allocation in the common case.
+ SmallVector<unsigned, 32> Bits;
+
+public:
+ FoldingSetNodeID() = default;
+
+ FoldingSetNodeID(FoldingSetNodeIDRef Ref)
+ : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {}
+
+ /// Add* - Add various data types to Bit data.
+ void AddPointer(const void *Ptr);
+ void AddInteger(signed I);
+ void AddInteger(unsigned I);
+ void AddInteger(long I);
+ void AddInteger(unsigned long I);
+ void AddInteger(long long I);
+ void AddInteger(unsigned long long I);
+ void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); }
+ void AddString(StringRef String);
+ void AddNodeID(const FoldingSetNodeID &ID);
+
+ template <typename T>
+ inline void Add(const T &x) { FoldingSetTrait<T>::Profile(x, *this); }
+
+ /// clear - Clear the accumulated profile, allowing this FoldingSetNodeID
+ /// object to be used to compute a new profile.
+ inline void clear() { Bits.clear(); }
+
+ /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used
+ /// to lookup the node in the FoldingSetBase.
+ unsigned ComputeHash() const;
+
+ /// operator== - Used to compare two nodes to each other.
+ bool operator==(const FoldingSetNodeID &RHS) const;
+ bool operator==(const FoldingSetNodeIDRef RHS) const;
+
+ bool operator!=(const FoldingSetNodeID &RHS) const { return !(*this == RHS); }
+ bool operator!=(const FoldingSetNodeIDRef RHS) const { return !(*this ==RHS);}
+
+ /// Used to compare the "ordering" of two nodes as defined by the
+ /// profiled bits and their ordering defined by memcmp().
+ bool operator<(const FoldingSetNodeID &RHS) const;
+ bool operator<(const FoldingSetNodeIDRef RHS) const;
+
+ /// Intern - Copy this node's data to a memory region allocated from the
+ /// given allocator and return a FoldingSetNodeIDRef describing the
+ /// interned data.
+ FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const;
+};
+
+// Convenience type to hide the implementation of the folding set.
+using FoldingSetNode = FoldingSetBase::Node;
+template<class T> class FoldingSetIterator;
+template<class T> class FoldingSetBucketIterator;
+
+// Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which
+// require the definition of FoldingSetNodeID.
+template<typename T>
+inline bool
+DefaultFoldingSetTrait<T>::Equals(T &X, const FoldingSetNodeID &ID,
+ unsigned /*IDHash*/,
+ FoldingSetNodeID &TempID) {
+ FoldingSetTrait<T>::Profile(X, TempID);
+ return TempID == ID;
+}
+template<typename T>
+inline unsigned
+DefaultFoldingSetTrait<T>::ComputeHash(T &X, FoldingSetNodeID &TempID) {
+ FoldingSetTrait<T>::Profile(X, TempID);
+ return TempID.ComputeHash();
+}
+template<typename T, typename Ctx>
+inline bool
+DefaultContextualFoldingSetTrait<T, Ctx>::Equals(T &X,
+ const FoldingSetNodeID &ID,
+ unsigned /*IDHash*/,
+ FoldingSetNodeID &TempID,
+ Ctx Context) {
+ ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context);
+ return TempID == ID;
+}
+template<typename T, typename Ctx>
+inline unsigned
+DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X,
+ FoldingSetNodeID &TempID,
+ Ctx Context) {
+ ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context);
+ return TempID.ComputeHash();
+}
+
+//===----------------------------------------------------------------------===//
+/// FoldingSetImpl - An implementation detail that lets us share code between
+/// FoldingSet and ContextualFoldingSet.
+template <class T> class FoldingSetImpl : public FoldingSetBase {
+protected:
+ explicit FoldingSetImpl(unsigned Log2InitSize)
+ : FoldingSetBase(Log2InitSize) {}
+
+ FoldingSetImpl(FoldingSetImpl &&Arg) = default;
+ FoldingSetImpl &operator=(FoldingSetImpl &&RHS) = default;
+ ~FoldingSetImpl() = default;
+
+public:
+ using iterator = FoldingSetIterator<T>;
+
+ iterator begin() { return iterator(Buckets); }
+ iterator end() { return iterator(Buckets+NumBuckets); }
+
+ using const_iterator = FoldingSetIterator<const T>;
+
+ const_iterator begin() const { return const_iterator(Buckets); }
+ const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
+
+ using bucket_iterator = FoldingSetBucketIterator<T>;
+
+ bucket_iterator bucket_begin(unsigned hash) {
+ return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
+ }
+
+ bucket_iterator bucket_end(unsigned hash) {
+ return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
+ }
+
+ /// 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 RemoveNode(T *N) { return FoldingSetBase::RemoveNode(N); }
+
+ /// GetOrInsertNode - If there is an existing simple Node exactly
+ /// equal to the specified node, return it. Otherwise, insert 'N' and
+ /// return it instead.
+ T *GetOrInsertNode(T *N) {
+ return static_cast<T *>(FoldingSetBase::GetOrInsertNode(N));
+ }
+
+ /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
+ /// return it. If not, return the insertion token that will make insertion
+ /// faster.
+ T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
+ return static_cast<T *>(FoldingSetBase::FindNodeOrInsertPos(ID, InsertPos));
+ }
+
+ /// InsertNode - Insert the specified node into the folding set, knowing that
+ /// it is not already in the folding set. InsertPos must be obtained from
+ /// FindNodeOrInsertPos.
+ void InsertNode(T *N, void *InsertPos) {
+ FoldingSetBase::InsertNode(N, InsertPos);
+ }
+
+ /// InsertNode - Insert the specified node into the folding set, knowing that
+ /// it is not already in the folding set.
+ void InsertNode(T *N) {
+ T *Inserted = GetOrInsertNode(N);
+ (void)Inserted;
+ assert(Inserted == N && "Node already inserted!");
+ }
+};
+
+//===----------------------------------------------------------------------===//
+/// FoldingSet - This template class is used to instantiate a specialized
+/// implementation of the folding set to the node class T. T must be a
+/// subclass of FoldingSetNode and implement a Profile function.
+///
+/// Note that this set type is movable and move-assignable. However, its
+/// moved-from state is not a valid state for anything other than
+/// move-assigning and destroying. This is primarily to enable movable APIs
+/// that incorporate these objects.
+template <class T> class FoldingSet final : public FoldingSetImpl<T> {
+ using Super = FoldingSetImpl<T>;
+ using Node = typename Super::Node;
+
+ /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
+ /// way to convert nodes into a unique specifier.
+ void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override {
+ T *TN = static_cast<T *>(N);
+ FoldingSetTrait<T>::Profile(*TN, ID);
+ }
+
+ /// NodeEquals - Instantiations may optionally provide a way to compare a
+ /// node with a specified ID.
+ bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
+ FoldingSetNodeID &TempID) const override {
+ T *TN = static_cast<T *>(N);
+ return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID);
+ }
+
+ /// ComputeNodeHash - Instantiations may optionally provide a way to compute a
+ /// hash value directly from a node.
+ unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override {
+ T *TN = static_cast<T *>(N);
+ return FoldingSetTrait<T>::ComputeHash(*TN, TempID);
+ }
+
+public:
+ explicit FoldingSet(unsigned Log2InitSize = 6) : Super(Log2InitSize) {}
+ FoldingSet(FoldingSet &&Arg) = default;
+ FoldingSet &operator=(FoldingSet &&RHS) = default;
+};
+
+//===----------------------------------------------------------------------===//
+/// ContextualFoldingSet - This template class is a further refinement
+/// of FoldingSet which provides a context argument when calling
+/// Profile on its nodes. Currently, that argument is fixed at
+/// initialization time.
+///
+/// T must be a subclass of FoldingSetNode and implement a Profile
+/// function with signature
+/// void Profile(FoldingSetNodeID &, Ctx);
+template <class T, class Ctx>
+class ContextualFoldingSet final : public FoldingSetImpl<T> {
+ // Unfortunately, this can't derive from FoldingSet<T> because the
+ // construction of the vtable for FoldingSet<T> requires
+ // FoldingSet<T>::GetNodeProfile to be instantiated, which in turn
+ // requires a single-argument T::Profile().
+
+ using Super = FoldingSetImpl<T>;
+ using Node = typename Super::Node;
+
+ Ctx Context;
+
+ /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
+ /// way to convert nodes into a unique specifier.
+ void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override {
+ T *TN = static_cast<T *>(N);
+ ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context);
+ }
+
+ bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
+ FoldingSetNodeID &TempID) const override {
+ T *TN = static_cast<T *>(N);
+ return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID,
+ Context);
+ }
+
+ unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override {
+ T *TN = static_cast<T *>(N);
+ return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID, Context);
+ }
+
+public:
+ explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6)
+ : Super(Log2InitSize), Context(Context) {}
+
+ Ctx getContext() const { return Context; }
+};
+
+//===----------------------------------------------------------------------===//
+/// FoldingSetVector - This template class combines a FoldingSet and a vector
+/// to provide the interface of FoldingSet but with deterministic iteration
+/// order based on the insertion order. T must be a subclass of FoldingSetNode
+/// and implement a Profile function.
+template <class T, class VectorT = SmallVector<T*, 8>>
+class FoldingSetVector {
+ FoldingSet<T> Set;
+ VectorT Vector;
+
+public:
+ explicit FoldingSetVector(unsigned Log2InitSize = 6) : Set(Log2InitSize) {}
+
+ using iterator = pointee_iterator<typename VectorT::iterator>;
+
+ iterator begin() { return Vector.begin(); }
+ iterator end() { return Vector.end(); }
+
+ using const_iterator = pointee_iterator<typename VectorT::const_iterator>;
+
+ const_iterator begin() const { return Vector.begin(); }
+ const_iterator end() const { return Vector.end(); }
+
+ /// clear - Remove all nodes from the folding set.
+ void clear() { Set.clear(); Vector.clear(); }
+
+ /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
+ /// return it. If not, return the insertion token that will make insertion
+ /// faster.
+ T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
+ return Set.FindNodeOrInsertPos(ID, InsertPos);
+ }
+
+ /// GetOrInsertNode - If there is an existing simple Node exactly
+ /// equal to the specified node, return it. Otherwise, insert 'N' and
+ /// return it instead.
+ T *GetOrInsertNode(T *N) {
+ T *Result = Set.GetOrInsertNode(N);
+ if (Result == N) Vector.push_back(N);
+ return Result;
+ }
+
+ /// InsertNode - Insert the specified node into the folding set, knowing that
+ /// it is not already in the folding set. InsertPos must be obtained from
+ /// FindNodeOrInsertPos.
+ void InsertNode(T *N, void *InsertPos) {
+ Set.InsertNode(N, InsertPos);
+ Vector.push_back(N);
+ }
+
+ /// InsertNode - Insert the specified node into the folding set, knowing that
+ /// it is not already in the folding set.
+ void InsertNode(T *N) {
+ Set.InsertNode(N);
+ Vector.push_back(N);
+ }
+
+ /// size - Returns the number of nodes in the folding set.
+ unsigned size() const { return Set.size(); }
+
+ /// empty - Returns true if there are no nodes in the folding set.
+ bool empty() const { return Set.empty(); }
+};
+
+//===----------------------------------------------------------------------===//
+/// FoldingSetIteratorImpl - This is the common iterator support shared by all
+/// folding sets, which knows how to walk the folding set hash table.
+class FoldingSetIteratorImpl {
+protected:
+ FoldingSetNode *NodePtr;
+
+ FoldingSetIteratorImpl(void **Bucket);
+
+ void advance();
+
+public:
+ bool operator==(const FoldingSetIteratorImpl &RHS) const {
+ return NodePtr == RHS.NodePtr;
+ }
+ bool operator!=(const FoldingSetIteratorImpl &RHS) const {
+ return NodePtr != RHS.NodePtr;
+ }
+};
+
+template <class T> class FoldingSetIterator : public FoldingSetIteratorImpl {
+public:
+ explicit FoldingSetIterator(void **Bucket) : FoldingSetIteratorImpl(Bucket) {}
+
+ T &operator*() const {
+ return *static_cast<T*>(NodePtr);
+ }
+
+ T *operator->() const {
+ return static_cast<T*>(NodePtr);
+ }
+
+ inline FoldingSetIterator &operator++() { // Preincrement
+ advance();
+ return *this;
+ }
+ FoldingSetIterator operator++(int) { // Postincrement
+ FoldingSetIterator tmp = *this; ++*this; return tmp;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+/// FoldingSetBucketIteratorImpl - This is the common bucket iterator support
+/// shared by all folding sets, which knows how to walk a particular bucket
+/// of a folding set hash table.
+class FoldingSetBucketIteratorImpl {
+protected:
+ void *Ptr;
+
+ explicit FoldingSetBucketIteratorImpl(void **Bucket);
+
+ FoldingSetBucketIteratorImpl(void **Bucket, bool) : Ptr(Bucket) {}
+
+ void advance() {
+ void *Probe = static_cast<FoldingSetNode*>(Ptr)->getNextInBucket();
+ uintptr_t x = reinterpret_cast<uintptr_t>(Probe) & ~0x1;
+ Ptr = reinterpret_cast<void*>(x);
+ }
+
+public:
+ bool operator==(const FoldingSetBucketIteratorImpl &RHS) const {
+ return Ptr == RHS.Ptr;
+ }
+ bool operator!=(const FoldingSetBucketIteratorImpl &RHS) const {
+ return Ptr != RHS.Ptr;
+ }
+};
+
+template <class T>
+class FoldingSetBucketIterator : public FoldingSetBucketIteratorImpl {
+public:
+ explicit FoldingSetBucketIterator(void **Bucket) :
+ FoldingSetBucketIteratorImpl(Bucket) {}
+
+ FoldingSetBucketIterator(void **Bucket, bool) :
+ FoldingSetBucketIteratorImpl(Bucket, true) {}
+
+ T &operator*() const { return *static_cast<T*>(Ptr); }
+ T *operator->() const { return static_cast<T*>(Ptr); }
+
+ inline FoldingSetBucketIterator &operator++() { // Preincrement
+ advance();
+ return *this;
+ }
+ FoldingSetBucketIterator operator++(int) { // Postincrement
+ FoldingSetBucketIterator tmp = *this; ++*this; return tmp;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+/// FoldingSetNodeWrapper - This template class is used to "wrap" arbitrary
+/// types in an enclosing object so that they can be inserted into FoldingSets.
+template <typename T>
+class FoldingSetNodeWrapper : public FoldingSetNode {
+ T data;
+
+public:
+ template <typename... Ts>
+ explicit FoldingSetNodeWrapper(Ts &&... Args)
+ : data(std::forward<Ts>(Args)...) {}
+
+ void Profile(FoldingSetNodeID &ID) { FoldingSetTrait<T>::Profile(data, ID); }
+
+ T &getValue() { return data; }
+ const T &getValue() const { return data; }
+
+ operator T&() { return data; }
+ operator const T&() const { return data; }
+};
+
+//===----------------------------------------------------------------------===//
+/// FastFoldingSetNode - This is a subclass of FoldingSetNode which stores
+/// a FoldingSetNodeID value rather than requiring the node to recompute it
+/// each time it is needed. This trades space for speed (which can be
+/// significant if the ID is long), and it also permits nodes to drop
+/// information that would otherwise only be required for recomputing an ID.
+class FastFoldingSetNode : public FoldingSetNode {
+ FoldingSetNodeID FastID;
+
+protected:
+ explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {}
+
+public:
+ void Profile(FoldingSetNodeID &ID) const { ID.AddNodeID(FastID); }
+};
+
+//===----------------------------------------------------------------------===//
+// Partial specializations of FoldingSetTrait.
+
+template<typename T> struct FoldingSetTrait<T*> {
+ static inline void Profile(T *X, FoldingSetNodeID &ID) {
+ ID.AddPointer(X);
+ }
+};
+template <typename T1, typename T2>
+struct FoldingSetTrait<std::pair<T1, T2>> {
+ static inline void Profile(const std::pair<T1, T2> &P,
+ FoldingSetNodeID &ID) {
+ ID.Add(P.first);
+ ID.Add(P.second);
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_FOLDINGSET_H
diff --git a/third_party/llvm-project/include/llvm/ADT/FunctionExtras.h b/third_party/llvm-project/include/llvm/ADT/FunctionExtras.h
new file mode 100644
index 000000000..121aa527a
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/FunctionExtras.h
@@ -0,0 +1,292 @@
+//===- FunctionExtras.h - Function type erasure utilities -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides a collection of function (or more generally, callable)
+/// type erasure utilities supplementing those provided by the standard library
+/// in `<function>`.
+///
+/// It provides `unique_function`, which works like `std::function` but supports
+/// move-only callable objects.
+///
+/// Future plans:
+/// - Add a `function` that provides const, volatile, and ref-qualified support,
+/// which doesn't work with `std::function`.
+/// - Provide support for specifying multiple signatures to type erase callable
+/// objects with an overload set, such as those produced by generic lambdas.
+/// - Expand to include a copyable utility that directly replaces std::function
+/// but brings the above improvements.
+///
+/// Note that LLVM's utilities are greatly simplified by not supporting
+/// allocators.
+///
+/// If the standard library ever begins to provide comparable facilities we can
+/// consider switching to those.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_FUNCTION_EXTRAS_H
+#define LLVM_ADT_FUNCTION_EXTRAS_H
+
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/type_traits.h"
+#include <memory>
+
+namespace llvm {
+
+template <typename FunctionT> class unique_function;
+
+template <typename ReturnT, typename... ParamTs>
+class unique_function<ReturnT(ParamTs...)> {
+ static constexpr size_t InlineStorageSize = sizeof(void *) * 3;
+
+ // MSVC has a bug and ICEs if we give it a particular dependent value
+ // expression as part of the `std::conditional` below. To work around this,
+ // we build that into a template struct's constexpr bool.
+ template <typename T> struct IsSizeLessThanThresholdT {
+ static constexpr bool value = sizeof(T) <= (2 * sizeof(void *));
+ };
+
+ // Provide a type function to map parameters that won't observe extra copies
+ // or moves and which are small enough to likely pass in register to values
+ // and all other types to l-value reference types. We use this to compute the
+ // types used in our erased call utility to minimize copies and moves unless
+ // doing so would force things unnecessarily into memory.
+ //
+ // The heuristic used is related to common ABI register passing conventions.
+ // It doesn't have to be exact though, and in one way it is more strict
+ // because we want to still be able to observe either moves *or* copies.
+ template <typename T>
+ using AdjustedParamT = typename std::conditional<
+ !std::is_reference<T>::value &&
+ llvm::is_trivially_copy_constructible<T>::value &&
+ llvm::is_trivially_move_constructible<T>::value &&
+ IsSizeLessThanThresholdT<T>::value,
+ T, T &>::type;
+
+ // The type of the erased function pointer we use as a callback to dispatch to
+ // the stored callable when it is trivial to move and destroy.
+ using CallPtrT = ReturnT (*)(void *CallableAddr,
+ AdjustedParamT<ParamTs>... Params);
+ using MovePtrT = void (*)(void *LHSCallableAddr, void *RHSCallableAddr);
+ using DestroyPtrT = void (*)(void *CallableAddr);
+
+ /// A struct to hold a single trivial callback with sufficient alignment for
+ /// our bitpacking.
+ struct alignas(8) TrivialCallback {
+ CallPtrT CallPtr;
+ };
+
+ /// A struct we use to aggregate three callbacks when we need full set of
+ /// operations.
+ struct alignas(8) NonTrivialCallbacks {
+ CallPtrT CallPtr;
+ MovePtrT MovePtr;
+ DestroyPtrT DestroyPtr;
+ };
+
+ // Create a pointer union between either a pointer to a static trivial call
+ // pointer in a struct or a pointer to a static struct of the call, move, and
+ // destroy pointers.
+ using CallbackPointerUnionT =
+ PointerUnion<TrivialCallback *, NonTrivialCallbacks *>;
+
+ // The main storage buffer. This will either have a pointer to out-of-line
+ // storage or an inline buffer storing the callable.
+ union StorageUnionT {
+ // For out-of-line storage we keep a pointer to the underlying storage and
+ // the size. This is enough to deallocate the memory.
+ struct OutOfLineStorageT {
+ void *StoragePtr;
+ size_t Size;
+ size_t Alignment;
+ } OutOfLineStorage;
+ static_assert(
+ sizeof(OutOfLineStorageT) <= InlineStorageSize,
+ "Should always use all of the out-of-line storage for inline storage!");
+
+ // For in-line storage, we just provide an aligned character buffer. We
+ // provide three pointers worth of storage here.
+ typename std::aligned_storage<InlineStorageSize, alignof(void *)>::type
+ InlineStorage;
+ } StorageUnion;
+
+ // A compressed pointer to either our dispatching callback or our table of
+ // dispatching callbacks and the flag for whether the callable itself is
+ // stored inline or not.
+ PointerIntPair<CallbackPointerUnionT, 1, bool> CallbackAndInlineFlag;
+
+ bool isInlineStorage() const { return CallbackAndInlineFlag.getInt(); }
+
+ bool isTrivialCallback() const {
+ return CallbackAndInlineFlag.getPointer().template is<TrivialCallback *>();
+ }
+
+ CallPtrT getTrivialCallback() const {
+ return CallbackAndInlineFlag.getPointer().template get<TrivialCallback *>()->CallPtr;
+ }
+
+ NonTrivialCallbacks *getNonTrivialCallbacks() const {
+ return CallbackAndInlineFlag.getPointer()
+ .template get<NonTrivialCallbacks *>();
+ }
+
+ void *getInlineStorage() { return &StorageUnion.InlineStorage; }
+
+ void *getOutOfLineStorage() {
+ return StorageUnion.OutOfLineStorage.StoragePtr;
+ }
+ size_t getOutOfLineStorageSize() const {
+ return StorageUnion.OutOfLineStorage.Size;
+ }
+ size_t getOutOfLineStorageAlignment() const {
+ return StorageUnion.OutOfLineStorage.Alignment;
+ }
+
+ void setOutOfLineStorage(void *Ptr, size_t Size, size_t Alignment) {
+ StorageUnion.OutOfLineStorage = {Ptr, Size, Alignment};
+ }
+
+ template <typename CallableT>
+ static ReturnT CallImpl(void *CallableAddr, AdjustedParamT<ParamTs>... Params) {
+ return (*reinterpret_cast<CallableT *>(CallableAddr))(
+ std::forward<ParamTs>(Params)...);
+ }
+
+ template <typename CallableT>
+ static void MoveImpl(void *LHSCallableAddr, void *RHSCallableAddr) noexcept {
+ new (LHSCallableAddr)
+ CallableT(std::move(*reinterpret_cast<CallableT *>(RHSCallableAddr)));
+ }
+
+ template <typename CallableT>
+ static void DestroyImpl(void *CallableAddr) noexcept {
+ reinterpret_cast<CallableT *>(CallableAddr)->~CallableT();
+ }
+
+public:
+ unique_function() = default;
+ unique_function(std::nullptr_t /*null_callable*/) {}
+
+ ~unique_function() {
+ if (!CallbackAndInlineFlag.getPointer())
+ return;
+
+ // Cache this value so we don't re-check it after type-erased operations.
+ bool IsInlineStorage = isInlineStorage();
+
+ if (!isTrivialCallback())
+ getNonTrivialCallbacks()->DestroyPtr(
+ IsInlineStorage ? getInlineStorage() : getOutOfLineStorage());
+
+ if (!IsInlineStorage)
+ deallocate_buffer(getOutOfLineStorage(), getOutOfLineStorageSize(),
+ getOutOfLineStorageAlignment());
+ }
+
+ unique_function(unique_function &&RHS) noexcept {
+ // Copy the callback and inline flag.
+ CallbackAndInlineFlag = RHS.CallbackAndInlineFlag;
+
+ // If the RHS is empty, just copying the above is sufficient.
+ if (!RHS)
+ return;
+
+ if (!isInlineStorage()) {
+ // The out-of-line case is easiest to move.
+ StorageUnion.OutOfLineStorage = RHS.StorageUnion.OutOfLineStorage;
+ } else if (isTrivialCallback()) {
+ // Move is trivial, just memcpy the bytes across.
+ memcpy(getInlineStorage(), RHS.getInlineStorage(), InlineStorageSize);
+ } else {
+ // Non-trivial move, so dispatch to a type-erased implementation.
+ getNonTrivialCallbacks()->MovePtr(getInlineStorage(),
+ RHS.getInlineStorage());
+ }
+
+ // Clear the old callback and inline flag to get back to as-if-null.
+ RHS.CallbackAndInlineFlag = {};
+
+#ifndef NDEBUG
+ // In debug builds, we also scribble across the rest of the storage.
+ memset(RHS.getInlineStorage(), 0xAD, InlineStorageSize);
+#endif
+ }
+
+ unique_function &operator=(unique_function &&RHS) noexcept {
+ if (this == &RHS)
+ return *this;
+
+ // Because we don't try to provide any exception safety guarantees we can
+ // implement move assignment very simply by first destroying the current
+ // object and then move-constructing over top of it.
+ this->~unique_function();
+ new (this) unique_function(std::move(RHS));
+ return *this;
+ }
+
+ template <typename CallableT> unique_function(CallableT Callable) {
+ bool IsInlineStorage = true;
+ void *CallableAddr = getInlineStorage();
+ if (sizeof(CallableT) > InlineStorageSize ||
+ alignof(CallableT) > alignof(decltype(StorageUnion.InlineStorage))) {
+ IsInlineStorage = false;
+ // Allocate out-of-line storage. FIXME: Use an explicit alignment
+ // parameter in C++17 mode.
+ auto Size = sizeof(CallableT);
+ auto Alignment = alignof(CallableT);
+ CallableAddr = allocate_buffer(Size, Alignment);
+ setOutOfLineStorage(CallableAddr, Size, Alignment);
+ }
+
+ // Now move into the storage.
+ new (CallableAddr) CallableT(std::move(Callable));
+
+ // See if we can create a trivial callback. We need the callable to be
+ // trivially moved and trivially destroyed so that we don't have to store
+ // type erased callbacks for those operations.
+ //
+ // FIXME: We should use constexpr if here and below to avoid instantiating
+ // the non-trivial static objects when unnecessary. While the linker should
+ // remove them, it is still wasteful.
+ if (llvm::is_trivially_move_constructible<CallableT>::value &&
+ std::is_trivially_destructible<CallableT>::value) {
+ // We need to create a nicely aligned object. We use a static variable
+ // for this because it is a trivial struct.
+ static TrivialCallback Callback = { &CallImpl<CallableT> };
+
+ CallbackAndInlineFlag = {&Callback, IsInlineStorage};
+ return;
+ }
+
+ // Otherwise, we need to point at an object that contains all the different
+ // type erased behaviors needed. Create a static instance of the struct type
+ // here and then use a pointer to that.
+ static NonTrivialCallbacks Callbacks = {
+ &CallImpl<CallableT>, &MoveImpl<CallableT>, &DestroyImpl<CallableT>};
+
+ CallbackAndInlineFlag = {&Callbacks, IsInlineStorage};
+ }
+
+ ReturnT operator()(ParamTs... Params) {
+ void *CallableAddr =
+ isInlineStorage() ? getInlineStorage() : getOutOfLineStorage();
+
+ return (isTrivialCallback()
+ ? getTrivialCallback()
+ : getNonTrivialCallbacks()->CallPtr)(CallableAddr, Params...);
+ }
+
+ explicit operator bool() const {
+ return (bool)CallbackAndInlineFlag.getPointer();
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_FUNCTION_H
diff --git a/third_party/llvm-project/include/llvm/ADT/Hashing.h b/third_party/llvm-project/include/llvm/ADT/Hashing.h
new file mode 100644
index 000000000..adcc5cf54
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/Hashing.h
@@ -0,0 +1,659 @@
+//===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the newly proposed standard C++ interfaces for hashing
+// arbitrary data and building hash functions for user-defined types. This
+// interface was originally proposed in N3333[1] and is currently under review
+// for inclusion in a future TR and/or standard.
+//
+// The primary interfaces provide are comprised of one type and three functions:
+//
+// -- 'hash_code' class is an opaque type representing the hash code for some
+// data. It is the intended product of hashing, and can be used to implement
+// hash tables, checksumming, and other common uses of hashes. It is not an
+// integer type (although it can be converted to one) because it is risky
+// to assume much about the internals of a hash_code. In particular, each
+// execution of the program has a high probability of producing a different
+// hash_code for a given input. Thus their values are not stable to save or
+// persist, and should only be used during the execution for the
+// construction of hashing datastructures.
+//
+// -- 'hash_value' is a function designed to be overloaded for each
+// user-defined type which wishes to be used within a hashing context. It
+// should be overloaded within the user-defined type's namespace and found
+// via ADL. Overloads for primitive types are provided by this library.
+//
+// -- 'hash_combine' and 'hash_combine_range' are functions designed to aid
+// programmers in easily and intuitively combining a set of data into
+// a single hash_code for their object. They should only logically be used
+// within the implementation of a 'hash_value' routine or similar context.
+//
+// Note that 'hash_combine_range' contains very special logic for hashing
+// a contiguous array of integers or pointers. This logic is *extremely* fast,
+// on a modern Intel "Gainestown" Xeon (Nehalem uarch) @2.2 GHz, these were
+// benchmarked at over 6.5 GiB/s for large keys, and <20 cycles/hash for keys
+// under 32-bytes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_HASHING_H
+#define LLVM_ADT_HASHING_H
+
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include "llvm/Support/type_traits.h"
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <string>
+#include <utility>
+
+namespace llvm {
+
+/// An opaque object representing a hash code.
+///
+/// This object represents the result of hashing some entity. It is intended to
+/// be used to implement hashtables or other hashing-based data structures.
+/// While it wraps and exposes a numeric value, this value should not be
+/// trusted to be stable or predictable across processes or executions.
+///
+/// In order to obtain the hash_code for an object 'x':
+/// \code
+/// using llvm::hash_value;
+/// llvm::hash_code code = hash_value(x);
+/// \endcode
+class hash_code {
+ size_t value;
+
+public:
+ /// Default construct a hash_code.
+ /// Note that this leaves the value uninitialized.
+ hash_code() = default;
+
+ /// Form a hash code directly from a numerical value.
+ hash_code(size_t value) : value(value) {}
+
+ /// Convert the hash code to its numerical value for use.
+ /*explicit*/ operator size_t() const { return value; }
+
+ friend bool operator==(const hash_code &lhs, const hash_code &rhs) {
+ return lhs.value == rhs.value;
+ }
+ friend bool operator!=(const hash_code &lhs, const hash_code &rhs) {
+ return lhs.value != rhs.value;
+ }
+
+ /// Allow a hash_code to be directly run through hash_value.
+ friend size_t hash_value(const hash_code &code) { return code.value; }
+};
+
+/// Compute a hash_code for any integer value.
+///
+/// Note that this function is intended to compute the same hash_code for
+/// a particular value without regard to the pre-promotion type. This is in
+/// contrast to hash_combine which may produce different hash_codes for
+/// differing argument types even if they would implicit promote to a common
+/// type without changing the value.
+template <typename T>
+typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type
+hash_value(T value);
+
+/// Compute a hash_code for a pointer's address.
+///
+/// N.B.: This hashes the *address*. Not the value and not the type.
+template <typename T> hash_code hash_value(const T *ptr);
+
+/// Compute a hash_code for a pair of objects.
+template <typename T, typename U>
+hash_code hash_value(const std::pair<T, U> &arg);
+
+/// Compute a hash_code for a standard string.
+template <typename T>
+hash_code hash_value(const std::basic_string<T> &arg);
+
+
+/// Override the execution seed with a fixed value.
+///
+/// This hashing library uses a per-execution seed designed to change on each
+/// run with high probability in order to ensure that the hash codes are not
+/// attackable and to ensure that output which is intended to be stable does
+/// not rely on the particulars of the hash codes produced.
+///
+/// That said, there are use cases where it is important to be able to
+/// reproduce *exactly* a specific behavior. To that end, we provide a function
+/// which will forcibly set the seed to a fixed value. This must be done at the
+/// start of the program, before any hashes are computed. Also, it cannot be
+/// undone. This makes it thread-hostile and very hard to use outside of
+/// immediately on start of a simple program designed for reproducible
+/// behavior.
+void set_fixed_execution_hash_seed(uint64_t fixed_value);
+
+
+// All of the implementation details of actually computing the various hash
+// code values are held within this namespace. These routines are included in
+// the header file mainly to allow inlining and constant propagation.
+namespace hashing {
+namespace detail {
+
+inline uint64_t fetch64(const char *p) {
+ uint64_t result;
+ memcpy(&result, p, sizeof(result));
+ if (sys::IsBigEndianHost)
+ sys::swapByteOrder(result);
+ return result;
+}
+
+inline uint32_t fetch32(const char *p) {
+ uint32_t result;
+ memcpy(&result, p, sizeof(result));
+ if (sys::IsBigEndianHost)
+ sys::swapByteOrder(result);
+ return result;
+}
+
+/// Some primes between 2^63 and 2^64 for various uses.
+static const uint64_t k0 = 0xc3a5c85c97cb3127ULL;
+static const uint64_t k1 = 0xb492b66fbe98f273ULL;
+static const uint64_t k2 = 0x9ae16a3b2f90404fULL;
+static const uint64_t k3 = 0xc949d7c7509e6557ULL;
+
+/// Bitwise right rotate.
+/// Normally this will compile to a single instruction, especially if the
+/// shift is a manifest constant.
+inline uint64_t rotate(uint64_t val, size_t shift) {
+ // Avoid shifting by 64: doing so yields an undefined result.
+ return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
+}
+
+inline uint64_t shift_mix(uint64_t val) {
+ return val ^ (val >> 47);
+}
+
+inline uint64_t hash_16_bytes(uint64_t low, uint64_t high) {
+ // Murmur-inspired hashing.
+ const uint64_t kMul = 0x9ddfea08eb382d69ULL;
+ uint64_t a = (low ^ high) * kMul;
+ a ^= (a >> 47);
+ uint64_t b = (high ^ a) * kMul;
+ b ^= (b >> 47);
+ b *= kMul;
+ return b;
+}
+
+inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) {
+ uint8_t a = s[0];
+ uint8_t b = s[len >> 1];
+ uint8_t c = s[len - 1];
+ uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);
+ uint32_t z = static_cast<uint32_t>(len) + (static_cast<uint32_t>(c) << 2);
+ return shift_mix(y * k2 ^ z * k3 ^ seed) * k2;
+}
+
+inline uint64_t hash_4to8_bytes(const char *s, size_t len, uint64_t seed) {
+ uint64_t a = fetch32(s);
+ return hash_16_bytes(len + (a << 3), seed ^ fetch32(s + len - 4));
+}
+
+inline uint64_t hash_9to16_bytes(const char *s, size_t len, uint64_t seed) {
+ uint64_t a = fetch64(s);
+ uint64_t b = fetch64(s + len - 8);
+ return hash_16_bytes(seed ^ a, rotate(b + len, len)) ^ b;
+}
+
+inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) {
+ uint64_t a = fetch64(s) * k1;
+ uint64_t b = fetch64(s + 8);
+ uint64_t c = fetch64(s + len - 8) * k2;
+ uint64_t d = fetch64(s + len - 16) * k0;
+ return hash_16_bytes(rotate(a - b, 43) + rotate(c ^ seed, 30) + d,
+ a + rotate(b ^ k3, 20) - c + len + seed);
+}
+
+inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) {
+ uint64_t z = fetch64(s + 24);
+ uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0;
+ uint64_t b = rotate(a + z, 52);
+ uint64_t c = rotate(a, 37);
+ a += fetch64(s + 8);
+ c += rotate(a, 7);
+ a += fetch64(s + 16);
+ uint64_t vf = a + z;
+ uint64_t vs = b + rotate(a, 31) + c;
+ a = fetch64(s + 16) + fetch64(s + len - 32);
+ z = fetch64(s + len - 8);
+ b = rotate(a + z, 52);
+ c = rotate(a, 37);
+ a += fetch64(s + len - 24);
+ c += rotate(a, 7);
+ a += fetch64(s + len - 16);
+ uint64_t wf = a + z;
+ uint64_t ws = b + rotate(a, 31) + c;
+ uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0);
+ return shift_mix((seed ^ (r * k0)) + vs) * k2;
+}
+
+inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) {
+ if (length >= 4 && length <= 8)
+ return hash_4to8_bytes(s, length, seed);
+ if (length > 8 && length <= 16)
+ return hash_9to16_bytes(s, length, seed);
+ if (length > 16 && length <= 32)
+ return hash_17to32_bytes(s, length, seed);
+ if (length > 32)
+ return hash_33to64_bytes(s, length, seed);
+ if (length != 0)
+ return hash_1to3_bytes(s, length, seed);
+
+ return k2 ^ seed;
+}
+
+/// The intermediate state used during hashing.
+/// Currently, the algorithm for computing hash codes is based on CityHash and
+/// keeps 56 bytes of arbitrary state.
+struct hash_state {
+ uint64_t h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0;
+
+ /// Create a new hash_state structure and initialize it based on the
+ /// seed and the first 64-byte chunk.
+ /// This effectively performs the initial mix.
+ static hash_state create(const char *s, uint64_t seed) {
+ hash_state state = {
+ 0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49),
+ seed * k1, shift_mix(seed), 0 };
+ state.h6 = hash_16_bytes(state.h4, state.h5);
+ state.mix(s);
+ return state;
+ }
+
+ /// Mix 32-bytes from the input sequence into the 16-bytes of 'a'
+ /// and 'b', including whatever is already in 'a' and 'b'.
+ static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) {
+ a += fetch64(s);
+ uint64_t c = fetch64(s + 24);
+ b = rotate(b + a + c, 21);
+ uint64_t d = a;
+ a += fetch64(s + 8) + fetch64(s + 16);
+ b += rotate(a, 44) + d;
+ a += c;
+ }
+
+ /// Mix in a 64-byte buffer of data.
+ /// We mix all 64 bytes even when the chunk length is smaller, but we
+ /// record the actual length.
+ void mix(const char *s) {
+ h0 = rotate(h0 + h1 + h3 + fetch64(s + 8), 37) * k1;
+ h1 = rotate(h1 + h4 + fetch64(s + 48), 42) * k1;
+ h0 ^= h6;
+ h1 += h3 + fetch64(s + 40);
+ h2 = rotate(h2 + h5, 33) * k1;
+ h3 = h4 * k1;
+ h4 = h0 + h5;
+ mix_32_bytes(s, h3, h4);
+ h5 = h2 + h6;
+ h6 = h1 + fetch64(s + 16);
+ mix_32_bytes(s + 32, h5, h6);
+ std::swap(h2, h0);
+ }
+
+ /// Compute the final 64-bit hash code value based on the current
+ /// state and the length of bytes hashed.
+ uint64_t finalize(size_t length) {
+ return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2,
+ hash_16_bytes(h4, h6) + shift_mix(length) * k1 + h0);
+ }
+};
+
+
+/// A global, fixed seed-override variable.
+///
+/// This variable can be set using the \see llvm::set_fixed_execution_seed
+/// function. See that function for details. Do not, under any circumstances,
+/// set or read this variable.
+extern uint64_t fixed_seed_override;
+
+inline uint64_t get_execution_seed() {
+ // FIXME: This needs to be a per-execution seed. This is just a placeholder
+ // implementation. Switching to a per-execution seed is likely to flush out
+ // instability bugs and so will happen as its own commit.
+ //
+ // However, if there is a fixed seed override set the first time this is
+ // called, return that instead of the per-execution seed.
+ const uint64_t seed_prime = 0xff51afd7ed558ccdULL;
+ static uint64_t seed = fixed_seed_override ? fixed_seed_override : seed_prime;
+ return seed;
+}
+
+
+/// Trait to indicate whether a type's bits can be hashed directly.
+///
+/// A type trait which is true if we want to combine values for hashing by
+/// reading the underlying data. It is false if values of this type must
+/// first be passed to hash_value, and the resulting hash_codes combined.
+//
+// FIXME: We want to replace is_integral_or_enum and is_pointer here with
+// a predicate which asserts that comparing the underlying storage of two
+// values of the type for equality is equivalent to comparing the two values
+// for equality. For all the platforms we care about, this holds for integers
+// and pointers, but there are platforms where it doesn't and we would like to
+// support user-defined types which happen to satisfy this property.
+template <typename T> struct is_hashable_data
+ : std::integral_constant<bool, ((is_integral_or_enum<T>::value ||
+ std::is_pointer<T>::value) &&
+ 64 % sizeof(T) == 0)> {};
+
+// Special case std::pair to detect when both types are viable and when there
+// is no alignment-derived padding in the pair. This is a bit of a lie because
+// std::pair isn't truly POD, but it's close enough in all reasonable
+// implementations for our use case of hashing the underlying data.
+template <typename T, typename U> struct is_hashable_data<std::pair<T, U> >
+ : std::integral_constant<bool, (is_hashable_data<T>::value &&
+ is_hashable_data<U>::value &&
+ (sizeof(T) + sizeof(U)) ==
+ sizeof(std::pair<T, U>))> {};
+
+/// Helper to get the hashable data representation for a type.
+/// This variant is enabled when the type itself can be used.
+template <typename T>
+typename std::enable_if<is_hashable_data<T>::value, T>::type
+get_hashable_data(const T &value) {
+ return value;
+}
+/// Helper to get the hashable data representation for a type.
+/// This variant is enabled when we must first call hash_value and use the
+/// result as our data.
+template <typename T>
+typename std::enable_if<!is_hashable_data<T>::value, size_t>::type
+get_hashable_data(const T &value) {
+ using ::llvm::hash_value;
+ return hash_value(value);
+}
+
+/// Helper to store data from a value into a buffer and advance the
+/// pointer into that buffer.
+///
+/// This routine first checks whether there is enough space in the provided
+/// buffer, and if not immediately returns false. If there is space, it
+/// copies the underlying bytes of value into the buffer, advances the
+/// buffer_ptr past the copied bytes, and returns true.
+template <typename T>
+bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value,
+ size_t offset = 0) {
+ size_t store_size = sizeof(value) - offset;
+ if (buffer_ptr + store_size > buffer_end)
+ return false;
+ const char *value_data = reinterpret_cast<const char *>(&value);
+ memcpy(buffer_ptr, value_data + offset, store_size);
+ buffer_ptr += store_size;
+ return true;
+}
+
+/// Implement the combining of integral values into a hash_code.
+///
+/// This overload is selected when the value type of the iterator is
+/// integral. Rather than computing a hash_code for each object and then
+/// combining them, this (as an optimization) directly combines the integers.
+template <typename InputIteratorT>
+hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
+ const uint64_t seed = get_execution_seed();
+ char buffer[64], *buffer_ptr = buffer;
+ char *const buffer_end = std::end(buffer);
+ while (first != last && store_and_advance(buffer_ptr, buffer_end,
+ get_hashable_data(*first)))
+ ++first;
+ if (first == last)
+ return hash_short(buffer, buffer_ptr - buffer, seed);
+ assert(buffer_ptr == buffer_end);
+
+ hash_state state = state.create(buffer, seed);
+ size_t length = 64;
+ while (first != last) {
+ // Fill up the buffer. We don't clear it, which re-mixes the last round
+ // when only a partial 64-byte chunk is left.
+ buffer_ptr = buffer;
+ while (first != last && store_and_advance(buffer_ptr, buffer_end,
+ get_hashable_data(*first)))
+ ++first;
+
+ // Rotate the buffer if we did a partial fill in order to simulate doing
+ // a mix of the last 64-bytes. That is how the algorithm works when we
+ // have a contiguous byte sequence, and we want to emulate that here.
+ std::rotate(buffer, buffer_ptr, buffer_end);
+
+ // Mix this chunk into the current state.
+ state.mix(buffer);
+ length += buffer_ptr - buffer;
+ };
+
+ return state.finalize(length);
+}
+
+/// Implement the combining of integral values into a hash_code.
+///
+/// This overload is selected when the value type of the iterator is integral
+/// and when the input iterator is actually a pointer. Rather than computing
+/// a hash_code for each object and then combining them, this (as an
+/// optimization) directly combines the integers. Also, because the integers
+/// are stored in contiguous memory, this routine avoids copying each value
+/// and directly reads from the underlying memory.
+template <typename ValueT>
+typename std::enable_if<is_hashable_data<ValueT>::value, hash_code>::type
+hash_combine_range_impl(ValueT *first, ValueT *last) {
+ const uint64_t seed = get_execution_seed();
+ const char *s_begin = reinterpret_cast<const char *>(first);
+ const char *s_end = reinterpret_cast<const char *>(last);
+ const size_t length = std::distance(s_begin, s_end);
+ if (length <= 64)
+ return hash_short(s_begin, length, seed);
+
+ const char *s_aligned_end = s_begin + (length & ~63);
+ hash_state state = state.create(s_begin, seed);
+ s_begin += 64;
+ while (s_begin != s_aligned_end) {
+ state.mix(s_begin);
+ s_begin += 64;
+ }
+ if (length & 63)
+ state.mix(s_end - 64);
+
+ return state.finalize(length);
+}
+
+} // namespace detail
+} // namespace hashing
+
+
+/// Compute a hash_code for a sequence of values.
+///
+/// This hashes a sequence of values. It produces the same hash_code as
+/// 'hash_combine(a, b, c, ...)', but can run over arbitrary sized sequences
+/// and is significantly faster given pointers and types which can be hashed as
+/// a sequence of bytes.
+template <typename InputIteratorT>
+hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) {
+ return ::llvm::hashing::detail::hash_combine_range_impl(first, last);
+}
+
+
+// Implementation details for hash_combine.
+namespace hashing {
+namespace detail {
+
+/// Helper class to manage the recursive combining of hash_combine
+/// arguments.
+///
+/// This class exists to manage the state and various calls involved in the
+/// recursive combining of arguments used in hash_combine. It is particularly
+/// useful at minimizing the code in the recursive calls to ease the pain
+/// caused by a lack of variadic functions.
+struct hash_combine_recursive_helper {
+ char buffer[64] = {};
+ hash_state state;
+ const uint64_t seed;
+
+public:
+ /// Construct a recursive hash combining helper.
+ ///
+ /// This sets up the state for a recursive hash combine, including getting
+ /// the seed and buffer setup.
+ hash_combine_recursive_helper()
+ : seed(get_execution_seed()) {}
+
+ /// Combine one chunk of data into the current in-flight hash.
+ ///
+ /// This merges one chunk of data into the hash. First it tries to buffer
+ /// the data. If the buffer is full, it hashes the buffer into its
+ /// hash_state, empties it, and then merges the new chunk in. This also
+ /// handles cases where the data straddles the end of the buffer.
+ template <typename T>
+ char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) {
+ if (!store_and_advance(buffer_ptr, buffer_end, data)) {
+ // Check for skew which prevents the buffer from being packed, and do
+ // a partial store into the buffer to fill it. This is only a concern
+ // with the variadic combine because that formation can have varying
+ // argument types.
+ size_t partial_store_size = buffer_end - buffer_ptr;
+ memcpy(buffer_ptr, &data, partial_store_size);
+
+ // If the store fails, our buffer is full and ready to hash. We have to
+ // either initialize the hash state (on the first full buffer) or mix
+ // this buffer into the existing hash state. Length tracks the *hashed*
+ // length, not the buffered length.
+ if (length == 0) {
+ state = state.create(buffer, seed);
+ length = 64;
+ } else {
+ // Mix this chunk into the current state and bump length up by 64.
+ state.mix(buffer);
+ length += 64;
+ }
+ // Reset the buffer_ptr to the head of the buffer for the next chunk of
+ // data.
+ buffer_ptr = buffer;
+
+ // Try again to store into the buffer -- this cannot fail as we only
+ // store types smaller than the buffer.
+ if (!store_and_advance(buffer_ptr, buffer_end, data,
+ partial_store_size))
+ llvm_unreachable("buffer smaller than stored type");
+ }
+ return buffer_ptr;
+ }
+
+ /// Recursive, variadic combining method.
+ ///
+ /// This function recurses through each argument, combining that argument
+ /// into a single hash.
+ template <typename T, typename ...Ts>
+ hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
+ const T &arg, const Ts &...args) {
+ buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg));
+
+ // Recurse to the next argument.
+ return combine(length, buffer_ptr, buffer_end, args...);
+ }
+
+ /// Base case for recursive, variadic combining.
+ ///
+ /// The base case when combining arguments recursively is reached when all
+ /// arguments have been handled. It flushes the remaining buffer and
+ /// constructs a hash_code.
+ hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) {
+ // Check whether the entire set of values fit in the buffer. If so, we'll
+ // use the optimized short hashing routine and skip state entirely.
+ if (length == 0)
+ return hash_short(buffer, buffer_ptr - buffer, seed);
+
+ // Mix the final buffer, rotating it if we did a partial fill in order to
+ // simulate doing a mix of the last 64-bytes. That is how the algorithm
+ // works when we have a contiguous byte sequence, and we want to emulate
+ // that here.
+ std::rotate(buffer, buffer_ptr, buffer_end);
+
+ // Mix this chunk into the current state.
+ state.mix(buffer);
+ length += buffer_ptr - buffer;
+
+ return state.finalize(length);
+ }
+};
+
+} // namespace detail
+} // namespace hashing
+
+/// Combine values into a single hash_code.
+///
+/// This routine accepts a varying number of arguments of any type. It will
+/// attempt to combine them into a single hash_code. For user-defined types it
+/// attempts to call a \see hash_value overload (via ADL) for the type. For
+/// integer and pointer types it directly combines their data into the
+/// resulting hash_code.
+///
+/// The result is suitable for returning from a user's hash_value
+/// *implementation* for their user-defined type. Consumers of a type should
+/// *not* call this routine, they should instead call 'hash_value'.
+template <typename ...Ts> hash_code hash_combine(const Ts &...args) {
+ // Recursively hash each argument using a helper class.
+ ::llvm::hashing::detail::hash_combine_recursive_helper helper;
+ return helper.combine(0, helper.buffer, helper.buffer + 64, args...);
+}
+
+// Implementation details for implementations of hash_value overloads provided
+// here.
+namespace hashing {
+namespace detail {
+
+/// Helper to hash the value of a single integer.
+///
+/// Overloads for smaller integer types are not provided to ensure consistent
+/// behavior in the presence of integral promotions. Essentially,
+/// "hash_value('4')" and "hash_value('0' + 4)" should be the same.
+inline hash_code hash_integer_value(uint64_t value) {
+ // Similar to hash_4to8_bytes but using a seed instead of length.
+ const uint64_t seed = get_execution_seed();
+ const char *s = reinterpret_cast<const char *>(&value);
+ const uint64_t a = fetch32(s);
+ return hash_16_bytes(seed + (a << 3), fetch32(s + 4));
+}
+
+} // namespace detail
+} // namespace hashing
+
+// Declared and documented above, but defined here so that any of the hashing
+// infrastructure is available.
+template <typename T>
+typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type
+hash_value(T value) {
+ return ::llvm::hashing::detail::hash_integer_value(
+ static_cast<uint64_t>(value));
+}
+
+// Declared and documented above, but defined here so that any of the hashing
+// infrastructure is available.
+template <typename T> hash_code hash_value(const T *ptr) {
+ return ::llvm::hashing::detail::hash_integer_value(
+ reinterpret_cast<uintptr_t>(ptr));
+}
+
+// Declared and documented above, but defined here so that any of the hashing
+// infrastructure is available.
+template <typename T, typename U>
+hash_code hash_value(const std::pair<T, U> &arg) {
+ return hash_combine(arg.first, arg.second);
+}
+
+// Declared and documented above, but defined here so that any of the hashing
+// infrastructure is available.
+template <typename T>
+hash_code hash_value(const std::basic_string<T> &arg) {
+ return hash_combine_range(arg.begin(), arg.end());
+}
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/ADT/MapVector.h b/third_party/llvm-project/include/llvm/ADT/MapVector.h
new file mode 100644
index 000000000..1de1124f4
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/MapVector.h
@@ -0,0 +1,239 @@
+//===- llvm/ADT/MapVector.h - Map w/ deterministic value order --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a map that provides insertion order iteration. The
+// interface is purposefully minimal. The key is assumed to be cheap to copy
+// and 2 copies are kept, one for indexing in a DenseMap, one for iteration in
+// a std::vector.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_MAPVECTOR_H
+#define LLVM_ADT_MAPVECTOR_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+/// This class implements a map that also provides access to all stored values
+/// in a deterministic order. The values are kept in a std::vector and the
+/// mapping is done with DenseMap from Keys to indexes in that vector.
+template<typename KeyT, typename ValueT,
+ typename MapType = DenseMap<KeyT, unsigned>,
+ typename VectorType = std::vector<std::pair<KeyT, ValueT>>>
+class MapVector {
+ MapType Map;
+ VectorType Vector;
+
+ static_assert(
+ std::is_integral<typename MapType::mapped_type>::value,
+ "The mapped_type of the specified Map must be an integral type");
+
+public:
+ using value_type = typename VectorType::value_type;
+ using size_type = typename VectorType::size_type;
+
+ using iterator = typename VectorType::iterator;
+ using const_iterator = typename VectorType::const_iterator;
+ using reverse_iterator = typename VectorType::reverse_iterator;
+ using const_reverse_iterator = typename VectorType::const_reverse_iterator;
+
+ /// Clear the MapVector and return the underlying vector.
+ VectorType takeVector() {
+ Map.clear();
+ return std::move(Vector);
+ }
+
+ size_type size() const { return Vector.size(); }
+
+ /// Grow the MapVector so that it can contain at least \p NumEntries items
+ /// before resizing again.
+ void reserve(size_type NumEntries) {
+ Map.reserve(NumEntries);
+ Vector.reserve(NumEntries);
+ }
+
+ iterator begin() { return Vector.begin(); }
+ const_iterator begin() const { return Vector.begin(); }
+ iterator end() { return Vector.end(); }
+ const_iterator end() const { return Vector.end(); }
+
+ reverse_iterator rbegin() { return Vector.rbegin(); }
+ const_reverse_iterator rbegin() const { return Vector.rbegin(); }
+ reverse_iterator rend() { return Vector.rend(); }
+ const_reverse_iterator rend() const { return Vector.rend(); }
+
+ bool empty() const {
+ return Vector.empty();
+ }
+
+ std::pair<KeyT, ValueT> &front() { return Vector.front(); }
+ const std::pair<KeyT, ValueT> &front() const { return Vector.front(); }
+ std::pair<KeyT, ValueT> &back() { return Vector.back(); }
+ const std::pair<KeyT, ValueT> &back() const { return Vector.back(); }
+
+ void clear() {
+ Map.clear();
+ Vector.clear();
+ }
+
+ void swap(MapVector &RHS) {
+ std::swap(Map, RHS.Map);
+ std::swap(Vector, RHS.Vector);
+ }
+
+ ValueT &operator[](const KeyT &Key) {
+ std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(Key, 0);
+ std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
+ auto &I = Result.first->second;
+ if (Result.second) {
+ Vector.push_back(std::make_pair(Key, ValueT()));
+ I = Vector.size() - 1;
+ }
+ return Vector[I].second;
+ }
+
+ // Returns a copy of the value. Only allowed if ValueT is copyable.
+ ValueT lookup(const KeyT &Key) const {
+ static_assert(std::is_copy_constructible<ValueT>::value,
+ "Cannot call lookup() if ValueT is not copyable.");
+ typename MapType::const_iterator Pos = Map.find(Key);
+ return Pos == Map.end()? ValueT() : Vector[Pos->second].second;
+ }
+
+ std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
+ std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0);
+ std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
+ auto &I = Result.first->second;
+ if (Result.second) {
+ Vector.push_back(std::make_pair(KV.first, KV.second));
+ I = Vector.size() - 1;
+ return std::make_pair(std::prev(end()), true);
+ }
+ return std::make_pair(begin() + I, false);
+ }
+
+ std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
+ // Copy KV.first into the map, then move it into the vector.
+ std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0);
+ std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
+ auto &I = Result.first->second;
+ if (Result.second) {
+ Vector.push_back(std::move(KV));
+ I = Vector.size() - 1;
+ return std::make_pair(std::prev(end()), true);
+ }
+ return std::make_pair(begin() + I, false);
+ }
+
+ size_type count(const KeyT &Key) const {
+ typename MapType::const_iterator Pos = Map.find(Key);
+ return Pos == Map.end()? 0 : 1;
+ }
+
+ iterator find(const KeyT &Key) {
+ typename MapType::const_iterator Pos = Map.find(Key);
+ return Pos == Map.end()? Vector.end() :
+ (Vector.begin() + Pos->second);
+ }
+
+ const_iterator find(const KeyT &Key) const {
+ typename MapType::const_iterator Pos = Map.find(Key);
+ return Pos == Map.end()? Vector.end() :
+ (Vector.begin() + Pos->second);
+ }
+
+ /// Remove the last element from the vector.
+ void pop_back() {
+ typename MapType::iterator Pos = Map.find(Vector.back().first);
+ Map.erase(Pos);
+ Vector.pop_back();
+ }
+
+ /// Remove the element given by Iterator.
+ ///
+ /// Returns an iterator to the element following the one which was removed,
+ /// which may be end().
+ ///
+ /// \note This is a deceivingly expensive operation (linear time). It's
+ /// usually better to use \a remove_if() if possible.
+ typename VectorType::iterator erase(typename VectorType::iterator Iterator) {
+ Map.erase(Iterator->first);
+ auto Next = Vector.erase(Iterator);
+ if (Next == Vector.end())
+ return Next;
+
+ // Update indices in the map.
+ size_t Index = Next - Vector.begin();
+ for (auto &I : Map) {
+ assert(I.second != Index && "Index was already erased!");
+ if (I.second > Index)
+ --I.second;
+ }
+ return Next;
+ }
+
+ /// Remove all elements with the key value Key.
+ ///
+ /// Returns the number of elements removed.
+ size_type erase(const KeyT &Key) {
+ auto Iterator = find(Key);
+ if (Iterator == end())
+ return 0;
+ erase(Iterator);
+ return 1;
+ }
+
+ /// Remove the elements that match the predicate.
+ ///
+ /// Erase all elements that match \c Pred in a single pass. Takes linear
+ /// time.
+ template <class Predicate> void remove_if(Predicate Pred);
+};
+
+template <typename KeyT, typename ValueT, typename MapType, typename VectorType>
+template <class Function>
+void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) {
+ auto O = Vector.begin();
+ for (auto I = O, E = Vector.end(); I != E; ++I) {
+ if (Pred(*I)) {
+ // Erase from the map.
+ Map.erase(I->first);
+ continue;
+ }
+
+ if (I != O) {
+ // Move the value and update the index in the map.
+ *O = std::move(*I);
+ Map[O->first] = O - Vector.begin();
+ }
+ ++O;
+ }
+ // Erase trailing entries in the vector.
+ Vector.erase(O, Vector.end());
+}
+
+/// A MapVector that performs no allocations if smaller than a certain
+/// size.
+template <typename KeyT, typename ValueT, unsigned N>
+struct SmallMapVector
+ : MapVector<KeyT, ValueT, SmallDenseMap<KeyT, unsigned, N>,
+ SmallVector<std::pair<KeyT, ValueT>, N>> {
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_MAPVECTOR_H
diff --git a/third_party/llvm-project/include/llvm/ADT/None.h b/third_party/llvm-project/include/llvm/ADT/None.h
new file mode 100644
index 000000000..004ca0ac5
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/None.h
@@ -0,0 +1,26 @@
+//===-- None.h - Simple null value for implicit construction ------*- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides None, an enumerator for use in implicit constructors
+// of various (usually templated) types to make such construction more
+// terse.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_NONE_H
+#define LLVM_ADT_NONE_H
+
+namespace llvm {
+/// A simple null object to allow implicit construction of Optional<T>
+/// and similar types without having to spell out the specialization's name.
+// (constant value 1 in an attempt to workaround MSVC build issue... )
+enum class NoneType { None = 1 };
+const NoneType None = NoneType::None;
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/ADT/Optional.h b/third_party/llvm-project/include/llvm/ADT/Optional.h
new file mode 100644
index 000000000..b45a74002
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/Optional.h
@@ -0,0 +1,429 @@
+//===- Optional.h - Simple variant for passing optional values --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Optional, a template class modeled in the spirit of
+// OCaml's 'opt' variant. The idea is to strongly type whether or not
+// a value can be optional.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_OPTIONAL_H
+#define LLVM_ADT_OPTIONAL_H
+
+#include "llvm/ADT/None.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <memory>
+#include <new>
+#include <utility>
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace optional_detail {
+
+struct in_place_t {};
+
+/// Storage for any type.
+template <typename T, bool = is_trivially_copyable<T>::value>
+class OptionalStorage {
+ union {
+ char empty;
+ T value;
+ };
+ bool hasVal;
+
+public:
+ ~OptionalStorage() { reset(); }
+
+ OptionalStorage() noexcept : empty(), hasVal(false) {}
+
+ OptionalStorage(OptionalStorage const &other) : OptionalStorage() {
+ if (other.hasValue()) {
+ emplace(other.value);
+ }
+ }
+ OptionalStorage(OptionalStorage &&other) : OptionalStorage() {
+ if (other.hasValue()) {
+ emplace(std::move(other.value));
+ }
+ }
+
+ template <class... Args>
+ explicit OptionalStorage(in_place_t, Args &&... args)
+ : value(std::forward<Args>(args)...), hasVal(true) {}
+
+ void reset() noexcept {
+ if (hasVal) {
+ value.~T();
+ hasVal = false;
+ }
+ }
+
+ bool hasValue() const noexcept { return hasVal; }
+
+ T &getValue() LLVM_LVALUE_FUNCTION noexcept {
+ assert(hasVal);
+ return value;
+ }
+ T const &getValue() const LLVM_LVALUE_FUNCTION noexcept {
+ assert(hasVal);
+ return value;
+ }
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+ T &&getValue() && noexcept {
+ assert(hasVal);
+ return std::move(value);
+ }
+#endif
+
+ template <class... Args> void emplace(Args &&... args) {
+ reset();
+ ::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...);
+ hasVal = true;
+ }
+
+ OptionalStorage &operator=(T const &y) {
+ if (hasValue()) {
+ value = y;
+ } else {
+ ::new ((void *)std::addressof(value)) T(y);
+ hasVal = true;
+ }
+ return *this;
+ }
+ OptionalStorage &operator=(T &&y) {
+ if (hasValue()) {
+ value = std::move(y);
+ } else {
+ ::new ((void *)std::addressof(value)) T(std::move(y));
+ hasVal = true;
+ }
+ return *this;
+ }
+
+ OptionalStorage &operator=(OptionalStorage const &other) {
+ if (other.hasValue()) {
+ if (hasValue()) {
+ value = other.value;
+ } else {
+ ::new ((void *)std::addressof(value)) T(other.value);
+ hasVal = true;
+ }
+ } else {
+ reset();
+ }
+ return *this;
+ }
+
+ OptionalStorage &operator=(OptionalStorage &&other) {
+ if (other.hasValue()) {
+ if (hasValue()) {
+ value = std::move(other.value);
+ } else {
+ ::new ((void *)std::addressof(value)) T(std::move(other.value));
+ hasVal = true;
+ }
+ } else {
+ reset();
+ }
+ return *this;
+ }
+};
+
+template <typename T> class OptionalStorage<T, true> {
+ union {
+ char empty;
+ T value;
+ };
+ bool hasVal = false;
+
+public:
+ ~OptionalStorage() = default;
+
+ OptionalStorage() noexcept : empty{} {}
+
+ OptionalStorage(OptionalStorage const &other) = default;
+ OptionalStorage(OptionalStorage &&other) = default;
+
+ OptionalStorage &operator=(OptionalStorage const &other) = default;
+ OptionalStorage &operator=(OptionalStorage &&other) = default;
+
+ template <class... Args>
+ explicit OptionalStorage(in_place_t, Args &&... args)
+ : value(std::forward<Args>(args)...), hasVal(true) {}
+
+ void reset() noexcept {
+ if (hasVal) {
+ value.~T();
+ hasVal = false;
+ }
+ }
+
+ bool hasValue() const noexcept { return hasVal; }
+
+ T &getValue() LLVM_LVALUE_FUNCTION noexcept {
+ assert(hasVal);
+ return value;
+ }
+ T const &getValue() const LLVM_LVALUE_FUNCTION noexcept {
+ assert(hasVal);
+ return value;
+ }
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+ T &&getValue() && noexcept {
+ assert(hasVal);
+ return std::move(value);
+ }
+#endif
+
+ template <class... Args> void emplace(Args &&... args) {
+ reset();
+ ::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...);
+ hasVal = true;
+ }
+
+ OptionalStorage &operator=(T const &y) {
+ if (hasValue()) {
+ value = y;
+ } else {
+ ::new ((void *)std::addressof(value)) T(y);
+ hasVal = true;
+ }
+ return *this;
+ }
+ OptionalStorage &operator=(T &&y) {
+ if (hasValue()) {
+ value = std::move(y);
+ } else {
+ ::new ((void *)std::addressof(value)) T(std::move(y));
+ hasVal = true;
+ }
+ return *this;
+ }
+};
+
+} // namespace optional_detail
+
+template <typename T> class Optional {
+ optional_detail::OptionalStorage<T> Storage;
+
+public:
+ using value_type = T;
+
+ constexpr Optional() {}
+ constexpr Optional(NoneType) {}
+
+ Optional(const T &y) : Storage(optional_detail::in_place_t{}, y) {}
+ Optional(const Optional &O) = default;
+
+ Optional(T &&y) : Storage(optional_detail::in_place_t{}, std::move(y)) {}
+ Optional(Optional &&O) = default;
+
+ Optional &operator=(T &&y) {
+ Storage = std::move(y);
+ return *this;
+ }
+ Optional &operator=(Optional &&O) = default;
+
+ /// Create a new object by constructing it in place with the given arguments.
+ template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
+ Storage.emplace(std::forward<ArgTypes>(Args)...);
+ }
+
+ static inline Optional create(const T *y) {
+ return y ? Optional(*y) : Optional();
+ }
+
+ Optional &operator=(const T &y) {
+ Storage = y;
+ return *this;
+ }
+ Optional &operator=(const Optional &O) = default;
+
+ void reset() { Storage.reset(); }
+
+ const T *getPointer() const { return &Storage.getValue(); }
+ T *getPointer() { return &Storage.getValue(); }
+ const T &getValue() const LLVM_LVALUE_FUNCTION { return Storage.getValue(); }
+ T &getValue() LLVM_LVALUE_FUNCTION { return Storage.getValue(); }
+
+ explicit operator bool() const { return hasValue(); }
+ bool hasValue() const { return Storage.hasValue(); }
+ const T *operator->() const { return getPointer(); }
+ T *operator->() { return getPointer(); }
+ const T &operator*() const LLVM_LVALUE_FUNCTION { return getValue(); }
+ T &operator*() LLVM_LVALUE_FUNCTION { return getValue(); }
+
+ template <typename U>
+ constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
+ return hasValue() ? getValue() : std::forward<U>(value);
+ }
+
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+ T &&getValue() && { return std::move(Storage.getValue()); }
+ T &&operator*() && { return std::move(Storage.getValue()); }
+
+ template <typename U>
+ T getValueOr(U &&value) && {
+ return hasValue() ? std::move(getValue()) : std::forward<U>(value);
+ }
+#endif
+};
+
+template <typename T, typename U>
+bool operator==(const Optional<T> &X, const Optional<U> &Y) {
+ if (X && Y)
+ return *X == *Y;
+ return X.hasValue() == Y.hasValue();
+}
+
+template <typename T, typename U>
+bool operator!=(const Optional<T> &X, const Optional<U> &Y) {
+ return !(X == Y);
+}
+
+template <typename T, typename U>
+bool operator<(const Optional<T> &X, const Optional<U> &Y) {
+ if (X && Y)
+ return *X < *Y;
+ return X.hasValue() < Y.hasValue();
+}
+
+template <typename T, typename U>
+bool operator<=(const Optional<T> &X, const Optional<U> &Y) {
+ return !(Y < X);
+}
+
+template <typename T, typename U>
+bool operator>(const Optional<T> &X, const Optional<U> &Y) {
+ return Y < X;
+}
+
+template <typename T, typename U>
+bool operator>=(const Optional<T> &X, const Optional<U> &Y) {
+ return !(X < Y);
+}
+
+template<typename T>
+bool operator==(const Optional<T> &X, NoneType) {
+ return !X;
+}
+
+template<typename T>
+bool operator==(NoneType, const Optional<T> &X) {
+ return X == None;
+}
+
+template<typename T>
+bool operator!=(const Optional<T> &X, NoneType) {
+ return !(X == None);
+}
+
+template<typename T>
+bool operator!=(NoneType, const Optional<T> &X) {
+ return X != None;
+}
+
+template <typename T> bool operator<(const Optional<T> &X, NoneType) {
+ return false;
+}
+
+template <typename T> bool operator<(NoneType, const Optional<T> &X) {
+ return X.hasValue();
+}
+
+template <typename T> bool operator<=(const Optional<T> &X, NoneType) {
+ return !(None < X);
+}
+
+template <typename T> bool operator<=(NoneType, const Optional<T> &X) {
+ return !(X < None);
+}
+
+template <typename T> bool operator>(const Optional<T> &X, NoneType) {
+ return None < X;
+}
+
+template <typename T> bool operator>(NoneType, const Optional<T> &X) {
+ return X < None;
+}
+
+template <typename T> bool operator>=(const Optional<T> &X, NoneType) {
+ return None <= X;
+}
+
+template <typename T> bool operator>=(NoneType, const Optional<T> &X) {
+ return X <= None;
+}
+
+template <typename T> bool operator==(const Optional<T> &X, const T &Y) {
+ return X && *X == Y;
+}
+
+template <typename T> bool operator==(const T &X, const Optional<T> &Y) {
+ return Y && X == *Y;
+}
+
+template <typename T> bool operator!=(const Optional<T> &X, const T &Y) {
+ return !(X == Y);
+}
+
+template <typename T> bool operator!=(const T &X, const Optional<T> &Y) {
+ return !(X == Y);
+}
+
+template <typename T> bool operator<(const Optional<T> &X, const T &Y) {
+ return !X || *X < Y;
+}
+
+template <typename T> bool operator<(const T &X, const Optional<T> &Y) {
+ return Y && X < *Y;
+}
+
+template <typename T> bool operator<=(const Optional<T> &X, const T &Y) {
+ return !(Y < X);
+}
+
+template <typename T> bool operator<=(const T &X, const Optional<T> &Y) {
+ return !(Y < X);
+}
+
+template <typename T> bool operator>(const Optional<T> &X, const T &Y) {
+ return Y < X;
+}
+
+template <typename T> bool operator>(const T &X, const Optional<T> &Y) {
+ return Y < X;
+}
+
+template <typename T> bool operator>=(const Optional<T> &X, const T &Y) {
+ return !(X < Y);
+}
+
+template <typename T> bool operator>=(const T &X, const Optional<T> &Y) {
+ return !(X < Y);
+}
+
+raw_ostream &operator<<(raw_ostream &OS, NoneType);
+
+template <typename T, typename = decltype(std::declval<raw_ostream &>()
+ << std::declval<const T &>())>
+raw_ostream &operator<<(raw_ostream &OS, const Optional<T> &O) {
+ if (O)
+ OS << *O;
+ else
+ OS << None;
+ return OS;
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_OPTIONAL_H
diff --git a/third_party/llvm-project/include/llvm/ADT/PointerIntPair.h b/third_party/llvm-project/include/llvm/ADT/PointerIntPair.h
new file mode 100644
index 000000000..fa6bf1504
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/PointerIntPair.h
@@ -0,0 +1,243 @@
+//===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PointerIntPair class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_POINTERINTPAIR_H
+#define LLVM_ADT_POINTERINTPAIR_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <cstdint>
+#include <limits>
+
+namespace llvm {
+
+template <typename T> struct DenseMapInfo;
+template <typename PointerT, unsigned IntBits, typename PtrTraits>
+struct PointerIntPairInfo;
+
+/// PointerIntPair - This class implements a pair of a pointer and small
+/// integer. It is designed to represent this in the space required by one
+/// pointer by bitmangling the integer into the low part of the pointer. This
+/// can only be done for small integers: typically up to 3 bits, but it depends
+/// on the number of bits available according to PointerLikeTypeTraits for the
+/// type.
+///
+/// Note that PointerIntPair always puts the IntVal part in the highest bits
+/// possible. For example, PointerIntPair<void*, 1, bool> will put the bit for
+/// the bool into bit #2, not bit #0, which allows the low two bits to be used
+/// for something else. For example, this allows:
+/// PointerIntPair<PointerIntPair<void*, 1, bool>, 1, bool>
+/// ... and the two bools will land in different bits.
+template <typename PointerTy, unsigned IntBits, typename IntType = unsigned,
+ typename PtrTraits = PointerLikeTypeTraits<PointerTy>,
+ typename Info = PointerIntPairInfo<PointerTy, IntBits, PtrTraits>>
+class PointerIntPair {
+ // Used by MSVC visualizer and generally helpful for debugging/visualizing.
+ using InfoTy = Info;
+ intptr_t Value = 0;
+
+public:
+ constexpr PointerIntPair() = default;
+
+ PointerIntPair(PointerTy PtrVal, IntType IntVal) {
+ setPointerAndInt(PtrVal, IntVal);
+ }
+
+ explicit PointerIntPair(PointerTy PtrVal) { initWithPointer(PtrVal); }
+
+ PointerTy getPointer() const { return Info::getPointer(Value); }
+
+ IntType getInt() const { return (IntType)Info::getInt(Value); }
+
+ void setPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION {
+ Value = Info::updatePointer(Value, PtrVal);
+ }
+
+ void setInt(IntType IntVal) LLVM_LVALUE_FUNCTION {
+ Value = Info::updateInt(Value, static_cast<intptr_t>(IntVal));
+ }
+
+ void initWithPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION {
+ Value = Info::updatePointer(0, PtrVal);
+ }
+
+ void setPointerAndInt(PointerTy PtrVal, IntType IntVal) LLVM_LVALUE_FUNCTION {
+ Value = Info::updateInt(Info::updatePointer(0, PtrVal),
+ static_cast<intptr_t>(IntVal));
+ }
+
+ PointerTy const *getAddrOfPointer() const {
+ return const_cast<PointerIntPair *>(this)->getAddrOfPointer();
+ }
+
+ PointerTy *getAddrOfPointer() {
+ assert(Value == reinterpret_cast<intptr_t>(getPointer()) &&
+ "Can only return the address if IntBits is cleared and "
+ "PtrTraits doesn't change the pointer");
+ return reinterpret_cast<PointerTy *>(&Value);
+ }
+
+ void *getOpaqueValue() const { return reinterpret_cast<void *>(Value); }
+
+ void setFromOpaqueValue(void *Val) LLVM_LVALUE_FUNCTION {
+ Value = reinterpret_cast<intptr_t>(Val);
+ }
+
+ static PointerIntPair getFromOpaqueValue(void *V) {
+ PointerIntPair P;
+ P.setFromOpaqueValue(V);
+ return P;
+ }
+
+ // Allow PointerIntPairs to be created from const void * if and only if the
+ // pointer type could be created from a const void *.
+ static PointerIntPair getFromOpaqueValue(const void *V) {
+ (void)PtrTraits::getFromVoidPointer(V);
+ return getFromOpaqueValue(const_cast<void *>(V));
+ }
+
+ bool operator==(const PointerIntPair &RHS) const {
+ return Value == RHS.Value;
+ }
+
+ bool operator!=(const PointerIntPair &RHS) const {
+ return Value != RHS.Value;
+ }
+
+ bool operator<(const PointerIntPair &RHS) const { return Value < RHS.Value; }
+ bool operator>(const PointerIntPair &RHS) const { return Value > RHS.Value; }
+
+ bool operator<=(const PointerIntPair &RHS) const {
+ return Value <= RHS.Value;
+ }
+
+ bool operator>=(const PointerIntPair &RHS) const {
+ return Value >= RHS.Value;
+ }
+};
+
+// Specialize is_trivially_copyable to avoid limitation of llvm::is_trivially_copyable
+// when compiled with gcc 4.9.
+template <typename PointerTy, unsigned IntBits, typename IntType,
+ typename PtrTraits,
+ typename Info>
+struct is_trivially_copyable<PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>> : std::true_type {
+#ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE
+ static_assert(std::is_trivially_copyable<PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>>::value,
+ "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
+#endif
+};
+
+
+template <typename PointerT, unsigned IntBits, typename PtrTraits>
+struct PointerIntPairInfo {
+ static_assert(PtrTraits::NumLowBitsAvailable <
+ std::numeric_limits<uintptr_t>::digits,
+ "cannot use a pointer type that has all bits free");
+ static_assert(IntBits <= PtrTraits::NumLowBitsAvailable,
+ "PointerIntPair with integer size too large for pointer");
+ enum : uintptr_t {
+ /// PointerBitMask - The bits that come from the pointer.
+ PointerBitMask =
+ ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable) - 1),
+
+ /// IntShift - The number of low bits that we reserve for other uses, and
+ /// keep zero.
+ IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable - IntBits,
+
+ /// IntMask - This is the unshifted mask for valid bits of the int type.
+ IntMask = (uintptr_t)(((intptr_t)1 << IntBits) - 1),
+
+ // ShiftedIntMask - This is the bits for the integer shifted in place.
+ ShiftedIntMask = (uintptr_t)(IntMask << IntShift)
+ };
+
+ static PointerT getPointer(intptr_t Value) {
+ return PtrTraits::getFromVoidPointer(
+ reinterpret_cast<void *>(Value & PointerBitMask));
+ }
+
+ static intptr_t getInt(intptr_t Value) {
+ return (Value >> IntShift) & IntMask;
+ }
+
+ static intptr_t updatePointer(intptr_t OrigValue, PointerT Ptr) {
+ intptr_t PtrWord =
+ reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(Ptr));
+ assert((PtrWord & ~PointerBitMask) == 0 &&
+ "Pointer is not sufficiently aligned");
+ // Preserve all low bits, just update the pointer.
+ return PtrWord | (OrigValue & ~PointerBitMask);
+ }
+
+ static intptr_t updateInt(intptr_t OrigValue, intptr_t Int) {
+ intptr_t IntWord = static_cast<intptr_t>(Int);
+ assert((IntWord & ~IntMask) == 0 && "Integer too large for field");
+
+ // Preserve all bits other than the ones we are updating.
+ return (OrigValue & ~ShiftedIntMask) | IntWord << IntShift;
+ }
+};
+
+// Provide specialization of DenseMapInfo for PointerIntPair.
+template <typename PointerTy, unsigned IntBits, typename IntType>
+struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>> {
+ using Ty = PointerIntPair<PointerTy, IntBits, IntType>;
+
+ static Ty getEmptyKey() {
+ uintptr_t Val = static_cast<uintptr_t>(-1);
+ Val <<= PointerLikeTypeTraits<Ty>::NumLowBitsAvailable;
+ return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val));
+ }
+
+ static Ty getTombstoneKey() {
+ uintptr_t Val = static_cast<uintptr_t>(-2);
+ Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
+ return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val));
+ }
+
+ static unsigned getHashValue(Ty V) {
+ uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue());
+ return unsigned(IV) ^ unsigned(IV >> 9);
+ }
+
+ static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; }
+};
+
+// Teach SmallPtrSet that PointerIntPair is "basically a pointer".
+template <typename PointerTy, unsigned IntBits, typename IntType,
+ typename PtrTraits>
+struct PointerLikeTypeTraits<
+ PointerIntPair<PointerTy, IntBits, IntType, PtrTraits>> {
+ static inline void *
+ getAsVoidPointer(const PointerIntPair<PointerTy, IntBits, IntType> &P) {
+ return P.getOpaqueValue();
+ }
+
+ static inline PointerIntPair<PointerTy, IntBits, IntType>
+ getFromVoidPointer(void *P) {
+ return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
+ }
+
+ static inline PointerIntPair<PointerTy, IntBits, IntType>
+ getFromVoidPointer(const void *P) {
+ return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
+ }
+
+ enum { NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits };
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_POINTERINTPAIR_H
diff --git a/third_party/llvm-project/include/llvm/ADT/PointerUnion.h b/third_party/llvm-project/include/llvm/ADT/PointerUnion.h
new file mode 100644
index 000000000..98c905775
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/PointerUnion.h
@@ -0,0 +1,309 @@
+//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PointerUnion class, which is a discriminated union of
+// pointer types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_POINTERUNION_H
+#define LLVM_ADT_POINTERUNION_H
+
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+
+namespace llvm {
+
+template <typename T> struct PointerUnionTypeSelectorReturn {
+ using Return = T;
+};
+
+/// Get a type based on whether two types are the same or not.
+///
+/// For:
+///
+/// \code
+/// using Ret = typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return;
+/// \endcode
+///
+/// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
+template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
+struct PointerUnionTypeSelector {
+ using Return = typename PointerUnionTypeSelectorReturn<RET_NE>::Return;
+};
+
+template <typename T, typename RET_EQ, typename RET_NE>
+struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
+ using Return = typename PointerUnionTypeSelectorReturn<RET_EQ>::Return;
+};
+
+template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
+struct PointerUnionTypeSelectorReturn<
+ PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>> {
+ using Return =
+ typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return;
+};
+
+namespace pointer_union_detail {
+ /// Determine the number of bits required to store integers with values < n.
+ /// This is ceil(log2(n)).
+ constexpr int bitsRequired(unsigned n) {
+ return n > 1 ? 1 + bitsRequired((n + 1) / 2) : 0;
+ }
+
+ template <typename... Ts> constexpr int lowBitsAvailable() {
+ return std::min<int>({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...});
+ }
+
+ /// Find the index of a type in a list of types. TypeIndex<T, Us...>::Index
+ /// is the index of T in Us, or sizeof...(Us) if T does not appear in the
+ /// list.
+ template <typename T, typename ...Us> struct TypeIndex;
+ template <typename T, typename ...Us> struct TypeIndex<T, T, Us...> {
+ static constexpr int Index = 0;
+ };
+ template <typename T, typename U, typename... Us>
+ struct TypeIndex<T, U, Us...> {
+ static constexpr int Index = 1 + TypeIndex<T, Us...>::Index;
+ };
+ template <typename T> struct TypeIndex<T> {
+ static constexpr int Index = 0;
+ };
+
+ /// Find the first type in a list of types.
+ template <typename T, typename...> struct GetFirstType {
+ using type = T;
+ };
+
+ /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
+ /// for the template arguments.
+ template <typename ...PTs> class PointerUnionUIntTraits {
+ public:
+ static inline void *getAsVoidPointer(void *P) { return P; }
+ static inline void *getFromVoidPointer(void *P) { return P; }
+ static constexpr int NumLowBitsAvailable = lowBitsAvailable<PTs...>();
+ };
+
+ /// Implement assigment in terms of construction.
+ template <typename Derived, typename T> struct AssignableFrom {
+ Derived &operator=(T t) {
+ return static_cast<Derived &>(*this) = Derived(t);
+ }
+ };
+
+ template <typename Derived, typename ValTy, int I, typename ...Types>
+ class PointerUnionMembers;
+
+ template <typename Derived, typename ValTy, int I>
+ class PointerUnionMembers<Derived, ValTy, I> {
+ protected:
+ ValTy Val;
+ PointerUnionMembers() = default;
+ PointerUnionMembers(ValTy Val) : Val(Val) {}
+
+ friend struct PointerLikeTypeTraits<Derived>;
+ };
+
+ template <typename Derived, typename ValTy, int I, typename Type,
+ typename ...Types>
+ class PointerUnionMembers<Derived, ValTy, I, Type, Types...>
+ : public PointerUnionMembers<Derived, ValTy, I + 1, Types...> {
+ using Base = PointerUnionMembers<Derived, ValTy, I + 1, Types...>;
+ public:
+ using Base::Base;
+ PointerUnionMembers() = default;
+ PointerUnionMembers(Type V)
+ : Base(ValTy(const_cast<void *>(
+ PointerLikeTypeTraits<Type>::getAsVoidPointer(V)),
+ I)) {}
+
+ using Base::operator=;
+ Derived &operator=(Type V) {
+ this->Val = ValTy(
+ const_cast<void *>(PointerLikeTypeTraits<Type>::getAsVoidPointer(V)),
+ I);
+ return static_cast<Derived &>(*this);
+ };
+ };
+}
+
+/// A discriminated union of two or more pointer types, with the discriminator
+/// in the low bit of the pointer.
+///
+/// This implementation is extremely efficient in space due to leveraging the
+/// low bits of the pointer, while exposing a natural and type-safe API.
+///
+/// Common use patterns would be something like this:
+/// PointerUnion<int*, float*> P;
+/// P = (int*)0;
+/// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0"
+/// X = P.get<int*>(); // ok.
+/// Y = P.get<float*>(); // runtime assertion failure.
+/// Z = P.get<double*>(); // compile time failure.
+/// P = (float*)0;
+/// Y = P.get<float*>(); // ok.
+/// X = P.get<int*>(); // runtime assertion failure.
+template <typename... PTs>
+class PointerUnion
+ : public pointer_union_detail::PointerUnionMembers<
+ PointerUnion<PTs...>,
+ PointerIntPair<
+ void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int,
+ pointer_union_detail::PointerUnionUIntTraits<PTs...>>,
+ 0, PTs...> {
+ // The first type is special because we want to directly cast a pointer to a
+ // default-initialized union to a pointer to the first type. But we don't
+ // want PointerUnion to be a 'template <typename First, typename ...Rest>'
+ // because it's much more convenient to have a name for the whole pack. So
+ // split off the first type here.
+ using First = typename pointer_union_detail::GetFirstType<PTs...>::type;
+ using Base = typename PointerUnion::PointerUnionMembers;
+
+public:
+ PointerUnion() = default;
+
+ PointerUnion(std::nullptr_t) : PointerUnion() {}
+ using Base::Base;
+
+ /// Test if the pointer held in the union is null, regardless of
+ /// which type it is.
+ bool isNull() const { return !this->Val.getPointer(); }
+
+ explicit operator bool() const { return !isNull(); }
+
+ /// Test if the Union currently holds the type matching T.
+ template <typename T> int is() const {
+ constexpr int Index = pointer_union_detail::TypeIndex<T, PTs...>::Index;
+ static_assert(Index < sizeof...(PTs),
+ "PointerUnion::is<T> given type not in the union");
+ return this->Val.getInt() == Index;
+ }
+
+ /// Returns the value of the specified pointer type.
+ ///
+ /// If the specified pointer type is incorrect, assert.
+ template <typename T> T get() const {
+ assert(is<T>() && "Invalid accessor called");
+ return PointerLikeTypeTraits<T>::getFromVoidPointer(this->Val.getPointer());
+ }
+
+ /// Returns the current pointer if it is of the specified pointer type,
+ /// otherwises returns null.
+ template <typename T> T dyn_cast() const {
+ if (is<T>())
+ return get<T>();
+ return T();
+ }
+
+ /// If the union is set to the first pointer type get an address pointing to
+ /// it.
+ First const *getAddrOfPtr1() const {
+ return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
+ }
+
+ /// If the union is set to the first pointer type get an address pointing to
+ /// it.
+ First *getAddrOfPtr1() {
+ assert(is<First>() && "Val is not the first pointer");
+ assert(
+ PointerLikeTypeTraits<First>::getAsVoidPointer(get<First>()) ==
+ this->Val.getPointer() &&
+ "Can't get the address because PointerLikeTypeTraits changes the ptr");
+ return const_cast<First *>(
+ reinterpret_cast<const First *>(this->Val.getAddrOfPointer()));
+ }
+
+ /// Assignment from nullptr which just clears the union.
+ const PointerUnion &operator=(std::nullptr_t) {
+ this->Val.initWithPointer(nullptr);
+ return *this;
+ }
+
+ /// Assignment from elements of the union.
+ using Base::operator=;
+
+ void *getOpaqueValue() const { return this->Val.getOpaqueValue(); }
+ static inline PointerUnion getFromOpaqueValue(void *VP) {
+ PointerUnion V;
+ V.Val = decltype(V.Val)::getFromOpaqueValue(VP);
+ return V;
+ }
+};
+
+template <typename ...PTs>
+bool operator==(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) {
+ return lhs.getOpaqueValue() == rhs.getOpaqueValue();
+}
+
+template <typename ...PTs>
+bool operator!=(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) {
+ return lhs.getOpaqueValue() != rhs.getOpaqueValue();
+}
+
+template <typename ...PTs>
+bool operator<(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) {
+ return lhs.getOpaqueValue() < rhs.getOpaqueValue();
+}
+
+// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
+// # low bits available = min(PT1bits,PT2bits)-1.
+template <typename ...PTs>
+struct PointerLikeTypeTraits<PointerUnion<PTs...>> {
+ static inline void *getAsVoidPointer(const PointerUnion<PTs...> &P) {
+ return P.getOpaqueValue();
+ }
+
+ static inline PointerUnion<PTs...> getFromVoidPointer(void *P) {
+ return PointerUnion<PTs...>::getFromOpaqueValue(P);
+ }
+
+ // The number of bits available are the min of the pointer types minus the
+ // bits needed for the discriminator.
+ static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<decltype(
+ PointerUnion<PTs...>::Val)>::NumLowBitsAvailable;
+};
+
+/// A pointer union of three pointer types. See documentation for PointerUnion
+/// for usage.
+template <typename PT1, typename PT2, typename PT3>
+using PointerUnion3 = PointerUnion<PT1, PT2, PT3>;
+
+/// A pointer union of four pointer types. See documentation for PointerUnion
+/// for usage.
+template <typename PT1, typename PT2, typename PT3, typename PT4>
+using PointerUnion4 = PointerUnion<PT1, PT2, PT3, PT4>;
+
+// Teach DenseMap how to use PointerUnions as keys.
+template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> {
+ using Union = PointerUnion<PTs...>;
+ using FirstInfo =
+ DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>;
+
+ static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); }
+
+ static inline Union getTombstoneKey() {
+ return Union(FirstInfo::getTombstoneKey());
+ }
+
+ static unsigned getHashValue(const Union &UnionVal) {
+ intptr_t key = (intptr_t)UnionVal.getOpaqueValue();
+ return DenseMapInfo<intptr_t>::getHashValue(key);
+ }
+
+ static bool isEqual(const Union &LHS, const Union &RHS) {
+ return LHS == RHS;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_POINTERUNION_H
diff --git a/third_party/llvm-project/include/llvm/ADT/STLExtras.h b/third_party/llvm-project/include/llvm/ADT/STLExtras.h
new file mode 100644
index 000000000..274933bc5
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/STLExtras.h
@@ -0,0 +1,1578 @@
+//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains some templates that are useful if you are working with the
+// STL at all.
+//
+// No library is required when using these functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STLEXTRAS_H
+#define LLVM_ADT_STLEXTRAS_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Config/abi-breaking.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
+#include <initializer_list>
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#ifdef EXPENSIVE_CHECKS
+#include <random> // for std::mt19937
+#endif
+
+namespace llvm {
+
+// Only used by compiler if both template types are the same. Useful when
+// using SFINAE to test for the existence of member functions.
+template <typename T, T> struct SameType;
+
+namespace detail {
+
+template <typename RangeT>
+using IterOfRange = decltype(std::begin(std::declval<RangeT &>()));
+
+template <typename RangeT>
+using ValueOfRange = typename std::remove_reference<decltype(
+ *std::begin(std::declval<RangeT &>()))>::type;
+
+} // end namespace detail
+
+//===----------------------------------------------------------------------===//
+// Extra additions to <type_traits>
+//===----------------------------------------------------------------------===//
+
+template <typename T>
+struct negation : std::integral_constant<bool, !bool(T::value)> {};
+
+template <typename...> struct conjunction : std::true_type {};
+template <typename B1> struct conjunction<B1> : B1 {};
+template <typename B1, typename... Bn>
+struct conjunction<B1, Bn...>
+ : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
+
+template <typename T> struct make_const_ptr {
+ using type =
+ typename std::add_pointer<typename std::add_const<T>::type>::type;
+};
+
+template <typename T> struct make_const_ref {
+ using type = typename std::add_lvalue_reference<
+ typename std::add_const<T>::type>::type;
+};
+
+//===----------------------------------------------------------------------===//
+// Extra additions to <functional>
+//===----------------------------------------------------------------------===//
+
+template <class Ty> struct identity {
+ using argument_type = Ty;
+
+ Ty &operator()(Ty &self) const {
+ return self;
+ }
+ const Ty &operator()(const Ty &self) const {
+ return self;
+ }
+};
+
+/// An efficient, type-erasing, non-owning reference to a callable. This is
+/// intended for use as the type of a function parameter that is not used
+/// after the function in question returns.
+///
+/// This class does not own the callable, so it is not in general safe to store
+/// a function_ref.
+template<typename Fn> class function_ref;
+
+template<typename Ret, typename ...Params>
+class function_ref<Ret(Params...)> {
+ Ret (*callback)(intptr_t callable, Params ...params) = nullptr;
+ intptr_t callable;
+
+ template<typename Callable>
+ static Ret callback_fn(intptr_t callable, Params ...params) {
+ return (*reinterpret_cast<Callable*>(callable))(
+ std::forward<Params>(params)...);
+ }
+
+public:
+ function_ref() = default;
+ function_ref(std::nullptr_t) {}
+
+ template <typename Callable>
+ function_ref(Callable &&callable,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_reference<Callable>::type,
+ function_ref>::value>::type * = nullptr)
+ : callback(callback_fn<typename std::remove_reference<Callable>::type>),
+ callable(reinterpret_cast<intptr_t>(&callable)) {}
+
+ Ret operator()(Params ...params) const {
+ return callback(callable, std::forward<Params>(params)...);
+ }
+
+ operator bool() const { return callback; }
+};
+
+// deleter - Very very very simple method that is used to invoke operator
+// delete on something. It is used like this:
+//
+// for_each(V.begin(), B.end(), deleter<Interval>);
+template <class T>
+inline void deleter(T *Ptr) {
+ delete Ptr;
+}
+
+//===----------------------------------------------------------------------===//
+// Extra additions to <iterator>
+//===----------------------------------------------------------------------===//
+
+namespace adl_detail {
+
+using std::begin;
+
+template <typename ContainerTy>
+auto adl_begin(ContainerTy &&container)
+ -> decltype(begin(std::forward<ContainerTy>(container))) {
+ return begin(std::forward<ContainerTy>(container));
+}
+
+using std::end;
+
+template <typename ContainerTy>
+auto adl_end(ContainerTy &&container)
+ -> decltype(end(std::forward<ContainerTy>(container))) {
+ return end(std::forward<ContainerTy>(container));
+}
+
+using std::swap;
+
+template <typename T>
+void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(),
+ std::declval<T>()))) {
+ swap(std::forward<T>(lhs), std::forward<T>(rhs));
+}
+
+} // end namespace adl_detail
+
+template <typename ContainerTy>
+auto adl_begin(ContainerTy &&container)
+ -> decltype(adl_detail::adl_begin(std::forward<ContainerTy>(container))) {
+ return adl_detail::adl_begin(std::forward<ContainerTy>(container));
+}
+
+template <typename ContainerTy>
+auto adl_end(ContainerTy &&container)
+ -> decltype(adl_detail::adl_end(std::forward<ContainerTy>(container))) {
+ return adl_detail::adl_end(std::forward<ContainerTy>(container));
+}
+
+template <typename T>
+void adl_swap(T &&lhs, T &&rhs) noexcept(
+ noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) {
+ adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs));
+}
+
+/// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty.
+template <typename T>
+constexpr bool empty(const T &RangeOrContainer) {
+ return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer);
+}
+
+// mapped_iterator - This is a simple iterator adapter that causes a function to
+// be applied whenever operator* is invoked on the iterator.
+
+template <typename ItTy, typename FuncTy,
+ typename FuncReturnTy =
+ decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))>
+class mapped_iterator
+ : public iterator_adaptor_base<
+ mapped_iterator<ItTy, FuncTy>, ItTy,
+ typename std::iterator_traits<ItTy>::iterator_category,
+ typename std::remove_reference<FuncReturnTy>::type> {
+public:
+ mapped_iterator(ItTy U, FuncTy F)
+ : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {}
+
+ ItTy getCurrent() { return this->I; }
+
+ FuncReturnTy operator*() { return F(*this->I); }
+
+private:
+ FuncTy F;
+};
+
+// map_iterator - Provide a convenient way to create mapped_iterators, just like
+// make_pair is useful for creating pairs...
+template <class ItTy, class FuncTy>
+inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) {
+ return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F));
+}
+
+template <class ContainerTy, class FuncTy>
+auto map_range(ContainerTy &&C, FuncTy F)
+ -> decltype(make_range(map_iterator(C.begin(), F),
+ map_iterator(C.end(), F))) {
+ return make_range(map_iterator(C.begin(), F), map_iterator(C.end(), F));
+}
+
+/// Helper to determine if type T has a member called rbegin().
+template <typename Ty> class has_rbegin_impl {
+ using yes = char[1];
+ using no = char[2];
+
+ template <typename Inner>
+ static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr);
+
+ template <typename>
+ static no& test(...);
+
+public:
+ static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
+};
+
+/// Metafunction to determine if T& or T has a member called rbegin().
+template <typename Ty>
+struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> {
+};
+
+// Returns an iterator_range over the given container which iterates in reverse.
+// Note that the container must have rbegin()/rend() methods for this to work.
+template <typename ContainerTy>
+auto reverse(ContainerTy &&C,
+ typename std::enable_if<has_rbegin<ContainerTy>::value>::type * =
+ nullptr) -> decltype(make_range(C.rbegin(), C.rend())) {
+ return make_range(C.rbegin(), C.rend());
+}
+
+// Returns a std::reverse_iterator wrapped around the given iterator.
+template <typename IteratorTy>
+std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) {
+ return std::reverse_iterator<IteratorTy>(It);
+}
+
+// Returns an iterator_range over the given container which iterates in reverse.
+// Note that the container must have begin()/end() methods which return
+// bidirectional iterators for this to work.
+template <typename ContainerTy>
+auto reverse(
+ ContainerTy &&C,
+ typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr)
+ -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)),
+ llvm::make_reverse_iterator(std::begin(C)))) {
+ return make_range(llvm::make_reverse_iterator(std::end(C)),
+ llvm::make_reverse_iterator(std::begin(C)));
+}
+
+/// An iterator adaptor that filters the elements of given inner iterators.
+///
+/// The predicate parameter should be a callable object that accepts the wrapped
+/// iterator's reference type and returns a bool. When incrementing or
+/// decrementing the iterator, it will call the predicate on each element and
+/// skip any where it returns false.
+///
+/// \code
+/// int A[] = { 1, 2, 3, 4 };
+/// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; });
+/// // R contains { 1, 3 }.
+/// \endcode
+///
+/// Note: filter_iterator_base implements support for forward iteration.
+/// filter_iterator_impl exists to provide support for bidirectional iteration,
+/// conditional on whether the wrapped iterator supports it.
+template <typename WrappedIteratorT, typename PredicateT, typename IterTag>
+class filter_iterator_base
+ : public iterator_adaptor_base<
+ filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
+ WrappedIteratorT,
+ typename std::common_type<
+ IterTag, typename std::iterator_traits<
+ WrappedIteratorT>::iterator_category>::type> {
+ using BaseT = iterator_adaptor_base<
+ filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
+ WrappedIteratorT,
+ typename std::common_type<
+ IterTag, typename std::iterator_traits<
+ WrappedIteratorT>::iterator_category>::type>;
+
+protected:
+ WrappedIteratorT End;
+ PredicateT Pred;
+
+ void findNextValid() {
+ while (this->I != End && !Pred(*this->I))
+ BaseT::operator++();
+ }
+
+ // Construct the iterator. The begin iterator needs to know where the end
+ // is, so that it can properly stop when it gets there. The end iterator only
+ // needs the predicate to support bidirectional iteration.
+ filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End,
+ PredicateT Pred)
+ : BaseT(Begin), End(End), Pred(Pred) {
+ findNextValid();
+ }
+
+public:
+ using BaseT::operator++;
+
+ filter_iterator_base &operator++() {
+ BaseT::operator++();
+ findNextValid();
+ return *this;
+ }
+};
+
+/// Specialization of filter_iterator_base for forward iteration only.
+template <typename WrappedIteratorT, typename PredicateT,
+ typename IterTag = std::forward_iterator_tag>
+class filter_iterator_impl
+ : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> {
+ using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>;
+
+public:
+ filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
+ PredicateT Pred)
+ : BaseT(Begin, End, Pred) {}
+};
+
+/// Specialization of filter_iterator_base for bidirectional iteration.
+template <typename WrappedIteratorT, typename PredicateT>
+class filter_iterator_impl<WrappedIteratorT, PredicateT,
+ std::bidirectional_iterator_tag>
+ : public filter_iterator_base<WrappedIteratorT, PredicateT,
+ std::bidirectional_iterator_tag> {
+ using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT,
+ std::bidirectional_iterator_tag>;
+ void findPrevValid() {
+ while (!this->Pred(*this->I))
+ BaseT::operator--();
+ }
+
+public:
+ using BaseT::operator--;
+
+ filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
+ PredicateT Pred)
+ : BaseT(Begin, End, Pred) {}
+
+ filter_iterator_impl &operator--() {
+ BaseT::operator--();
+ findPrevValid();
+ return *this;
+ }
+};
+
+namespace detail {
+
+template <bool is_bidirectional> struct fwd_or_bidi_tag_impl {
+ using type = std::forward_iterator_tag;
+};
+
+template <> struct fwd_or_bidi_tag_impl<true> {
+ using type = std::bidirectional_iterator_tag;
+};
+
+/// Helper which sets its type member to forward_iterator_tag if the category
+/// of \p IterT does not derive from bidirectional_iterator_tag, and to
+/// bidirectional_iterator_tag otherwise.
+template <typename IterT> struct fwd_or_bidi_tag {
+ using type = typename fwd_or_bidi_tag_impl<std::is_base_of<
+ std::bidirectional_iterator_tag,
+ typename std::iterator_traits<IterT>::iterator_category>::value>::type;
+};
+
+} // namespace detail
+
+/// Defines filter_iterator to a suitable specialization of
+/// filter_iterator_impl, based on the underlying iterator's category.
+template <typename WrappedIteratorT, typename PredicateT>
+using filter_iterator = filter_iterator_impl<
+ WrappedIteratorT, PredicateT,
+ typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>;
+
+/// Convenience function that takes a range of elements and a predicate,
+/// and return a new filter_iterator range.
+///
+/// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the
+/// lifetime of that temporary is not kept by the returned range object, and the
+/// temporary is going to be dropped on the floor after the make_iterator_range
+/// full expression that contains this function call.
+template <typename RangeT, typename PredicateT>
+iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>>
+make_filter_range(RangeT &&Range, PredicateT Pred) {
+ using FilterIteratorT =
+ filter_iterator<detail::IterOfRange<RangeT>, PredicateT>;
+ return make_range(
+ FilterIteratorT(std::begin(std::forward<RangeT>(Range)),
+ std::end(std::forward<RangeT>(Range)), Pred),
+ FilterIteratorT(std::end(std::forward<RangeT>(Range)),
+ std::end(std::forward<RangeT>(Range)), Pred));
+}
+
+/// A pseudo-iterator adaptor that is designed to implement "early increment"
+/// style loops.
+///
+/// This is *not a normal iterator* and should almost never be used directly. It
+/// is intended primarily to be used with range based for loops and some range
+/// algorithms.
+///
+/// The iterator isn't quite an `OutputIterator` or an `InputIterator` but
+/// somewhere between them. The constraints of these iterators are:
+///
+/// - On construction or after being incremented, it is comparable and
+/// dereferencable. It is *not* incrementable.
+/// - After being dereferenced, it is neither comparable nor dereferencable, it
+/// is only incrementable.
+///
+/// This means you can only dereference the iterator once, and you can only
+/// increment it once between dereferences.
+template <typename WrappedIteratorT>
+class early_inc_iterator_impl
+ : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
+ WrappedIteratorT, std::input_iterator_tag> {
+ using BaseT =
+ iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
+ WrappedIteratorT, std::input_iterator_tag>;
+
+ using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer;
+
+protected:
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ bool IsEarlyIncremented = false;
+#endif
+
+public:
+ early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {}
+
+ using BaseT::operator*;
+ typename BaseT::reference operator*() {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ assert(!IsEarlyIncremented && "Cannot dereference twice!");
+ IsEarlyIncremented = true;
+#endif
+ return *(this->I)++;
+ }
+
+ using BaseT::operator++;
+ early_inc_iterator_impl &operator++() {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ assert(IsEarlyIncremented && "Cannot increment before dereferencing!");
+ IsEarlyIncremented = false;
+#endif
+ return *this;
+ }
+
+ using BaseT::operator==;
+ bool operator==(const early_inc_iterator_impl &RHS) const {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ assert(!IsEarlyIncremented && "Cannot compare after dereferencing!");
+#endif
+ return BaseT::operator==(RHS);
+ }
+};
+
+/// Make a range that does early increment to allow mutation of the underlying
+/// range without disrupting iteration.
+///
+/// The underlying iterator will be incremented immediately after it is
+/// dereferenced, allowing deletion of the current node or insertion of nodes to
+/// not disrupt iteration provided they do not invalidate the *next* iterator --
+/// the current iterator can be invalidated.
+///
+/// This requires a very exact pattern of use that is only really suitable to
+/// range based for loops and other range algorithms that explicitly guarantee
+/// to dereference exactly once each element, and to increment exactly once each
+/// element.
+template <typename RangeT>
+iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>>
+make_early_inc_range(RangeT &&Range) {
+ using EarlyIncIteratorT =
+ early_inc_iterator_impl<detail::IterOfRange<RangeT>>;
+ return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))),
+ EarlyIncIteratorT(std::end(std::forward<RangeT>(Range))));
+}
+
+// forward declarations required by zip_shortest/zip_first/zip_longest
+template <typename R, typename UnaryPredicate>
+bool all_of(R &&range, UnaryPredicate P);
+template <typename R, typename UnaryPredicate>
+bool any_of(R &&range, UnaryPredicate P);
+
+namespace detail {
+
+using std::declval;
+
+// We have to alias this since inlining the actual type at the usage site
+// in the parameter list of iterator_facade_base<> below ICEs MSVC 2017.
+template<typename... Iters> struct ZipTupleType {
+ using type = std::tuple<decltype(*declval<Iters>())...>;
+};
+
+template <typename ZipType, typename... Iters>
+using zip_traits = iterator_facade_base<
+ ZipType, typename std::common_type<std::bidirectional_iterator_tag,
+ typename std::iterator_traits<
+ Iters>::iterator_category...>::type,
+ // ^ TODO: Implement random access methods.
+ typename ZipTupleType<Iters...>::type,
+ typename std::iterator_traits<typename std::tuple_element<
+ 0, std::tuple<Iters...>>::type>::difference_type,
+ // ^ FIXME: This follows boost::make_zip_iterator's assumption that all
+ // inner iterators have the same difference_type. It would fail if, for
+ // instance, the second field's difference_type were non-numeric while the
+ // first is.
+ typename ZipTupleType<Iters...>::type *,
+ typename ZipTupleType<Iters...>::type>;
+
+template <typename ZipType, typename... Iters>
+struct zip_common : public zip_traits<ZipType, Iters...> {
+ using Base = zip_traits<ZipType, Iters...>;
+ using value_type = typename Base::value_type;
+
+ std::tuple<Iters...> iterators;
+
+protected:
+ template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const {
+ return value_type(*std::get<Ns>(iterators)...);
+ }
+
+ template <size_t... Ns>
+ decltype(iterators) tup_inc(std::index_sequence<Ns...>) const {
+ return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...);
+ }
+
+ template <size_t... Ns>
+ decltype(iterators) tup_dec(std::index_sequence<Ns...>) const {
+ return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...);
+ }
+
+public:
+ zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {}
+
+ value_type operator*() { return deref(std::index_sequence_for<Iters...>{}); }
+
+ const value_type operator*() const {
+ return deref(std::index_sequence_for<Iters...>{});
+ }
+
+ ZipType &operator++() {
+ iterators = tup_inc(std::index_sequence_for<Iters...>{});
+ return *reinterpret_cast<ZipType *>(this);
+ }
+
+ ZipType &operator--() {
+ static_assert(Base::IsBidirectional,
+ "All inner iterators must be at least bidirectional.");
+ iterators = tup_dec(std::index_sequence_for<Iters...>{});
+ return *reinterpret_cast<ZipType *>(this);
+ }
+};
+
+template <typename... Iters>
+struct zip_first : public zip_common<zip_first<Iters...>, Iters...> {
+ using Base = zip_common<zip_first<Iters...>, Iters...>;
+
+ bool operator==(const zip_first<Iters...> &other) const {
+ return std::get<0>(this->iterators) == std::get<0>(other.iterators);
+ }
+
+ zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
+};
+
+template <typename... Iters>
+class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> {
+ template <size_t... Ns>
+ bool test(const zip_shortest<Iters...> &other,
+ std::index_sequence<Ns...>) const {
+ return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
+ std::get<Ns>(other.iterators)...},
+ identity<bool>{});
+ }
+
+public:
+ using Base = zip_common<zip_shortest<Iters...>, Iters...>;
+
+ zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
+
+ bool operator==(const zip_shortest<Iters...> &other) const {
+ return !test(other, std::index_sequence_for<Iters...>{});
+ }
+};
+
+template <template <typename...> class ItType, typename... Args> class zippy {
+public:
+ using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>;
+ using iterator_category = typename iterator::iterator_category;
+ using value_type = typename iterator::value_type;
+ using difference_type = typename iterator::difference_type;
+ using pointer = typename iterator::pointer;
+ using reference = typename iterator::reference;
+
+private:
+ std::tuple<Args...> ts;
+
+ template <size_t... Ns>
+ iterator begin_impl(std::index_sequence<Ns...>) const {
+ return iterator(std::begin(std::get<Ns>(ts))...);
+ }
+ template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const {
+ return iterator(std::end(std::get<Ns>(ts))...);
+ }
+
+public:
+ zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
+
+ iterator begin() const {
+ return begin_impl(std::index_sequence_for<Args...>{});
+ }
+ iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); }
+};
+
+} // end namespace detail
+
+/// zip iterator for two or more iteratable types.
+template <typename T, typename U, typename... Args>
+detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u,
+ Args &&... args) {
+ return detail::zippy<detail::zip_shortest, T, U, Args...>(
+ std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
+}
+
+/// zip iterator that, for the sake of efficiency, assumes the first iteratee to
+/// be the shortest.
+template <typename T, typename U, typename... Args>
+detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u,
+ Args &&... args) {
+ return detail::zippy<detail::zip_first, T, U, Args...>(
+ std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
+}
+
+namespace detail {
+template <typename Iter>
+static Iter next_or_end(const Iter &I, const Iter &End) {
+ if (I == End)
+ return End;
+ return std::next(I);
+}
+
+template <typename Iter>
+static auto deref_or_none(const Iter &I, const Iter &End)
+ -> llvm::Optional<typename std::remove_const<
+ typename std::remove_reference<decltype(*I)>::type>::type> {
+ if (I == End)
+ return None;
+ return *I;
+}
+
+template <typename Iter> struct ZipLongestItemType {
+ using type =
+ llvm::Optional<typename std::remove_const<typename std::remove_reference<
+ decltype(*std::declval<Iter>())>::type>::type>;
+};
+
+template <typename... Iters> struct ZipLongestTupleType {
+ using type = std::tuple<typename ZipLongestItemType<Iters>::type...>;
+};
+
+template <typename... Iters>
+class zip_longest_iterator
+ : public iterator_facade_base<
+ zip_longest_iterator<Iters...>,
+ typename std::common_type<
+ std::forward_iterator_tag,
+ typename std::iterator_traits<Iters>::iterator_category...>::type,
+ typename ZipLongestTupleType<Iters...>::type,
+ typename std::iterator_traits<typename std::tuple_element<
+ 0, std::tuple<Iters...>>::type>::difference_type,
+ typename ZipLongestTupleType<Iters...>::type *,
+ typename ZipLongestTupleType<Iters...>::type> {
+public:
+ using value_type = typename ZipLongestTupleType<Iters...>::type;
+
+private:
+ std::tuple<Iters...> iterators;
+ std::tuple<Iters...> end_iterators;
+
+ template <size_t... Ns>
+ bool test(const zip_longest_iterator<Iters...> &other,
+ std::index_sequence<Ns...>) const {
+ return llvm::any_of(
+ std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
+ std::get<Ns>(other.iterators)...},
+ identity<bool>{});
+ }
+
+ template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const {
+ return value_type(
+ deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
+ }
+
+ template <size_t... Ns>
+ decltype(iterators) tup_inc(std::index_sequence<Ns...>) const {
+ return std::tuple<Iters...>(
+ next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
+ }
+
+public:
+ zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts)
+ : iterators(std::forward<Iters>(ts.first)...),
+ end_iterators(std::forward<Iters>(ts.second)...) {}
+
+ value_type operator*() { return deref(std::index_sequence_for<Iters...>{}); }
+
+ value_type operator*() const {
+ return deref(std::index_sequence_for<Iters...>{});
+ }
+
+ zip_longest_iterator<Iters...> &operator++() {
+ iterators = tup_inc(std::index_sequence_for<Iters...>{});
+ return *this;
+ }
+
+ bool operator==(const zip_longest_iterator<Iters...> &other) const {
+ return !test(other, std::index_sequence_for<Iters...>{});
+ }
+};
+
+template <typename... Args> class zip_longest_range {
+public:
+ using iterator =
+ zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>;
+ using iterator_category = typename iterator::iterator_category;
+ using value_type = typename iterator::value_type;
+ using difference_type = typename iterator::difference_type;
+ using pointer = typename iterator::pointer;
+ using reference = typename iterator::reference;
+
+private:
+ std::tuple<Args...> ts;
+
+ template <size_t... Ns>
+ iterator begin_impl(std::index_sequence<Ns...>) const {
+ return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)),
+ adl_end(std::get<Ns>(ts)))...);
+ }
+
+ template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const {
+ return iterator(std::make_pair(adl_end(std::get<Ns>(ts)),
+ adl_end(std::get<Ns>(ts)))...);
+ }
+
+public:
+ zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
+
+ iterator begin() const {
+ return begin_impl(std::index_sequence_for<Args...>{});
+ }
+ iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); }
+};
+} // namespace detail
+
+/// Iterate over two or more iterators at the same time. Iteration continues
+/// until all iterators reach the end. The llvm::Optional only contains a value
+/// if the iterator has not reached the end.
+template <typename T, typename U, typename... Args>
+detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u,
+ Args &&... args) {
+ return detail::zip_longest_range<T, U, Args...>(
+ std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
+}
+
+/// Iterator wrapper that concatenates sequences together.
+///
+/// This can concatenate different iterators, even with different types, into
+/// a single iterator provided the value types of all the concatenated
+/// iterators expose `reference` and `pointer` types that can be converted to
+/// `ValueT &` and `ValueT *` respectively. It doesn't support more
+/// interesting/customized pointer or reference types.
+///
+/// Currently this only supports forward or higher iterator categories as
+/// inputs and always exposes a forward iterator interface.
+template <typename ValueT, typename... IterTs>
+class concat_iterator
+ : public iterator_facade_base<concat_iterator<ValueT, IterTs...>,
+ std::forward_iterator_tag, ValueT> {
+ using BaseT = typename concat_iterator::iterator_facade_base;
+
+ /// We store both the current and end iterators for each concatenated
+ /// sequence in a tuple of pairs.
+ ///
+ /// Note that something like iterator_range seems nice at first here, but the
+ /// range properties are of little benefit and end up getting in the way
+ /// because we need to do mutation on the current iterators.
+ std::tuple<IterTs...> Begins;
+ std::tuple<IterTs...> Ends;
+
+ /// Attempts to increment a specific iterator.
+ ///
+ /// Returns true if it was able to increment the iterator. Returns false if
+ /// the iterator is already at the end iterator.
+ template <size_t Index> bool incrementHelper() {
+ auto &Begin = std::get<Index>(Begins);
+ auto &End = std::get<Index>(Ends);
+ if (Begin == End)
+ return false;
+
+ ++Begin;
+ return true;
+ }
+
+ /// Increments the first non-end iterator.
+ ///
+ /// It is an error to call this with all iterators at the end.
+ template <size_t... Ns> void increment(std::index_sequence<Ns...>) {
+ // Build a sequence of functions to increment each iterator if possible.
+ bool (concat_iterator::*IncrementHelperFns[])() = {
+ &concat_iterator::incrementHelper<Ns>...};
+
+ // Loop over them, and stop as soon as we succeed at incrementing one.
+ for (auto &IncrementHelperFn : IncrementHelperFns)
+ if ((this->*IncrementHelperFn)())
+ return;
+
+ llvm_unreachable("Attempted to increment an end concat iterator!");
+ }
+
+ /// Returns null if the specified iterator is at the end. Otherwise,
+ /// dereferences the iterator and returns the address of the resulting
+ /// reference.
+ template <size_t Index> ValueT *getHelper() const {
+ auto &Begin = std::get<Index>(Begins);
+ auto &End = std::get<Index>(Ends);
+ if (Begin == End)
+ return nullptr;
+
+ return &*Begin;
+ }
+
+ /// Finds the first non-end iterator, dereferences, and returns the resulting
+ /// reference.
+ ///
+ /// It is an error to call this with all iterators at the end.
+ template <size_t... Ns> ValueT &get(std::index_sequence<Ns...>) const {
+ // Build a sequence of functions to get from iterator if possible.
+ ValueT *(concat_iterator::*GetHelperFns[])() const = {
+ &concat_iterator::getHelper<Ns>...};
+
+ // Loop over them, and return the first result we find.
+ for (auto &GetHelperFn : GetHelperFns)
+ if (ValueT *P = (this->*GetHelperFn)())
+ return *P;
+
+ llvm_unreachable("Attempted to get a pointer from an end concat iterator!");
+ }
+
+public:
+ /// Constructs an iterator from a squence of ranges.
+ ///
+ /// We need the full range to know how to switch between each of the
+ /// iterators.
+ template <typename... RangeTs>
+ explicit concat_iterator(RangeTs &&... Ranges)
+ : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {}
+
+ using BaseT::operator++;
+
+ concat_iterator &operator++() {
+ increment(std::index_sequence_for<IterTs...>());
+ return *this;
+ }
+
+ ValueT &operator*() const {
+ return get(std::index_sequence_for<IterTs...>());
+ }
+
+ bool operator==(const concat_iterator &RHS) const {
+ return Begins == RHS.Begins && Ends == RHS.Ends;
+ }
+};
+
+namespace detail {
+
+/// Helper to store a sequence of ranges being concatenated and access them.
+///
+/// This is designed to facilitate providing actual storage when temporaries
+/// are passed into the constructor such that we can use it as part of range
+/// based for loops.
+template <typename ValueT, typename... RangeTs> class concat_range {
+public:
+ using iterator =
+ concat_iterator<ValueT,
+ decltype(std::begin(std::declval<RangeTs &>()))...>;
+
+private:
+ std::tuple<RangeTs...> Ranges;
+
+ template <size_t... Ns> iterator begin_impl(std::index_sequence<Ns...>) {
+ return iterator(std::get<Ns>(Ranges)...);
+ }
+ template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) {
+ return iterator(make_range(std::end(std::get<Ns>(Ranges)),
+ std::end(std::get<Ns>(Ranges)))...);
+ }
+
+public:
+ concat_range(RangeTs &&... Ranges)
+ : Ranges(std::forward<RangeTs>(Ranges)...) {}
+
+ iterator begin() { return begin_impl(std::index_sequence_for<RangeTs...>{}); }
+ iterator end() { return end_impl(std::index_sequence_for<RangeTs...>{}); }
+};
+
+} // end namespace detail
+
+/// Concatenated range across two or more ranges.
+///
+/// The desired value type must be explicitly specified.
+template <typename ValueT, typename... RangeTs>
+detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) {
+ static_assert(sizeof...(RangeTs) > 1,
+ "Need more than one range to concatenate!");
+ return detail::concat_range<ValueT, RangeTs...>(
+ std::forward<RangeTs>(Ranges)...);
+}
+
+//===----------------------------------------------------------------------===//
+// Extra additions to <utility>
+//===----------------------------------------------------------------------===//
+
+/// Function object to check whether the first component of a std::pair
+/// compares less than the first component of another std::pair.
+struct less_first {
+ template <typename T> bool operator()(const T &lhs, const T &rhs) const {
+ return lhs.first < rhs.first;
+ }
+};
+
+/// Function object to check whether the second component of a std::pair
+/// compares less than the second component of another std::pair.
+struct less_second {
+ template <typename T> bool operator()(const T &lhs, const T &rhs) const {
+ return lhs.second < rhs.second;
+ }
+};
+
+/// \brief Function object to apply a binary function to the first component of
+/// a std::pair.
+template<typename FuncTy>
+struct on_first {
+ FuncTy func;
+
+ template <typename T>
+ auto operator()(const T &lhs, const T &rhs) const
+ -> decltype(func(lhs.first, rhs.first)) {
+ return func(lhs.first, rhs.first);
+ }
+};
+
+/// Utility type to build an inheritance chain that makes it easy to rank
+/// overload candidates.
+template <int N> struct rank : rank<N - 1> {};
+template <> struct rank<0> {};
+
+/// traits class for checking whether type T is one of any of the given
+/// types in the variadic list.
+template <typename T, typename... Ts> struct is_one_of {
+ static const bool value = false;
+};
+
+template <typename T, typename U, typename... Ts>
+struct is_one_of<T, U, Ts...> {
+ static const bool value =
+ std::is_same<T, U>::value || is_one_of<T, Ts...>::value;
+};
+
+/// traits class for checking whether type T is a base class for all
+/// the given types in the variadic list.
+template <typename T, typename... Ts> struct are_base_of {
+ static const bool value = true;
+};
+
+template <typename T, typename U, typename... Ts>
+struct are_base_of<T, U, Ts...> {
+ static const bool value =
+ std::is_base_of<T, U>::value && are_base_of<T, Ts...>::value;
+};
+
+//===----------------------------------------------------------------------===//
+// Extra additions for arrays
+//===----------------------------------------------------------------------===//
+
+/// Find the length of an array.
+template <class T, std::size_t N>
+constexpr inline size_t array_lengthof(T (&)[N]) {
+ return N;
+}
+
+/// Adapt std::less<T> for array_pod_sort.
+template<typename T>
+inline int array_pod_sort_comparator(const void *P1, const void *P2) {
+ if (std::less<T>()(*reinterpret_cast<const T*>(P1),
+ *reinterpret_cast<const T*>(P2)))
+ return -1;
+ if (std::less<T>()(*reinterpret_cast<const T*>(P2),
+ *reinterpret_cast<const T*>(P1)))
+ return 1;
+ return 0;
+}
+
+/// get_array_pod_sort_comparator - This is an internal helper function used to
+/// get type deduction of T right.
+template<typename T>
+inline int (*get_array_pod_sort_comparator(const T &))
+ (const void*, const void*) {
+ return array_pod_sort_comparator<T>;
+}
+
+/// array_pod_sort - This sorts an array with the specified start and end
+/// extent. This is just like std::sort, except that it calls qsort instead of
+/// using an inlined template. qsort is slightly slower than std::sort, but
+/// most sorts are not performance critical in LLVM and std::sort has to be
+/// template instantiated for each type, leading to significant measured code
+/// bloat. This function should generally be used instead of std::sort where
+/// possible.
+///
+/// This function assumes that you have simple POD-like types that can be
+/// compared with std::less and can be moved with memcpy. If this isn't true,
+/// you should use std::sort.
+///
+/// NOTE: If qsort_r were portable, we could allow a custom comparator and
+/// default to std::less.
+template<class IteratorTy>
+inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
+ // Don't inefficiently call qsort with one element or trigger undefined
+ // behavior with an empty sequence.
+ auto NElts = End - Start;
+ if (NElts <= 1) return;
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
+ qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
+}
+
+template <class IteratorTy>
+inline void array_pod_sort(
+ IteratorTy Start, IteratorTy End,
+ int (*Compare)(
+ const typename std::iterator_traits<IteratorTy>::value_type *,
+ const typename std::iterator_traits<IteratorTy>::value_type *)) {
+ // Don't inefficiently call qsort with one element or trigger undefined
+ // behavior with an empty sequence.
+ auto NElts = End - Start;
+ if (NElts <= 1) return;
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
+ qsort(&*Start, NElts, sizeof(*Start),
+ reinterpret_cast<int (*)(const void *, const void *)>(Compare));
+}
+
+// Provide wrappers to std::sort which shuffle the elements before sorting
+// to help uncover non-deterministic behavior (PR35135).
+template <typename IteratorTy>
+inline void sort(IteratorTy Start, IteratorTy End) {
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
+ std::sort(Start, End);
+}
+
+template <typename Container> inline void sort(Container &&C) {
+ llvm::sort(adl_begin(C), adl_end(C));
+}
+
+template <typename IteratorTy, typename Compare>
+inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
+ std::sort(Start, End, Comp);
+}
+
+template <typename Container, typename Compare>
+inline void sort(Container &&C, Compare Comp) {
+ llvm::sort(adl_begin(C), adl_end(C), Comp);
+}
+
+//===----------------------------------------------------------------------===//
+// Extra additions to <algorithm>
+//===----------------------------------------------------------------------===//
+
+/// For a container of pointers, deletes the pointers and then clears the
+/// container.
+template<typename Container>
+void DeleteContainerPointers(Container &C) {
+ for (auto V : C)
+ delete V;
+ C.clear();
+}
+
+/// In a container of pairs (usually a map) whose second element is a pointer,
+/// deletes the second elements and then clears the container.
+template<typename Container>
+void DeleteContainerSeconds(Container &C) {
+ for (auto &V : C)
+ delete V.second;
+ C.clear();
+}
+
+/// Get the size of a range. This is a wrapper function around std::distance
+/// which is only enabled when the operation is O(1).
+template <typename R>
+auto size(R &&Range, typename std::enable_if<
+ std::is_same<typename std::iterator_traits<decltype(
+ Range.begin())>::iterator_category,
+ std::random_access_iterator_tag>::value,
+ void>::type * = nullptr)
+ -> decltype(std::distance(Range.begin(), Range.end())) {
+ return std::distance(Range.begin(), Range.end());
+}
+
+/// Provide wrappers to std::for_each which take ranges instead of having to
+/// pass begin/end explicitly.
+template <typename R, typename UnaryPredicate>
+UnaryPredicate for_each(R &&Range, UnaryPredicate P) {
+ return std::for_each(adl_begin(Range), adl_end(Range), P);
+}
+
+/// Provide wrappers to std::all_of which take ranges instead of having to pass
+/// begin/end explicitly.
+template <typename R, typename UnaryPredicate>
+bool all_of(R &&Range, UnaryPredicate P) {
+ return std::all_of(adl_begin(Range), adl_end(Range), P);
+}
+
+/// Provide wrappers to std::any_of which take ranges instead of having to pass
+/// begin/end explicitly.
+template <typename R, typename UnaryPredicate>
+bool any_of(R &&Range, UnaryPredicate P) {
+ return std::any_of(adl_begin(Range), adl_end(Range), P);
+}
+
+/// Provide wrappers to std::none_of which take ranges instead of having to pass
+/// begin/end explicitly.
+template <typename R, typename UnaryPredicate>
+bool none_of(R &&Range, UnaryPredicate P) {
+ return std::none_of(adl_begin(Range), adl_end(Range), P);
+}
+
+/// Provide wrappers to std::find which take ranges instead of having to pass
+/// begin/end explicitly.
+template <typename R, typename T>
+auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range)) {
+ return std::find(adl_begin(Range), adl_end(Range), Val);
+}
+
+/// Provide wrappers to std::find_if which take ranges instead of having to pass
+/// begin/end explicitly.
+template <typename R, typename UnaryPredicate>
+auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
+ return std::find_if(adl_begin(Range), adl_end(Range), P);
+}
+
+template <typename R, typename UnaryPredicate>
+auto find_if_not(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
+ return std::find_if_not(adl_begin(Range), adl_end(Range), P);
+}
+
+/// Provide wrappers to std::remove_if which take ranges instead of having to
+/// pass begin/end explicitly.
+template <typename R, typename UnaryPredicate>
+auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
+ return std::remove_if(adl_begin(Range), adl_end(Range), P);
+}
+
+/// Provide wrappers to std::copy_if which take ranges instead of having to
+/// pass begin/end explicitly.
+template <typename R, typename OutputIt, typename UnaryPredicate>
+OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) {
+ return std::copy_if(adl_begin(Range), adl_end(Range), Out, P);
+}
+
+template <typename R, typename OutputIt>
+OutputIt copy(R &&Range, OutputIt Out) {
+ return std::copy(adl_begin(Range), adl_end(Range), Out);
+}
+
+/// Wrapper function around std::find to detect if an element exists
+/// in a container.
+template <typename R, typename E>
+bool is_contained(R &&Range, const E &Element) {
+ return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range);
+}
+
+/// Wrapper function around std::count to count the number of times an element
+/// \p Element occurs in the given range \p Range.
+template <typename R, typename E>
+auto count(R &&Range, const E &Element) ->
+ typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type {
+ return std::count(adl_begin(Range), adl_end(Range), Element);
+}
+
+/// Wrapper function around std::count_if to count the number of times an
+/// element satisfying a given predicate occurs in a range.
+template <typename R, typename UnaryPredicate>
+auto count_if(R &&Range, UnaryPredicate P) ->
+ typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type {
+ return std::count_if(adl_begin(Range), adl_end(Range), P);
+}
+
+/// Wrapper function around std::transform to apply a function to a range and
+/// store the result elsewhere.
+template <typename R, typename OutputIt, typename UnaryPredicate>
+OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P) {
+ return std::transform(adl_begin(Range), adl_end(Range), d_first, P);
+}
+
+/// Provide wrappers to std::partition which take ranges instead of having to
+/// pass begin/end explicitly.
+template <typename R, typename UnaryPredicate>
+auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
+ return std::partition(adl_begin(Range), adl_end(Range), P);
+}
+
+/// Provide wrappers to std::lower_bound which take ranges instead of having to
+/// pass begin/end explicitly.
+template <typename R, typename T>
+auto lower_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) {
+ return std::lower_bound(adl_begin(Range), adl_end(Range),
+ std::forward<T>(Value));
+}
+
+template <typename R, typename T, typename Compare>
+auto lower_bound(R &&Range, T &&Value, Compare C)
+ -> decltype(adl_begin(Range)) {
+ return std::lower_bound(adl_begin(Range), adl_end(Range),
+ std::forward<T>(Value), C);
+}
+
+/// Provide wrappers to std::upper_bound which take ranges instead of having to
+/// pass begin/end explicitly.
+template <typename R, typename T>
+auto upper_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) {
+ return std::upper_bound(adl_begin(Range), adl_end(Range),
+ std::forward<T>(Value));
+}
+
+template <typename R, typename T, typename Compare>
+auto upper_bound(R &&Range, T &&Value, Compare C)
+ -> decltype(adl_begin(Range)) {
+ return std::upper_bound(adl_begin(Range), adl_end(Range),
+ std::forward<T>(Value), C);
+}
+
+template <typename R>
+void stable_sort(R &&Range) {
+ std::stable_sort(adl_begin(Range), adl_end(Range));
+}
+
+template <typename R, typename Compare>
+void stable_sort(R &&Range, Compare C) {
+ std::stable_sort(adl_begin(Range), adl_end(Range), C);
+}
+
+/// Binary search for the first iterator in a range where a predicate is false.
+/// Requires that C is always true below some limit, and always false above it.
+template <typename R, typename Predicate,
+ typename Val = decltype(*adl_begin(std::declval<R>()))>
+auto partition_point(R &&Range, Predicate P) -> decltype(adl_begin(Range)) {
+ return std::partition_point(adl_begin(Range), adl_end(Range), P);
+}
+
+/// Wrapper function around std::equal to detect if all elements
+/// in a container are same.
+template <typename R>
+bool is_splat(R &&Range) {
+ size_t range_size = size(Range);
+ return range_size != 0 && (range_size == 1 ||
+ std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range)));
+}
+
+/// Given a range of type R, iterate the entire range and return a
+/// SmallVector with elements of the vector. This is useful, for example,
+/// when you want to iterate a range and then sort the results.
+template <unsigned Size, typename R>
+SmallVector<typename std::remove_const<detail::ValueOfRange<R>>::type, Size>
+to_vector(R &&Range) {
+ return {adl_begin(Range), adl_end(Range)};
+}
+
+/// Provide a container algorithm similar to C++ Library Fundamentals v2's
+/// `erase_if` which is equivalent to:
+///
+/// C.erase(remove_if(C, pred), C.end());
+///
+/// This version works for any container with an erase method call accepting
+/// two iterators.
+template <typename Container, typename UnaryPredicate>
+void erase_if(Container &C, UnaryPredicate P) {
+ C.erase(remove_if(C, P), C.end());
+}
+
+/// Given a sequence container Cont, replace the range [ContIt, ContEnd) with
+/// the range [ValIt, ValEnd) (which is not from the same container).
+template<typename Container, typename RandomAccessIterator>
+void replace(Container &Cont, typename Container::iterator ContIt,
+ typename Container::iterator ContEnd, RandomAccessIterator ValIt,
+ RandomAccessIterator ValEnd) {
+ while (true) {
+ if (ValIt == ValEnd) {
+ Cont.erase(ContIt, ContEnd);
+ return;
+ } else if (ContIt == ContEnd) {
+ Cont.insert(ContIt, ValIt, ValEnd);
+ return;
+ }
+ *ContIt++ = *ValIt++;
+ }
+}
+
+/// Given a sequence container Cont, replace the range [ContIt, ContEnd) with
+/// the range R.
+template<typename Container, typename Range = std::initializer_list<
+ typename Container::value_type>>
+void replace(Container &Cont, typename Container::iterator ContIt,
+ typename Container::iterator ContEnd, Range R) {
+ replace(Cont, ContIt, ContEnd, R.begin(), R.end());
+}
+
+//===----------------------------------------------------------------------===//
+// Extra additions to <memory>
+//===----------------------------------------------------------------------===//
+
+struct FreeDeleter {
+ void operator()(void* v) {
+ ::free(v);
+ }
+};
+
+template<typename First, typename Second>
+struct pair_hash {
+ size_t operator()(const std::pair<First, Second> &P) const {
+ return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second);
+ }
+};
+
+/// Binary functor that adapts to any other binary functor after dereferencing
+/// operands.
+template <typename T> struct deref {
+ T func;
+
+ // Could be further improved to cope with non-derivable functors and
+ // non-binary functors (should be a variadic template member function
+ // operator()).
+ template <typename A, typename B>
+ auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) {
+ assert(lhs);
+ assert(rhs);
+ return func(*lhs, *rhs);
+ }
+};
+
+namespace detail {
+
+template <typename R> class enumerator_iter;
+
+template <typename R> struct result_pair {
+ using value_reference =
+ typename std::iterator_traits<IterOfRange<R>>::reference;
+
+ friend class enumerator_iter<R>;
+
+ result_pair() = default;
+ result_pair(std::size_t Index, IterOfRange<R> Iter)
+ : Index(Index), Iter(Iter) {}
+
+ result_pair<R> &operator=(const result_pair<R> &Other) {
+ Index = Other.Index;
+ Iter = Other.Iter;
+ return *this;
+ }
+
+ std::size_t index() const { return Index; }
+ const value_reference value() const { return *Iter; }
+ value_reference value() { return *Iter; }
+
+private:
+ std::size_t Index = std::numeric_limits<std::size_t>::max();
+ IterOfRange<R> Iter;
+};
+
+template <typename R>
+class enumerator_iter
+ : public iterator_facade_base<
+ enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>,
+ typename std::iterator_traits<IterOfRange<R>>::difference_type,
+ typename std::iterator_traits<IterOfRange<R>>::pointer,
+ typename std::iterator_traits<IterOfRange<R>>::reference> {
+ using result_type = result_pair<R>;
+
+public:
+ explicit enumerator_iter(IterOfRange<R> EndIter)
+ : Result(std::numeric_limits<size_t>::max(), EndIter) {}
+
+ enumerator_iter(std::size_t Index, IterOfRange<R> Iter)
+ : Result(Index, Iter) {}
+
+ result_type &operator*() { return Result; }
+ const result_type &operator*() const { return Result; }
+
+ enumerator_iter<R> &operator++() {
+ assert(Result.Index != std::numeric_limits<size_t>::max());
+ ++Result.Iter;
+ ++Result.Index;
+ return *this;
+ }
+
+ bool operator==(const enumerator_iter<R> &RHS) const {
+ // Don't compare indices here, only iterators. It's possible for an end
+ // iterator to have different indices depending on whether it was created
+ // by calling std::end() versus incrementing a valid iterator.
+ return Result.Iter == RHS.Result.Iter;
+ }
+
+ enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) {
+ Result = Other.Result;
+ return *this;
+ }
+
+private:
+ result_type Result;
+};
+
+template <typename R> class enumerator {
+public:
+ explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {}
+
+ enumerator_iter<R> begin() {
+ return enumerator_iter<R>(0, std::begin(TheRange));
+ }
+
+ enumerator_iter<R> end() {
+ return enumerator_iter<R>(std::end(TheRange));
+ }
+
+private:
+ R TheRange;
+};
+
+} // end namespace detail
+
+/// Given an input range, returns a new range whose values are are pair (A,B)
+/// such that A is the 0-based index of the item in the sequence, and B is
+/// the value from the original sequence. Example:
+///
+/// std::vector<char> Items = {'A', 'B', 'C', 'D'};
+/// for (auto X : enumerate(Items)) {
+/// printf("Item %d - %c\n", X.index(), X.value());
+/// }
+///
+/// Output:
+/// Item 0 - A
+/// Item 1 - B
+/// Item 2 - C
+/// Item 3 - D
+///
+template <typename R> detail::enumerator<R> enumerate(R &&TheRange) {
+ return detail::enumerator<R>(std::forward<R>(TheRange));
+}
+
+namespace detail {
+
+template <typename F, typename Tuple, std::size_t... I>
+auto apply_tuple_impl(F &&f, Tuple &&t, std::index_sequence<I...>)
+ -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...)) {
+ return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
+}
+
+} // end namespace detail
+
+/// Given an input tuple (a1, a2, ..., an), pass the arguments of the
+/// tuple variadically to f as if by calling f(a1, a2, ..., an) and
+/// return the result.
+template <typename F, typename Tuple>
+auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl(
+ std::forward<F>(f), std::forward<Tuple>(t),
+ std::make_index_sequence<
+ std::tuple_size<typename std::decay<Tuple>::type>::value>{})) {
+ using Indices = std::make_index_sequence<
+ std::tuple_size<typename std::decay<Tuple>::type>::value>;
+
+ return detail::apply_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t),
+ Indices{});
+}
+
+/// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N)
+/// time. Not meant for use with random-access iterators.
+template <typename IterTy>
+bool hasNItems(
+ IterTy &&Begin, IterTy &&End, unsigned N,
+ typename std::enable_if<
+ !std::is_same<
+ typename std::iterator_traits<typename std::remove_reference<
+ decltype(Begin)>::type>::iterator_category,
+ std::random_access_iterator_tag>::value,
+ void>::type * = nullptr) {
+ for (; N; --N, ++Begin)
+ if (Begin == End)
+ return false; // Too few.
+ return Begin == End;
+}
+
+/// Return true if the sequence [Begin, End) has N or more items. Runs in O(N)
+/// time. Not meant for use with random-access iterators.
+template <typename IterTy>
+bool hasNItemsOrMore(
+ IterTy &&Begin, IterTy &&End, unsigned N,
+ typename std::enable_if<
+ !std::is_same<
+ typename std::iterator_traits<typename std::remove_reference<
+ decltype(Begin)>::type>::iterator_category,
+ std::random_access_iterator_tag>::value,
+ void>::type * = nullptr) {
+ for (; N; --N, ++Begin)
+ if (Begin == End)
+ return false; // Too few.
+ return true;
+}
+
+/// Returns a raw pointer that represents the same address as the argument.
+///
+/// The late bound return should be removed once we move to C++14 to better
+/// align with the C++20 declaration. Also, this implementation can be removed
+/// once we move to C++20 where it's defined as std::to_addres()
+///
+/// The std::pointer_traits<>::to_address(p) variations of these overloads has
+/// not been implemented.
+template <class Ptr> auto to_address(const Ptr &P) -> decltype(P.operator->()) {
+ return P.operator->();
+}
+template <class T> constexpr T *to_address(T *P) { return P; }
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_STLEXTRAS_H
diff --git a/third_party/llvm-project/include/llvm/ADT/SmallPtrSet.h b/third_party/llvm-project/include/llvm/ADT/SmallPtrSet.h
new file mode 100644
index 000000000..1d8280063
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/SmallPtrSet.h
@@ -0,0 +1,511 @@
+//===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SmallPtrSet class. See the doxygen comment for
+// SmallPtrSetImplBase for more details on the algorithm used.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SMALLPTRSET_H
+#define LLVM_ADT_SMALLPTRSET_H
+
+#include "llvm/ADT/EpochTracker.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ReverseIteration.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <initializer_list>
+#include <iterator>
+#include <utility>
+
+namespace llvm {
+
+/// SmallPtrSetImplBase - This is the common code shared among all the
+/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one
+/// for small and one for large sets.
+///
+/// Small sets use an array of pointers allocated in the SmallPtrSet object,
+/// which is treated as a simple array of pointers. When a pointer is added to
+/// the set, the array is scanned to see if the element already exists, if not
+/// the element is 'pushed back' onto the array. If we run out of space in the
+/// array, we grow into the 'large set' case. SmallSet should be used when the
+/// sets are often small. In this case, no memory allocation is used, and only
+/// light-weight and cache-efficient scanning is used.
+///
+/// Large sets use a classic exponentially-probed hash table. Empty buckets are
+/// represented with an illegal pointer value (-1) to allow null pointers to be
+/// inserted. Tombstones are represented with another illegal pointer value
+/// (-2), to allow deletion. The hash table is resized when the table is 3/4 or
+/// more. When this happens, the table is doubled in size.
+///
+class SmallPtrSetImplBase : public DebugEpochBase {
+ friend class SmallPtrSetIteratorImpl;
+
+protected:
+ /// SmallArray - Points to a fixed size set of buckets, used in 'small mode'.
+ const void **SmallArray;
+ /// CurArray - This is the current set of buckets. If equal to SmallArray,
+ /// then the set is in 'small mode'.
+ const void **CurArray;
+ /// CurArraySize - The allocated size of CurArray, always a power of two.
+ unsigned CurArraySize;
+
+ /// Number of elements in CurArray that contain a value or are a tombstone.
+ /// If small, all these elements are at the beginning of CurArray and the rest
+ /// is uninitialized.
+ unsigned NumNonEmpty;
+ /// Number of tombstones in CurArray.
+ unsigned NumTombstones;
+
+ // Helpers to copy and move construct a SmallPtrSet.
+ SmallPtrSetImplBase(const void **SmallStorage,
+ const SmallPtrSetImplBase &that);
+ SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize,
+ SmallPtrSetImplBase &&that);
+
+ explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize)
+ : SmallArray(SmallStorage), CurArray(SmallStorage),
+ CurArraySize(SmallSize), NumNonEmpty(0), NumTombstones(0) {
+ assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
+ "Initial size must be a power of two!");
+ }
+
+ ~SmallPtrSetImplBase() {
+ if (!isSmall())
+ free(CurArray);
+ }
+
+public:
+ using size_type = unsigned;
+
+ SmallPtrSetImplBase &operator=(const SmallPtrSetImplBase &) = delete;
+
+ LLVM_NODISCARD bool empty() const { return size() == 0; }
+ size_type size() const { return NumNonEmpty - NumTombstones; }
+
+ void clear() {
+ incrementEpoch();
+ // If the capacity of the array is huge, and the # elements used is small,
+ // shrink the array.
+ if (!isSmall()) {
+ if (size() * 4 < CurArraySize && CurArraySize > 32)
+ return shrink_and_clear();
+ // Fill the array with empty markers.
+ memset(CurArray, -1, CurArraySize * sizeof(void *));
+ }
+
+ NumNonEmpty = 0;
+ NumTombstones = 0;
+ }
+
+protected:
+ static void *getTombstoneMarker() { return reinterpret_cast<void*>(-2); }
+
+ static void *getEmptyMarker() {
+ // Note that -1 is chosen to make clear() efficiently implementable with
+ // memset and because it's not a valid pointer value.
+ return reinterpret_cast<void*>(-1);
+ }
+
+ const void **EndPointer() const {
+ return isSmall() ? CurArray + NumNonEmpty : CurArray + CurArraySize;
+ }
+
+ /// insert_imp - This returns true if the pointer was new to the set, false if
+ /// it was already in the set. This is hidden from the client so that the
+ /// derived class can check that the right type of pointer is passed in.
+ std::pair<const void *const *, bool> insert_imp(const void *Ptr) {
+ if (isSmall()) {
+ // Check to see if it is already in the set.
+ const void **LastTombstone = nullptr;
+ for (const void **APtr = SmallArray, **E = SmallArray + NumNonEmpty;
+ APtr != E; ++APtr) {
+ const void *Value = *APtr;
+ if (Value == Ptr)
+ return std::make_pair(APtr, false);
+ if (Value == getTombstoneMarker())
+ LastTombstone = APtr;
+ }
+
+ // Did we find any tombstone marker?
+ if (LastTombstone != nullptr) {
+ *LastTombstone = Ptr;
+ --NumTombstones;
+ incrementEpoch();
+ return std::make_pair(LastTombstone, true);
+ }
+
+ // Nope, there isn't. If we stay small, just 'pushback' now.
+ if (NumNonEmpty < CurArraySize) {
+ SmallArray[NumNonEmpty++] = Ptr;
+ incrementEpoch();
+ return std::make_pair(SmallArray + (NumNonEmpty - 1), true);
+ }
+ // Otherwise, hit the big set case, which will call grow.
+ }
+ return insert_imp_big(Ptr);
+ }
+
+ /// erase_imp - If the set contains the specified pointer, remove it and
+ /// return true, otherwise return false. This is hidden from the client so
+ /// that the derived class can check that the right type of pointer is passed
+ /// in.
+ bool erase_imp(const void * Ptr) {
+ const void *const *P = find_imp(Ptr);
+ if (P == EndPointer())
+ return false;
+
+ const void **Loc = const_cast<const void **>(P);
+ assert(*Loc == Ptr && "broken find!");
+ *Loc = getTombstoneMarker();
+ NumTombstones++;
+ return true;
+ }
+
+ /// Returns the raw pointer needed to construct an iterator. If element not
+ /// found, this will be EndPointer. Otherwise, it will be a pointer to the
+ /// slot which stores Ptr;
+ const void *const * find_imp(const void * Ptr) const {
+ if (isSmall()) {
+ // Linear search for the item.
+ for (const void *const *APtr = SmallArray,
+ *const *E = SmallArray + NumNonEmpty; APtr != E; ++APtr)
+ if (*APtr == Ptr)
+ return APtr;
+ return EndPointer();
+ }
+
+ // Big set case.
+ auto *Bucket = FindBucketFor(Ptr);
+ if (*Bucket == Ptr)
+ return Bucket;
+ return EndPointer();
+ }
+
+private:
+ bool isSmall() const { return CurArray == SmallArray; }
+
+ std::pair<const void *const *, bool> insert_imp_big(const void *Ptr);
+
+ const void * const *FindBucketFor(const void *Ptr) const;
+ void shrink_and_clear();
+
+ /// Grow - Allocate a larger backing store for the buckets and move it over.
+ void Grow(unsigned NewSize);
+
+protected:
+ /// swap - Swaps the elements of two sets.
+ /// Note: This method assumes that both sets have the same small size.
+ void swap(SmallPtrSetImplBase &RHS);
+
+ void CopyFrom(const SmallPtrSetImplBase &RHS);
+ void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS);
+
+private:
+ /// Code shared by MoveFrom() and move constructor.
+ void MoveHelper(unsigned SmallSize, SmallPtrSetImplBase &&RHS);
+ /// Code shared by CopyFrom() and copy constructor.
+ void CopyHelper(const SmallPtrSetImplBase &RHS);
+};
+
+/// SmallPtrSetIteratorImpl - This is the common base class shared between all
+/// instances of SmallPtrSetIterator.
+class SmallPtrSetIteratorImpl {
+protected:
+ const void *const *Bucket;
+ const void *const *End;
+
+public:
+ explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E)
+ : Bucket(BP), End(E) {
+ if (shouldReverseIterate()) {
+ RetreatIfNotValid();
+ return;
+ }
+ AdvanceIfNotValid();
+ }
+
+ bool operator==(const SmallPtrSetIteratorImpl &RHS) const {
+ return Bucket == RHS.Bucket;
+ }
+ bool operator!=(const SmallPtrSetIteratorImpl &RHS) const {
+ return Bucket != RHS.Bucket;
+ }
+
+protected:
+ /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket
+ /// that is. This is guaranteed to stop because the end() bucket is marked
+ /// valid.
+ void AdvanceIfNotValid() {
+ assert(Bucket <= End);
+ while (Bucket != End &&
+ (*Bucket == SmallPtrSetImplBase::getEmptyMarker() ||
+ *Bucket == SmallPtrSetImplBase::getTombstoneMarker()))
+ ++Bucket;
+ }
+ void RetreatIfNotValid() {
+ assert(Bucket >= End);
+ while (Bucket != End &&
+ (Bucket[-1] == SmallPtrSetImplBase::getEmptyMarker() ||
+ Bucket[-1] == SmallPtrSetImplBase::getTombstoneMarker())) {
+ --Bucket;
+ }
+ }
+};
+
+/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
+template <typename PtrTy>
+class SmallPtrSetIterator : public SmallPtrSetIteratorImpl,
+ DebugEpochBase::HandleBase {
+ using PtrTraits = PointerLikeTypeTraits<PtrTy>;
+
+public:
+ using value_type = PtrTy;
+ using reference = PtrTy;
+ using pointer = PtrTy;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::forward_iterator_tag;
+
+ explicit SmallPtrSetIterator(const void *const *BP, const void *const *E,
+ const DebugEpochBase &Epoch)
+ : SmallPtrSetIteratorImpl(BP, E), DebugEpochBase::HandleBase(&Epoch) {}
+
+ // Most methods provided by baseclass.
+
+ const PtrTy operator*() const {
+ assert(isHandleInSync() && "invalid iterator access!");
+ if (shouldReverseIterate()) {
+ assert(Bucket > End);
+ return PtrTraits::getFromVoidPointer(const_cast<void *>(Bucket[-1]));
+ }
+ assert(Bucket < End);
+ return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket));
+ }
+
+ inline SmallPtrSetIterator& operator++() { // Preincrement
+ assert(isHandleInSync() && "invalid iterator access!");
+ if (shouldReverseIterate()) {
+ --Bucket;
+ RetreatIfNotValid();
+ return *this;
+ }
+ ++Bucket;
+ AdvanceIfNotValid();
+ return *this;
+ }
+
+ SmallPtrSetIterator operator++(int) { // Postincrement
+ SmallPtrSetIterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+};
+
+/// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next
+/// power of two (which means N itself if N is already a power of two).
+template<unsigned N>
+struct RoundUpToPowerOfTwo;
+
+/// RoundUpToPowerOfTwoH - If N is not a power of two, increase it. This is a
+/// helper template used to implement RoundUpToPowerOfTwo.
+template<unsigned N, bool isPowerTwo>
+struct RoundUpToPowerOfTwoH {
+ enum { Val = N };
+};
+template<unsigned N>
+struct RoundUpToPowerOfTwoH<N, false> {
+ enum {
+ // We could just use NextVal = N+1, but this converges faster. N|(N-1) sets
+ // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111.
+ Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val
+ };
+};
+
+template<unsigned N>
+struct RoundUpToPowerOfTwo {
+ enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
+};
+
+/// A templated base class for \c SmallPtrSet which provides the
+/// typesafe interface that is common across all small sizes.
+///
+/// This is particularly useful for passing around between interface boundaries
+/// to avoid encoding a particular small size in the interface boundary.
+template <typename PtrType>
+class SmallPtrSetImpl : public SmallPtrSetImplBase {
+ using ConstPtrType = typename add_const_past_pointer<PtrType>::type;
+ using PtrTraits = PointerLikeTypeTraits<PtrType>;
+ using ConstPtrTraits = PointerLikeTypeTraits<ConstPtrType>;
+
+protected:
+ // Constructors that forward to the base.
+ SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that)
+ : SmallPtrSetImplBase(SmallStorage, that) {}
+ SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize,
+ SmallPtrSetImpl &&that)
+ : SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {}
+ explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize)
+ : SmallPtrSetImplBase(SmallStorage, SmallSize) {}
+
+public:
+ using iterator = SmallPtrSetIterator<PtrType>;
+ using const_iterator = SmallPtrSetIterator<PtrType>;
+ using key_type = ConstPtrType;
+ using value_type = PtrType;
+
+ SmallPtrSetImpl(const SmallPtrSetImpl &) = delete;
+
+ /// Inserts Ptr if and only if there is no element in the container equal to
+ /// Ptr. The bool component of the returned pair is true if and only if the
+ /// insertion takes place, and the iterator component of the pair points to
+ /// the element equal to Ptr.
+ std::pair<iterator, bool> insert(PtrType Ptr) {
+ auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr));
+ return std::make_pair(makeIterator(p.first), p.second);
+ }
+
+ /// erase - If the set contains the specified pointer, remove it and return
+ /// true, otherwise return false.
+ bool erase(PtrType Ptr) {
+ return erase_imp(PtrTraits::getAsVoidPointer(Ptr));
+ }
+ /// count - Return 1 if the specified pointer is in the set, 0 otherwise.
+ size_type count(ConstPtrType Ptr) const { return find(Ptr) != end() ? 1 : 0; }
+ iterator find(ConstPtrType Ptr) const {
+ return makeIterator(find_imp(ConstPtrTraits::getAsVoidPointer(Ptr)));
+ }
+
+ template <typename IterT>
+ void insert(IterT I, IterT E) {
+ for (; I != E; ++I)
+ insert(*I);
+ }
+
+ void insert(std::initializer_list<PtrType> IL) {
+ insert(IL.begin(), IL.end());
+ }
+
+ iterator begin() const {
+ if (shouldReverseIterate())
+ return makeIterator(EndPointer() - 1);
+ return makeIterator(CurArray);
+ }
+ iterator end() const { return makeIterator(EndPointer()); }
+
+private:
+ /// Create an iterator that dereferences to same place as the given pointer.
+ iterator makeIterator(const void *const *P) const {
+ if (shouldReverseIterate())
+ return iterator(P == EndPointer() ? CurArray : P + 1, CurArray, *this);
+ return iterator(P, EndPointer(), *this);
+ }
+};
+
+/// Equality comparison for SmallPtrSet.
+///
+/// Iterates over elements of LHS confirming that each value from LHS is also in
+/// RHS, and that no additional values are in RHS.
+template <typename PtrType>
+bool operator==(const SmallPtrSetImpl<PtrType> &LHS,
+ const SmallPtrSetImpl<PtrType> &RHS) {
+ if (LHS.size() != RHS.size())
+ return false;
+
+ for (const auto *KV : LHS)
+ if (!RHS.count(KV))
+ return false;
+
+ return true;
+}
+
+/// Inequality comparison for SmallPtrSet.
+///
+/// Equivalent to !(LHS == RHS).
+template <typename PtrType>
+bool operator!=(const SmallPtrSetImpl<PtrType> &LHS,
+ const SmallPtrSetImpl<PtrType> &RHS) {
+ return !(LHS == RHS);
+}
+
+/// SmallPtrSet - This class implements a set which is optimized for holding
+/// SmallSize or less elements. This internally rounds up SmallSize to the next
+/// power of two if it is not already a power of two. See the comments above
+/// SmallPtrSetImplBase for details of the algorithm.
+template<class PtrType, unsigned SmallSize>
+class SmallPtrSet : public SmallPtrSetImpl<PtrType> {
+ // In small mode SmallPtrSet uses linear search for the elements, so it is
+ // not a good idea to choose this value too high. You may consider using a
+ // DenseSet<> instead if you expect many elements in the set.
+ static_assert(SmallSize <= 32, "SmallSize should be small");
+
+ using BaseT = SmallPtrSetImpl<PtrType>;
+
+ // Make sure that SmallSize is a power of two, round up if not.
+ enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val };
+ /// SmallStorage - Fixed size storage used in 'small mode'.
+ const void *SmallStorage[SmallSizePowTwo];
+
+public:
+ SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {}
+ SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {}
+ SmallPtrSet(SmallPtrSet &&that)
+ : BaseT(SmallStorage, SmallSizePowTwo, std::move(that)) {}
+
+ template<typename It>
+ SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) {
+ this->insert(I, E);
+ }
+
+ SmallPtrSet(std::initializer_list<PtrType> IL)
+ : BaseT(SmallStorage, SmallSizePowTwo) {
+ this->insert(IL.begin(), IL.end());
+ }
+
+ SmallPtrSet<PtrType, SmallSize> &
+ operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) {
+ if (&RHS != this)
+ this->CopyFrom(RHS);
+ return *this;
+ }
+
+ SmallPtrSet<PtrType, SmallSize> &
+ operator=(SmallPtrSet<PtrType, SmallSize> &&RHS) {
+ if (&RHS != this)
+ this->MoveFrom(SmallSizePowTwo, std::move(RHS));
+ return *this;
+ }
+
+ SmallPtrSet<PtrType, SmallSize> &
+ operator=(std::initializer_list<PtrType> IL) {
+ this->clear();
+ this->insert(IL.begin(), IL.end());
+ return *this;
+ }
+
+ /// swap - Swaps the elements of two sets.
+ void swap(SmallPtrSet<PtrType, SmallSize> &RHS) {
+ SmallPtrSetImplBase::swap(RHS);
+ }
+};
+
+} // end namespace llvm
+
+namespace std {
+
+ /// Implement std::swap in terms of SmallPtrSet swap.
+ template<class T, unsigned N>
+ inline void swap(llvm::SmallPtrSet<T, N> &LHS, llvm::SmallPtrSet<T, N> &RHS) {
+ LHS.swap(RHS);
+ }
+
+} // end namespace std
+
+#endif // LLVM_ADT_SMALLPTRSET_H
diff --git a/third_party/llvm-project/include/llvm/ADT/SmallSet.h b/third_party/llvm-project/include/llvm/ADT/SmallSet.h
new file mode 100644
index 000000000..a03fa7dd8
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/SmallSet.h
@@ -0,0 +1,278 @@
+//===- llvm/ADT/SmallSet.h - 'Normally small' sets --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SmallSet class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SMALLSET_H
+#define LLVM_ADT_SMALLSET_H
+
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/type_traits.h"
+#include <cstddef>
+#include <functional>
+#include <set>
+#include <type_traits>
+#include <utility>
+
+namespace llvm {
+
+/// SmallSetIterator - This class implements a const_iterator for SmallSet by
+/// delegating to the underlying SmallVector or Set iterators.
+template <typename T, unsigned N, typename C>
+class SmallSetIterator
+ : public iterator_facade_base<SmallSetIterator<T, N, C>,
+ std::forward_iterator_tag, T> {
+private:
+ using SetIterTy = typename std::set<T, C>::const_iterator;
+ using VecIterTy = typename SmallVector<T, N>::const_iterator;
+ using SelfTy = SmallSetIterator<T, N, C>;
+
+ /// Iterators to the parts of the SmallSet containing the data. They are set
+ /// depending on isSmall.
+ union {
+ SetIterTy SetIter;
+ VecIterTy VecIter;
+ };
+
+ bool isSmall;
+
+public:
+ SmallSetIterator(SetIterTy SetIter) : SetIter(SetIter), isSmall(false) {}
+
+ SmallSetIterator(VecIterTy VecIter) : VecIter(VecIter), isSmall(true) {}
+
+ // Spell out destructor, copy/move constructor and assignment operators for
+ // MSVC STL, where set<T>::const_iterator is not trivially copy constructible.
+ ~SmallSetIterator() {
+ if (isSmall)
+ VecIter.~VecIterTy();
+ else
+ SetIter.~SetIterTy();
+ }
+
+ SmallSetIterator(const SmallSetIterator &Other) : isSmall(Other.isSmall) {
+ if (isSmall)
+ VecIter = Other.VecIter;
+ else
+ // Use placement new, to make sure SetIter is properly constructed, even
+ // if it is not trivially copy-able (e.g. in MSVC).
+ new (&SetIter) SetIterTy(Other.SetIter);
+ }
+
+ SmallSetIterator(SmallSetIterator &&Other) : isSmall(Other.isSmall) {
+ if (isSmall)
+ VecIter = std::move(Other.VecIter);
+ else
+ // Use placement new, to make sure SetIter is properly constructed, even
+ // if it is not trivially copy-able (e.g. in MSVC).
+ new (&SetIter) SetIterTy(std::move(Other.SetIter));
+ }
+
+ SmallSetIterator& operator=(const SmallSetIterator& Other) {
+ // Call destructor for SetIter, so it gets properly destroyed if it is
+ // not trivially destructible in case we are setting VecIter.
+ if (!isSmall)
+ SetIter.~SetIterTy();
+
+ isSmall = Other.isSmall;
+ if (isSmall)
+ VecIter = Other.VecIter;
+ else
+ new (&SetIter) SetIterTy(Other.SetIter);
+ return *this;
+ }
+
+ SmallSetIterator& operator=(SmallSetIterator&& Other) {
+ // Call destructor for SetIter, so it gets properly destroyed if it is
+ // not trivially destructible in case we are setting VecIter.
+ if (!isSmall)
+ SetIter.~SetIterTy();
+
+ isSmall = Other.isSmall;
+ if (isSmall)
+ VecIter = std::move(Other.VecIter);
+ else
+ new (&SetIter) SetIterTy(std::move(Other.SetIter));
+ return *this;
+ }
+
+ bool operator==(const SmallSetIterator &RHS) const {
+ if (isSmall != RHS.isSmall)
+ return false;
+ if (isSmall)
+ return VecIter == RHS.VecIter;
+ return SetIter == RHS.SetIter;
+ }
+
+ SmallSetIterator &operator++() { // Preincrement
+ if (isSmall)
+ VecIter++;
+ else
+ SetIter++;
+ return *this;
+ }
+
+ const T &operator*() const { return isSmall ? *VecIter : *SetIter; }
+};
+
+/// SmallSet - This maintains a set of unique values, optimizing for the case
+/// when the set is small (less than N). In this case, the set can be
+/// maintained with no mallocs. If the set gets large, we expand to using an
+/// std::set to maintain reasonable lookup times.
+template <typename T, unsigned N, typename C = std::less<T>>
+class SmallSet {
+ /// Use a SmallVector to hold the elements here (even though it will never
+ /// reach its 'large' stage) to avoid calling the default ctors of elements
+ /// we will never use.
+ SmallVector<T, N> Vector;
+ std::set<T, C> Set;
+
+ using VIterator = typename SmallVector<T, N>::const_iterator;
+ using mutable_iterator = typename SmallVector<T, N>::iterator;
+
+ // In small mode SmallPtrSet uses linear search for the elements, so it is
+ // not a good idea to choose this value too high. You may consider using a
+ // DenseSet<> instead if you expect many elements in the set.
+ static_assert(N <= 32, "N should be small");
+
+public:
+ using size_type = size_t;
+ using const_iterator = SmallSetIterator<T, N, C>;
+
+ SmallSet() = default;
+
+ LLVM_NODISCARD bool empty() const {
+ return Vector.empty() && Set.empty();
+ }
+
+ size_type size() const {
+ return isSmall() ? Vector.size() : Set.size();
+ }
+
+ /// count - Return 1 if the element is in the set, 0 otherwise.
+ size_type count(const T &V) const {
+ if (isSmall()) {
+ // Since the collection is small, just do a linear search.
+ return vfind(V) == Vector.end() ? 0 : 1;
+ } else {
+ return Set.count(V);
+ }
+ }
+
+ /// insert - Insert an element into the set if it isn't already there.
+ /// Returns true if the element is inserted (it was not in the set before).
+ /// The first value of the returned pair is unused and provided for
+ /// partial compatibility with the standard library self-associative container
+ /// concept.
+ // FIXME: Add iterators that abstract over the small and large form, and then
+ // return those here.
+ std::pair<NoneType, bool> insert(const T &V) {
+ if (!isSmall())
+ return std::make_pair(None, Set.insert(V).second);
+
+ VIterator I = vfind(V);
+ if (I != Vector.end()) // Don't reinsert if it already exists.
+ return std::make_pair(None, false);
+ if (Vector.size() < N) {
+ Vector.push_back(V);
+ return std::make_pair(None, true);
+ }
+
+ // Otherwise, grow from vector to set.
+ while (!Vector.empty()) {
+ Set.insert(Vector.back());
+ Vector.pop_back();
+ }
+ Set.insert(V);
+ return std::make_pair(None, true);
+ }
+
+ template <typename IterT>
+ void insert(IterT I, IterT E) {
+ for (; I != E; ++I)
+ insert(*I);
+ }
+
+ bool erase(const T &V) {
+ if (!isSmall())
+ return Set.erase(V);
+ for (mutable_iterator I = Vector.begin(), E = Vector.end(); I != E; ++I)
+ if (*I == V) {
+ Vector.erase(I);
+ return true;
+ }
+ return false;
+ }
+
+ void clear() {
+ Vector.clear();
+ Set.clear();
+ }
+
+ const_iterator begin() const {
+ if (isSmall())
+ return {Vector.begin()};
+ return {Set.begin()};
+ }
+
+ const_iterator end() const {
+ if (isSmall())
+ return {Vector.end()};
+ return {Set.end()};
+ }
+
+private:
+ bool isSmall() const { return Set.empty(); }
+
+ VIterator vfind(const T &V) const {
+ for (VIterator I = Vector.begin(), E = Vector.end(); I != E; ++I)
+ if (*I == V)
+ return I;
+ return Vector.end();
+ }
+};
+
+/// If this set is of pointer values, transparently switch over to using
+/// SmallPtrSet for performance.
+template <typename PointeeType, unsigned N>
+class SmallSet<PointeeType*, N> : public SmallPtrSet<PointeeType*, N> {};
+
+/// Equality comparison for SmallSet.
+///
+/// Iterates over elements of LHS confirming that each element is also a member
+/// of RHS, and that RHS contains no additional values.
+/// Equivalent to N calls to RHS.count.
+/// For small-set mode amortized complexity is O(N^2)
+/// For large-set mode amortized complexity is linear, worst case is O(N^2) (if
+/// every hash collides).
+template <typename T, unsigned LN, unsigned RN, typename C>
+bool operator==(const SmallSet<T, LN, C> &LHS, const SmallSet<T, RN, C> &RHS) {
+ if (LHS.size() != RHS.size())
+ return false;
+
+ // All elements in LHS must also be in RHS
+ return all_of(LHS, [&RHS](const T &E) { return RHS.count(E); });
+}
+
+/// Inequality comparison for SmallSet.
+///
+/// Equivalent to !(LHS == RHS). See operator== for performance notes.
+template <typename T, unsigned LN, unsigned RN, typename C>
+bool operator!=(const SmallSet<T, LN, C> &LHS, const SmallSet<T, RN, C> &RHS) {
+ return !(LHS == RHS);
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_SMALLSET_H
diff --git a/third_party/llvm-project/include/llvm/ADT/SmallString.h b/third_party/llvm-project/include/llvm/ADT/SmallString.h
new file mode 100644
index 000000000..898be80d0
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/SmallString.h
@@ -0,0 +1,296 @@
+//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SmallString class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SMALLSTRING_H
+#define LLVM_ADT_SMALLSTRING_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <cstddef>
+
+namespace llvm {
+
+/// SmallString - A SmallString is just a SmallVector with methods and accessors
+/// that make it work better as a string (e.g. operator+ etc).
+template<unsigned InternalLen>
+class SmallString : public SmallVector<char, InternalLen> {
+public:
+ /// Default ctor - Initialize to empty.
+ SmallString() = default;
+
+ /// Initialize from a StringRef.
+ SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {}
+
+ /// Initialize with a range.
+ template<typename ItTy>
+ SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {}
+
+ // Note that in order to add new overloads for append & assign, we have to
+ // duplicate the inherited versions so as not to inadvertently hide them.
+
+ /// @}
+ /// @name String Assignment
+ /// @{
+
+ /// Assign from a repeated element.
+ void assign(size_t NumElts, char Elt) {
+ this->SmallVectorImpl<char>::assign(NumElts, Elt);
+ }
+
+ /// Assign from an iterator pair.
+ template<typename in_iter>
+ void assign(in_iter S, in_iter E) {
+ this->clear();
+ SmallVectorImpl<char>::append(S, E);
+ }
+
+ /// Assign from a StringRef.
+ void assign(StringRef RHS) {
+ this->clear();
+ SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
+ }
+
+ /// Assign from a SmallVector.
+ void assign(const SmallVectorImpl<char> &RHS) {
+ this->clear();
+ SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
+ }
+
+ /// @}
+ /// @name String Concatenation
+ /// @{
+
+ /// Append from an iterator pair.
+ template<typename in_iter>
+ void append(in_iter S, in_iter E) {
+ SmallVectorImpl<char>::append(S, E);
+ }
+
+ void append(size_t NumInputs, char Elt) {
+ SmallVectorImpl<char>::append(NumInputs, Elt);
+ }
+
+ /// Append from a StringRef.
+ void append(StringRef RHS) {
+ SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
+ }
+
+ /// Append from a SmallVector.
+ void append(const SmallVectorImpl<char> &RHS) {
+ SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
+ }
+
+ /// @}
+ /// @name String Comparison
+ /// @{
+
+ /// Check for string equality. This is more efficient than compare() when
+ /// the relative ordering of inequal strings isn't needed.
+ bool equals(StringRef RHS) const {
+ return str().equals(RHS);
+ }
+
+ /// Check for string equality, ignoring case.
+ bool equals_lower(StringRef RHS) const {
+ return str().equals_lower(RHS);
+ }
+
+ /// Compare two strings; the result is -1, 0, or 1 if this string is
+ /// lexicographically less than, equal to, or greater than the \p RHS.
+ int compare(StringRef RHS) const {
+ return str().compare(RHS);
+ }
+
+ /// compare_lower - Compare two strings, ignoring case.
+ int compare_lower(StringRef RHS) const {
+ return str().compare_lower(RHS);
+ }
+
+ /// compare_numeric - Compare two strings, treating sequences of digits as
+ /// numbers.
+ int compare_numeric(StringRef RHS) const {
+ return str().compare_numeric(RHS);
+ }
+
+ /// @}
+ /// @name String Predicates
+ /// @{
+
+ /// startswith - Check if this string starts with the given \p Prefix.
+ bool startswith(StringRef Prefix) const {
+ return str().startswith(Prefix);
+ }
+
+ /// endswith - Check if this string ends with the given \p Suffix.
+ bool endswith(StringRef Suffix) const {
+ return str().endswith(Suffix);
+ }
+
+ /// @}
+ /// @name String Searching
+ /// @{
+
+ /// find - Search for the first character \p C in the string.
+ ///
+ /// \return - The index of the first occurrence of \p C, or npos if not
+ /// found.
+ size_t find(char C, size_t From = 0) const {
+ return str().find(C, From);
+ }
+
+ /// Search for the first string \p Str in the string.
+ ///
+ /// \returns The index of the first occurrence of \p Str, or npos if not
+ /// found.
+ size_t find(StringRef Str, size_t From = 0) const {
+ return str().find(Str, From);
+ }
+
+ /// Search for the last character \p C in the string.
+ ///
+ /// \returns The index of the last occurrence of \p C, or npos if not
+ /// found.
+ size_t rfind(char C, size_t From = StringRef::npos) const {
+ return str().rfind(C, From);
+ }
+
+ /// Search for the last string \p Str in the string.
+ ///
+ /// \returns The index of the last occurrence of \p Str, or npos if not
+ /// found.
+ size_t rfind(StringRef Str) const {
+ return str().rfind(Str);
+ }
+
+ /// Find the first character in the string that is \p C, or npos if not
+ /// found. Same as find.
+ size_t find_first_of(char C, size_t From = 0) const {
+ return str().find_first_of(C, From);
+ }
+
+ /// Find the first character in the string that is in \p Chars, or npos if
+ /// not found.
+ ///
+ /// Complexity: O(size() + Chars.size())
+ size_t find_first_of(StringRef Chars, size_t From = 0) const {
+ return str().find_first_of(Chars, From);
+ }
+
+ /// Find the first character in the string that is not \p C or npos if not
+ /// found.
+ size_t find_first_not_of(char C, size_t From = 0) const {
+ return str().find_first_not_of(C, From);
+ }
+
+ /// Find the first character in the string that is not in the string
+ /// \p Chars, or npos if not found.
+ ///
+ /// Complexity: O(size() + Chars.size())
+ size_t find_first_not_of(StringRef Chars, size_t From = 0) const {
+ return str().find_first_not_of(Chars, From);
+ }
+
+ /// Find the last character in the string that is \p C, or npos if not
+ /// found.
+ size_t find_last_of(char C, size_t From = StringRef::npos) const {
+ return str().find_last_of(C, From);
+ }
+
+ /// Find the last character in the string that is in \p C, or npos if not
+ /// found.
+ ///
+ /// Complexity: O(size() + Chars.size())
+ size_t find_last_of(
+ StringRef Chars, size_t From = StringRef::npos) const {
+ return str().find_last_of(Chars, From);
+ }
+
+ /// @}
+ /// @name Helpful Algorithms
+ /// @{
+
+ /// Return the number of occurrences of \p C in the string.
+ size_t count(char C) const {
+ return str().count(C);
+ }
+
+ /// Return the number of non-overlapped occurrences of \p Str in the
+ /// string.
+ size_t count(StringRef Str) const {
+ return str().count(Str);
+ }
+
+ /// @}
+ /// @name Substring Operations
+ /// @{
+
+ /// Return a reference to the substring from [Start, Start + N).
+ ///
+ /// \param Start The index of the starting character in the substring; if
+ /// the index is npos or greater than the length of the string then the
+ /// empty substring will be returned.
+ ///
+ /// \param N The number of characters to included in the substring. If \p N
+ /// exceeds the number of characters remaining in the string, the string
+ /// suffix (starting with \p Start) will be returned.
+ StringRef substr(size_t Start, size_t N = StringRef::npos) const {
+ return str().substr(Start, N);
+ }
+
+ /// Return a reference to the substring from [Start, End).
+ ///
+ /// \param Start The index of the starting character in the substring; if
+ /// the index is npos or greater than the length of the string then the
+ /// empty substring will be returned.
+ ///
+ /// \param End The index following the last character to include in the
+ /// substring. If this is npos, or less than \p Start, or exceeds the
+ /// number of characters remaining in the string, the string suffix
+ /// (starting with \p Start) will be returned.
+ StringRef slice(size_t Start, size_t End) const {
+ return str().slice(Start, End);
+ }
+
+ // Extra methods.
+
+ /// Explicit conversion to StringRef.
+ StringRef str() const { return StringRef(this->begin(), this->size()); }
+
+ // TODO: Make this const, if it's safe...
+ const char* c_str() {
+ this->push_back(0);
+ this->pop_back();
+ return this->data();
+ }
+
+ /// Implicit conversion to StringRef.
+ operator StringRef() const { return str(); }
+
+ // Extra operators.
+ const SmallString &operator=(StringRef RHS) {
+ this->clear();
+ return *this += RHS;
+ }
+
+ SmallString &operator+=(StringRef RHS) {
+ this->append(RHS.begin(), RHS.end());
+ return *this;
+ }
+ SmallString &operator+=(char C) {
+ this->push_back(C);
+ return *this;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_SMALLSTRING_H
diff --git a/third_party/llvm-project/include/llvm/ADT/SmallVector.h b/third_party/llvm-project/include/llvm/ADT/SmallVector.h
new file mode 100644
index 000000000..17586904d
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/SmallVector.h
@@ -0,0 +1,930 @@
+//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SmallVector class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SMALLVECTOR_H
+#define LLVM_ADT_SMALLVECTOR_H
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemAlloc.h"
+#include "llvm/Support/type_traits.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <initializer_list>
+#include <iterator>
+#include <memory>
+#include <new>
+#include <type_traits>
+#include <utility>
+
+namespace llvm {
+
+/// This is all the non-templated stuff common to all SmallVectors.
+class SmallVectorBase {
+protected:
+ void *BeginX;
+ unsigned Size = 0, Capacity;
+
+ SmallVectorBase() = delete;
+ SmallVectorBase(void *FirstEl, size_t TotalCapacity)
+ : BeginX(FirstEl), Capacity(TotalCapacity) {}
+
+ /// This is an implementation of the grow() method which only works
+ /// on POD-like data types and is out of line to reduce code duplication.
+ void grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize);
+
+public:
+ size_t size() const { return Size; }
+ size_t capacity() const { return Capacity; }
+
+ LLVM_NODISCARD bool empty() const { return !Size; }
+
+ /// Set the array size to \p N, which the current array must have enough
+ /// capacity for.
+ ///
+ /// This does not construct or destroy any elements in the vector.
+ ///
+ /// Clients can use this in conjunction with capacity() to write past the end
+ /// of the buffer when they know that more elements are available, and only
+ /// update the size later. This avoids the cost of value initializing elements
+ /// which will only be overwritten.
+ void set_size(size_t N) {
+ assert(N <= capacity());
+ Size = N;
+ }
+};
+
+/// Figure out the offset of the first element.
+template <class T, typename = void> struct SmallVectorAlignmentAndSize {
+ AlignedCharArrayUnion<SmallVectorBase> Base;
+ AlignedCharArrayUnion<T> FirstEl;
+};
+
+/// This is the part of SmallVectorTemplateBase which does not depend on whether
+/// the type T is a POD. The extra dummy template argument is used by ArrayRef
+/// to avoid unnecessarily requiring T to be complete.
+template <typename T, typename = void>
+class SmallVectorTemplateCommon : public SmallVectorBase {
+ /// Find the address of the first element. For this pointer math to be valid
+ /// with small-size of 0 for T with lots of alignment, it's important that
+ /// SmallVectorStorage is properly-aligned even for small-size of 0.
+ void *getFirstEl() const {
+ return const_cast<void *>(reinterpret_cast<const void *>(
+ reinterpret_cast<const char *>(this) +
+ offsetof(SmallVectorAlignmentAndSize<T>, FirstEl)));
+ }
+ // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
+
+protected:
+ SmallVectorTemplateCommon(size_t Size)
+ : SmallVectorBase(getFirstEl(), Size) {}
+
+ void grow_pod(size_t MinCapacity, size_t TSize) {
+ SmallVectorBase::grow_pod(getFirstEl(), MinCapacity, TSize);
+ }
+
+ /// Return true if this is a smallvector which has not had dynamic
+ /// memory allocated for it.
+ bool isSmall() const { return BeginX == getFirstEl(); }
+
+ /// Put this vector in a state of being small.
+ void resetToSmall() {
+ BeginX = getFirstEl();
+ Size = Capacity = 0; // FIXME: Setting Capacity to 0 is suspect.
+ }
+
+public:
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+ using value_type = T;
+ using iterator = T *;
+ using const_iterator = const T *;
+
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+
+ using reference = T &;
+ using const_reference = const T &;
+ using pointer = T *;
+ using const_pointer = const T *;
+
+ // forward iterator creation methods.
+ iterator begin() { return (iterator)this->BeginX; }
+ const_iterator begin() const { return (const_iterator)this->BeginX; }
+ iterator end() { return begin() + size(); }
+ const_iterator end() const { return begin() + size(); }
+
+ // reverse iterator creation methods.
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
+
+ size_type size_in_bytes() const { return size() * sizeof(T); }
+ size_type max_size() const { return size_type(-1) / sizeof(T); }
+
+ size_t capacity_in_bytes() const { return capacity() * sizeof(T); }
+
+ /// Return a pointer to the vector's buffer, even if empty().
+ pointer data() { return pointer(begin()); }
+ /// Return a pointer to the vector's buffer, even if empty().
+ const_pointer data() const { return const_pointer(begin()); }
+
+ reference operator[](size_type idx) {
+ assert(idx < size());
+ return begin()[idx];
+ }
+ const_reference operator[](size_type idx) const {
+ assert(idx < size());
+ return begin()[idx];
+ }
+
+ reference front() {
+ assert(!empty());
+ return begin()[0];
+ }
+ const_reference front() const {
+ assert(!empty());
+ return begin()[0];
+ }
+
+ reference back() {
+ assert(!empty());
+ return end()[-1];
+ }
+ const_reference back() const {
+ assert(!empty());
+ return end()[-1];
+ }
+};
+
+/// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put method
+/// implementations that are designed to work with non-POD-like T's.
+template <typename T, bool = is_trivially_copyable<T>::value>
+class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
+protected:
+ SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
+
+ static void destroy_range(T *S, T *E) {
+ while (S != E) {
+ --E;
+ E->~T();
+ }
+ }
+
+ /// Move the range [I, E) into the uninitialized memory starting with "Dest",
+ /// constructing elements as needed.
+ template<typename It1, typename It2>
+ static void uninitialized_move(It1 I, It1 E, It2 Dest) {
+ std::uninitialized_copy(std::make_move_iterator(I),
+ std::make_move_iterator(E), Dest);
+ }
+
+ /// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
+ /// constructing elements as needed.
+ template<typename It1, typename It2>
+ static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
+ std::uninitialized_copy(I, E, Dest);
+ }
+
+ /// Grow the allocated memory (without initializing new elements), doubling
+ /// the size of the allocated memory. Guarantees space for at least one more
+ /// element, or MinSize more elements if specified.
+ void grow(size_t MinSize = 0);
+
+public:
+ void push_back(const T &Elt) {
+ if (LLVM_UNLIKELY(this->size() >= this->capacity()))
+ this->grow();
+ ::new ((void*) this->end()) T(Elt);
+ this->set_size(this->size() + 1);
+ }
+
+ void push_back(T &&Elt) {
+ if (LLVM_UNLIKELY(this->size() >= this->capacity()))
+ this->grow();
+ ::new ((void*) this->end()) T(::std::move(Elt));
+ this->set_size(this->size() + 1);
+ }
+
+ void pop_back() {
+ this->set_size(this->size() - 1);
+ this->end()->~T();
+ }
+};
+
+// Define this out-of-line to dissuade the C++ compiler from inlining it.
+template <typename T, bool TriviallyCopyable>
+void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) {
+ if (MinSize > UINT32_MAX)
+ report_bad_alloc_error("SmallVector capacity overflow during allocation");
+
+ // Always grow, even from zero.
+ size_t NewCapacity = size_t(NextPowerOf2(this->capacity() + 2));
+ NewCapacity = std::min(std::max(NewCapacity, MinSize), size_t(UINT32_MAX));
+ T *NewElts = static_cast<T*>(llvm::safe_malloc(NewCapacity*sizeof(T)));
+
+ // Move the elements over.
+ this->uninitialized_move(this->begin(), this->end(), NewElts);
+
+ // Destroy the original elements.
+ destroy_range(this->begin(), this->end());
+
+ // If this wasn't grown from the inline copy, deallocate the old space.
+ if (!this->isSmall())
+ free(this->begin());
+
+ this->BeginX = NewElts;
+ this->Capacity = NewCapacity;
+}
+
+/// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
+/// method implementations that are designed to work with POD-like T's.
+template <typename T>
+class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
+protected:
+ SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
+
+ // No need to do a destroy loop for POD's.
+ static void destroy_range(T *, T *) {}
+
+ /// Move the range [I, E) onto the uninitialized memory
+ /// starting with "Dest", constructing elements into it as needed.
+ template<typename It1, typename It2>
+ static void uninitialized_move(It1 I, It1 E, It2 Dest) {
+ // Just do a copy.
+ uninitialized_copy(I, E, Dest);
+ }
+
+ /// Copy the range [I, E) onto the uninitialized memory
+ /// starting with "Dest", constructing elements into it as needed.
+ template<typename It1, typename It2>
+ static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
+ // Arbitrary iterator types; just use the basic implementation.
+ std::uninitialized_copy(I, E, Dest);
+ }
+
+ /// Copy the range [I, E) onto the uninitialized memory
+ /// starting with "Dest", constructing elements into it as needed.
+ template <typename T1, typename T2>
+ static void uninitialized_copy(
+ T1 *I, T1 *E, T2 *Dest,
+ typename std::enable_if<std::is_same<typename std::remove_const<T1>::type,
+ T2>::value>::type * = nullptr) {
+ // Use memcpy for PODs iterated by pointers (which includes SmallVector
+ // iterators): std::uninitialized_copy optimizes to memmove, but we can
+ // use memcpy here. Note that I and E are iterators and thus might be
+ // invalid for memcpy if they are equal.
+ if (I != E)
+ memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T));
+ }
+
+ /// Double the size of the allocated memory, guaranteeing space for at
+ /// least one more element or MinSize if specified.
+ void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); }
+
+public:
+ void push_back(const T &Elt) {
+ if (LLVM_UNLIKELY(this->size() >= this->capacity()))
+ this->grow();
+ memcpy(reinterpret_cast<void *>(this->end()), &Elt, sizeof(T));
+ this->set_size(this->size() + 1);
+ }
+
+ void pop_back() { this->set_size(this->size() - 1); }
+};
+
+/// This class consists of common code factored out of the SmallVector class to
+/// reduce code duplication based on the SmallVector 'N' template parameter.
+template <typename T>
+class SmallVectorImpl : public SmallVectorTemplateBase<T> {
+ using SuperClass = SmallVectorTemplateBase<T>;
+
+public:
+ using iterator = typename SuperClass::iterator;
+ using const_iterator = typename SuperClass::const_iterator;
+ using reference = typename SuperClass::reference;
+ using size_type = typename SuperClass::size_type;
+
+protected:
+ // Default ctor - Initialize to empty.
+ explicit SmallVectorImpl(unsigned N)
+ : SmallVectorTemplateBase<T>(N) {}
+
+public:
+ SmallVectorImpl(const SmallVectorImpl &) = delete;
+
+ ~SmallVectorImpl() {
+ // Subclass has already destructed this vector's elements.
+ // If this wasn't grown from the inline copy, deallocate the old space.
+ if (!this->isSmall())
+ free(this->begin());
+ }
+
+ void clear() {
+ this->destroy_range(this->begin(), this->end());
+ this->Size = 0;
+ }
+
+ void resize(size_type N) {
+ if (N < this->size()) {
+ this->destroy_range(this->begin()+N, this->end());
+ this->set_size(N);
+ } else if (N > this->size()) {
+ if (this->capacity() < N)
+ this->grow(N);
+ for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
+ new (&*I) T();
+ this->set_size(N);
+ }
+ }
+
+ void resize(size_type N, const T &NV) {
+ if (N < this->size()) {
+ this->destroy_range(this->begin()+N, this->end());
+ this->set_size(N);
+ } else if (N > this->size()) {
+ if (this->capacity() < N)
+ this->grow(N);
+ std::uninitialized_fill(this->end(), this->begin()+N, NV);
+ this->set_size(N);
+ }
+ }
+
+ void reserve(size_type N) {
+ if (this->capacity() < N)
+ this->grow(N);
+ }
+
+ LLVM_NODISCARD T pop_back_val() {
+ T Result = ::std::move(this->back());
+ this->pop_back();
+ return Result;
+ }
+
+ void swap(SmallVectorImpl &RHS);
+
+ /// Add the specified range to the end of the SmallVector.
+ template <typename in_iter,
+ typename = typename std::enable_if<std::is_convertible<
+ typename std::iterator_traits<in_iter>::iterator_category,
+ std::input_iterator_tag>::value>::type>
+ void append(in_iter in_start, in_iter in_end) {
+ size_type NumInputs = std::distance(in_start, in_end);
+ if (NumInputs > this->capacity() - this->size())
+ this->grow(this->size()+NumInputs);
+
+ this->uninitialized_copy(in_start, in_end, this->end());
+ this->set_size(this->size() + NumInputs);
+ }
+
+ /// Append \p NumInputs copies of \p Elt to the end.
+ void append(size_type NumInputs, const T &Elt) {
+ if (NumInputs > this->capacity() - this->size())
+ this->grow(this->size()+NumInputs);
+
+ std::uninitialized_fill_n(this->end(), NumInputs, Elt);
+ this->set_size(this->size() + NumInputs);
+ }
+
+ void append(std::initializer_list<T> IL) {
+ append(IL.begin(), IL.end());
+ }
+
+ // FIXME: Consider assigning over existing elements, rather than clearing &
+ // re-initializing them - for all assign(...) variants.
+
+ void assign(size_type NumElts, const T &Elt) {
+ clear();
+ if (this->capacity() < NumElts)
+ this->grow(NumElts);
+ this->set_size(NumElts);
+ std::uninitialized_fill(this->begin(), this->end(), Elt);
+ }
+
+ template <typename in_iter,
+ typename = typename std::enable_if<std::is_convertible<
+ typename std::iterator_traits<in_iter>::iterator_category,
+ std::input_iterator_tag>::value>::type>
+ void assign(in_iter in_start, in_iter in_end) {
+ clear();
+ append(in_start, in_end);
+ }
+
+ void assign(std::initializer_list<T> IL) {
+ clear();
+ append(IL);
+ }
+
+ iterator erase(const_iterator CI) {
+ // Just cast away constness because this is a non-const member function.
+ iterator I = const_cast<iterator>(CI);
+
+ assert(I >= this->begin() && "Iterator to erase is out of bounds.");
+ assert(I < this->end() && "Erasing at past-the-end iterator.");
+
+ iterator N = I;
+ // Shift all elts down one.
+ std::move(I+1, this->end(), I);
+ // Drop the last elt.
+ this->pop_back();
+ return(N);
+ }
+
+ iterator erase(const_iterator CS, const_iterator CE) {
+ // Just cast away constness because this is a non-const member function.
+ iterator S = const_cast<iterator>(CS);
+ iterator E = const_cast<iterator>(CE);
+
+ assert(S >= this->begin() && "Range to erase is out of bounds.");
+ assert(S <= E && "Trying to erase invalid range.");
+ assert(E <= this->end() && "Trying to erase past the end.");
+
+ iterator N = S;
+ // Shift all elts down.
+ iterator I = std::move(E, this->end(), S);
+ // Drop the last elts.
+ this->destroy_range(I, this->end());
+ this->set_size(I - this->begin());
+ return(N);
+ }
+
+ iterator insert(iterator I, T &&Elt) {
+ if (I == this->end()) { // Important special case for empty vector.
+ this->push_back(::std::move(Elt));
+ return this->end()-1;
+ }
+
+ assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+ assert(I <= this->end() && "Inserting past the end of the vector.");
+
+ if (this->size() >= this->capacity()) {
+ size_t EltNo = I-this->begin();
+ this->grow();
+ I = this->begin()+EltNo;
+ }
+
+ ::new ((void*) this->end()) T(::std::move(this->back()));
+ // Push everything else over.
+ std::move_backward(I, this->end()-1, this->end());
+ this->set_size(this->size() + 1);
+
+ // If we just moved the element we're inserting, be sure to update
+ // the reference.
+ T *EltPtr = &Elt;
+ if (I <= EltPtr && EltPtr < this->end())
+ ++EltPtr;
+
+ *I = ::std::move(*EltPtr);
+ return I;
+ }
+
+ iterator insert(iterator I, const T &Elt) {
+ if (I == this->end()) { // Important special case for empty vector.
+ this->push_back(Elt);
+ return this->end()-1;
+ }
+
+ assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+ assert(I <= this->end() && "Inserting past the end of the vector.");
+
+ if (this->size() >= this->capacity()) {
+ size_t EltNo = I-this->begin();
+ this->grow();
+ I = this->begin()+EltNo;
+ }
+ ::new ((void*) this->end()) T(std::move(this->back()));
+ // Push everything else over.
+ std::move_backward(I, this->end()-1, this->end());
+ this->set_size(this->size() + 1);
+
+ // If we just moved the element we're inserting, be sure to update
+ // the reference.
+ const T *EltPtr = &Elt;
+ if (I <= EltPtr && EltPtr < this->end())
+ ++EltPtr;
+
+ *I = *EltPtr;
+ return I;
+ }
+
+ iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
+ // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+ size_t InsertElt = I - this->begin();
+
+ if (I == this->end()) { // Important special case for empty vector.
+ append(NumToInsert, Elt);
+ return this->begin()+InsertElt;
+ }
+
+ assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+ assert(I <= this->end() && "Inserting past the end of the vector.");
+
+ // Ensure there is enough space.
+ reserve(this->size() + NumToInsert);
+
+ // Uninvalidate the iterator.
+ I = this->begin()+InsertElt;
+
+ // If there are more elements between the insertion point and the end of the
+ // range than there are being inserted, we can use a simple approach to
+ // insertion. Since we already reserved space, we know that this won't
+ // reallocate the vector.
+ if (size_t(this->end()-I) >= NumToInsert) {
+ T *OldEnd = this->end();
+ append(std::move_iterator<iterator>(this->end() - NumToInsert),
+ std::move_iterator<iterator>(this->end()));
+
+ // Copy the existing elements that get replaced.
+ std::move_backward(I, OldEnd-NumToInsert, OldEnd);
+
+ std::fill_n(I, NumToInsert, Elt);
+ return I;
+ }
+
+ // Otherwise, we're inserting more elements than exist already, and we're
+ // not inserting at the end.
+
+ // Move over the elements that we're about to overwrite.
+ T *OldEnd = this->end();
+ this->set_size(this->size() + NumToInsert);
+ size_t NumOverwritten = OldEnd-I;
+ this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
+
+ // Replace the overwritten part.
+ std::fill_n(I, NumOverwritten, Elt);
+
+ // Insert the non-overwritten middle part.
+ std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
+ return I;
+ }
+
+ template <typename ItTy,
+ typename = typename std::enable_if<std::is_convertible<
+ typename std::iterator_traits<ItTy>::iterator_category,
+ std::input_iterator_tag>::value>::type>
+ iterator insert(iterator I, ItTy From, ItTy To) {
+ // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+ size_t InsertElt = I - this->begin();
+
+ if (I == this->end()) { // Important special case for empty vector.
+ append(From, To);
+ return this->begin()+InsertElt;
+ }
+
+ assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+ assert(I <= this->end() && "Inserting past the end of the vector.");
+
+ size_t NumToInsert = std::distance(From, To);
+
+ // Ensure there is enough space.
+ reserve(this->size() + NumToInsert);
+
+ // Uninvalidate the iterator.
+ I = this->begin()+InsertElt;
+
+ // If there are more elements between the insertion point and the end of the
+ // range than there are being inserted, we can use a simple approach to
+ // insertion. Since we already reserved space, we know that this won't
+ // reallocate the vector.
+ if (size_t(this->end()-I) >= NumToInsert) {
+ T *OldEnd = this->end();
+ append(std::move_iterator<iterator>(this->end() - NumToInsert),
+ std::move_iterator<iterator>(this->end()));
+
+ // Copy the existing elements that get replaced.
+ std::move_backward(I, OldEnd-NumToInsert, OldEnd);
+
+ std::copy(From, To, I);
+ return I;
+ }
+
+ // Otherwise, we're inserting more elements than exist already, and we're
+ // not inserting at the end.
+
+ // Move over the elements that we're about to overwrite.
+ T *OldEnd = this->end();
+ this->set_size(this->size() + NumToInsert);
+ size_t NumOverwritten = OldEnd-I;
+ this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
+
+ // Replace the overwritten part.
+ for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
+ *J = *From;
+ ++J; ++From;
+ }
+
+ // Insert the non-overwritten middle part.
+ this->uninitialized_copy(From, To, OldEnd);
+ return I;
+ }
+
+ void insert(iterator I, std::initializer_list<T> IL) {
+ insert(I, IL.begin(), IL.end());
+ }
+
+ template <typename... ArgTypes> reference emplace_back(ArgTypes &&... Args) {
+ if (LLVM_UNLIKELY(this->size() >= this->capacity()))
+ this->grow();
+ ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
+ this->set_size(this->size() + 1);
+ return this->back();
+ }
+
+ SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
+
+ SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
+
+ bool operator==(const SmallVectorImpl &RHS) const {
+ if (this->size() != RHS.size()) return false;
+ return std::equal(this->begin(), this->end(), RHS.begin());
+ }
+ bool operator!=(const SmallVectorImpl &RHS) const {
+ return !(*this == RHS);
+ }
+
+ bool operator<(const SmallVectorImpl &RHS) const {
+ return std::lexicographical_compare(this->begin(), this->end(),
+ RHS.begin(), RHS.end());
+ }
+};
+
+template <typename T>
+void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
+ if (this == &RHS) return;
+
+ // We can only avoid copying elements if neither vector is small.
+ if (!this->isSmall() && !RHS.isSmall()) {
+ std::swap(this->BeginX, RHS.BeginX);
+ std::swap(this->Size, RHS.Size);
+ std::swap(this->Capacity, RHS.Capacity);
+ return;
+ }
+ if (RHS.size() > this->capacity())
+ this->grow(RHS.size());
+ if (this->size() > RHS.capacity())
+ RHS.grow(this->size());
+
+ // Swap the shared elements.
+ size_t NumShared = this->size();
+ if (NumShared > RHS.size()) NumShared = RHS.size();
+ for (size_type i = 0; i != NumShared; ++i)
+ std::swap((*this)[i], RHS[i]);
+
+ // Copy over the extra elts.
+ if (this->size() > RHS.size()) {
+ size_t EltDiff = this->size() - RHS.size();
+ this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
+ RHS.set_size(RHS.size() + EltDiff);
+ this->destroy_range(this->begin()+NumShared, this->end());
+ this->set_size(NumShared);
+ } else if (RHS.size() > this->size()) {
+ size_t EltDiff = RHS.size() - this->size();
+ this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
+ this->set_size(this->size() + EltDiff);
+ this->destroy_range(RHS.begin()+NumShared, RHS.end());
+ RHS.set_size(NumShared);
+ }
+}
+
+template <typename T>
+SmallVectorImpl<T> &SmallVectorImpl<T>::
+ operator=(const SmallVectorImpl<T> &RHS) {
+ // Avoid self-assignment.
+ if (this == &RHS) return *this;
+
+ // If we already have sufficient space, assign the common elements, then
+ // destroy any excess.
+ size_t RHSSize = RHS.size();
+ size_t CurSize = this->size();
+ if (CurSize >= RHSSize) {
+ // Assign common elements.
+ iterator NewEnd;
+ if (RHSSize)
+ NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
+ else
+ NewEnd = this->begin();
+
+ // Destroy excess elements.
+ this->destroy_range(NewEnd, this->end());
+
+ // Trim.
+ this->set_size(RHSSize);
+ return *this;
+ }
+
+ // If we have to grow to have enough elements, destroy the current elements.
+ // This allows us to avoid copying them during the grow.
+ // FIXME: don't do this if they're efficiently moveable.
+ if (this->capacity() < RHSSize) {
+ // Destroy current elements.
+ this->destroy_range(this->begin(), this->end());
+ this->set_size(0);
+ CurSize = 0;
+ this->grow(RHSSize);
+ } else if (CurSize) {
+ // Otherwise, use assignment for the already-constructed elements.
+ std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
+ }
+
+ // Copy construct the new elements in place.
+ this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
+ this->begin()+CurSize);
+
+ // Set end.
+ this->set_size(RHSSize);
+ return *this;
+}
+
+template <typename T>
+SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
+ // Avoid self-assignment.
+ if (this == &RHS) return *this;
+
+ // If the RHS isn't small, clear this vector and then steal its buffer.
+ if (!RHS.isSmall()) {
+ this->destroy_range(this->begin(), this->end());
+ if (!this->isSmall()) free(this->begin());
+ this->BeginX = RHS.BeginX;
+ this->Size = RHS.Size;
+ this->Capacity = RHS.Capacity;
+ RHS.resetToSmall();
+ return *this;
+ }
+
+ // If we already have sufficient space, assign the common elements, then
+ // destroy any excess.
+ size_t RHSSize = RHS.size();
+ size_t CurSize = this->size();
+ if (CurSize >= RHSSize) {
+ // Assign common elements.
+ iterator NewEnd = this->begin();
+ if (RHSSize)
+ NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
+
+ // Destroy excess elements and trim the bounds.
+ this->destroy_range(NewEnd, this->end());
+ this->set_size(RHSSize);
+
+ // Clear the RHS.
+ RHS.clear();
+
+ return *this;
+ }
+
+ // If we have to grow to have enough elements, destroy the current elements.
+ // This allows us to avoid copying them during the grow.
+ // FIXME: this may not actually make any sense if we can efficiently move
+ // elements.
+ if (this->capacity() < RHSSize) {
+ // Destroy current elements.
+ this->destroy_range(this->begin(), this->end());
+ this->set_size(0);
+ CurSize = 0;
+ this->grow(RHSSize);
+ } else if (CurSize) {
+ // Otherwise, use assignment for the already-constructed elements.
+ std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
+ }
+
+ // Move-construct the new elements in place.
+ this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
+ this->begin()+CurSize);
+
+ // Set end.
+ this->set_size(RHSSize);
+
+ RHS.clear();
+ return *this;
+}
+
+/// Storage for the SmallVector elements. This is specialized for the N=0 case
+/// to avoid allocating unnecessary storage.
+template <typename T, unsigned N>
+struct SmallVectorStorage {
+ AlignedCharArrayUnion<T> InlineElts[N];
+};
+
+/// We need the storage to be properly aligned even for small-size of 0 so that
+/// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is
+/// well-defined.
+template <typename T> struct alignas(alignof(T)) SmallVectorStorage<T, 0> {};
+
+/// This is a 'vector' (really, a variable-sized array), optimized
+/// for the case when the array is small. It contains some number of elements
+/// in-place, which allows it to avoid heap allocation when the actual number of
+/// elements is below that threshold. This allows normal "small" cases to be
+/// fast without losing generality for large inputs.
+///
+/// Note that this does not attempt to be exception safe.
+///
+template <typename T, unsigned N>
+class SmallVector : public SmallVectorImpl<T>, SmallVectorStorage<T, N> {
+public:
+ SmallVector() : SmallVectorImpl<T>(N) {}
+
+ ~SmallVector() {
+ // Destroy the constructed elements in the vector.
+ this->destroy_range(this->begin(), this->end());
+ }
+
+ explicit SmallVector(size_t Size, const T &Value = T())
+ : SmallVectorImpl<T>(N) {
+ this->assign(Size, Value);
+ }
+
+ template <typename ItTy,
+ typename = typename std::enable_if<std::is_convertible<
+ typename std::iterator_traits<ItTy>::iterator_category,
+ std::input_iterator_tag>::value>::type>
+ SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
+ this->append(S, E);
+ }
+
+ template <typename RangeTy>
+ explicit SmallVector(const iterator_range<RangeTy> &R)
+ : SmallVectorImpl<T>(N) {
+ this->append(R.begin(), R.end());
+ }
+
+ SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
+ this->assign(IL);
+ }
+
+ SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) {
+ if (!RHS.empty())
+ SmallVectorImpl<T>::operator=(RHS);
+ }
+
+ const SmallVector &operator=(const SmallVector &RHS) {
+ SmallVectorImpl<T>::operator=(RHS);
+ return *this;
+ }
+
+ SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) {
+ if (!RHS.empty())
+ SmallVectorImpl<T>::operator=(::std::move(RHS));
+ }
+
+ SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) {
+ if (!RHS.empty())
+ SmallVectorImpl<T>::operator=(::std::move(RHS));
+ }
+
+ const SmallVector &operator=(SmallVector &&RHS) {
+ SmallVectorImpl<T>::operator=(::std::move(RHS));
+ return *this;
+ }
+
+ const SmallVector &operator=(SmallVectorImpl<T> &&RHS) {
+ SmallVectorImpl<T>::operator=(::std::move(RHS));
+ return *this;
+ }
+
+ const SmallVector &operator=(std::initializer_list<T> IL) {
+ this->assign(IL);
+ return *this;
+ }
+};
+
+template <typename T, unsigned N>
+inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
+ return X.capacity_in_bytes();
+}
+
+} // end namespace llvm
+
+namespace std {
+
+ /// Implement std::swap in terms of SmallVector swap.
+ template<typename T>
+ inline void
+ swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) {
+ LHS.swap(RHS);
+ }
+
+ /// Implement std::swap in terms of SmallVector swap.
+ template<typename T, unsigned N>
+ inline void
+ swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) {
+ LHS.swap(RHS);
+ }
+
+} // end namespace std
+
+#endif // LLVM_ADT_SMALLVECTOR_H
diff --git a/third_party/llvm-project/include/llvm/ADT/StringExtras.h b/third_party/llvm-project/include/llvm/ADT/StringExtras.h
new file mode 100644
index 000000000..ef1a11e06
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/StringExtras.h
@@ -0,0 +1,401 @@
+//===- llvm/ADT/StringExtras.h - Useful string functions --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains some functions that are useful when dealing with strings.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STRINGEXTRAS_H
+#define LLVM_ADT_STRINGEXTRAS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iterator>
+#include <string>
+#include <utility>
+
+namespace llvm {
+
+template<typename T> class SmallVectorImpl;
+class raw_ostream;
+
+/// hexdigit - Return the hexadecimal character for the
+/// given number \p X (which should be less than 16).
+inline char hexdigit(unsigned X, bool LowerCase = false) {
+ const char HexChar = LowerCase ? 'a' : 'A';
+ return X < 10 ? '0' + X : HexChar + X - 10;
+}
+
+/// Given an array of c-style strings terminated by a null pointer, construct
+/// a vector of StringRefs representing the same strings without the terminating
+/// null string.
+inline std::vector<StringRef> toStringRefArray(const char *const *Strings) {
+ std::vector<StringRef> Result;
+ while (*Strings)
+ Result.push_back(*Strings++);
+ return Result;
+}
+
+/// Construct a string ref from a boolean.
+inline StringRef toStringRef(bool B) { return StringRef(B ? "true" : "false"); }
+
+/// Construct a string ref from an array ref of unsigned chars.
+inline StringRef toStringRef(ArrayRef<uint8_t> Input) {
+ return StringRef(reinterpret_cast<const char *>(Input.begin()), Input.size());
+}
+
+/// Construct a string ref from an array ref of unsigned chars.
+inline ArrayRef<uint8_t> arrayRefFromStringRef(StringRef Input) {
+ return {Input.bytes_begin(), Input.bytes_end()};
+}
+
+/// Interpret the given character \p C as a hexadecimal digit and return its
+/// value.
+///
+/// If \p C is not a valid hex digit, -1U is returned.
+inline unsigned hexDigitValue(char C) {
+ if (C >= '0' && C <= '9') return C-'0';
+ if (C >= 'a' && C <= 'f') return C-'a'+10U;
+ if (C >= 'A' && C <= 'F') return C-'A'+10U;
+ return -1U;
+}
+
+/// Checks if character \p C is one of the 10 decimal digits.
+inline bool isDigit(char C) { return C >= '0' && C <= '9'; }
+
+/// Checks if character \p C is a hexadecimal numeric character.
+inline bool isHexDigit(char C) { return hexDigitValue(C) != -1U; }
+
+/// Checks if character \p C is a valid letter as classified by "C" locale.
+inline bool isAlpha(char C) {
+ return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z');
+}
+
+/// Checks whether character \p C is either a decimal digit or an uppercase or
+/// lowercase letter as classified by "C" locale.
+inline bool isAlnum(char C) { return isAlpha(C) || isDigit(C); }
+
+/// Checks whether character \p C is valid ASCII (high bit is zero).
+inline bool isASCII(char C) { return static_cast<unsigned char>(C) <= 127; }
+
+/// Checks whether all characters in S are ASCII.
+inline bool isASCII(llvm::StringRef S) {
+ for (char C : S)
+ if (LLVM_UNLIKELY(!isASCII(C)))
+ return false;
+ return true;
+}
+
+/// Checks whether character \p C is printable.
+///
+/// Locale-independent version of the C standard library isprint whose results
+/// may differ on different platforms.
+inline bool isPrint(char C) {
+ unsigned char UC = static_cast<unsigned char>(C);
+ return (0x20 <= UC) && (UC <= 0x7E);
+}
+
+/// Returns the corresponding lowercase character if \p x is uppercase.
+inline char toLower(char x) {
+ if (x >= 'A' && x <= 'Z')
+ return x - 'A' + 'a';
+ return x;
+}
+
+/// Returns the corresponding uppercase character if \p x is lowercase.
+inline char toUpper(char x) {
+ if (x >= 'a' && x <= 'z')
+ return x - 'a' + 'A';
+ return x;
+}
+
+inline std::string utohexstr(uint64_t X, bool LowerCase = false) {
+ char Buffer[17];
+ char *BufPtr = std::end(Buffer);
+
+ if (X == 0) *--BufPtr = '0';
+
+ while (X) {
+ unsigned char Mod = static_cast<unsigned char>(X) & 15;
+ *--BufPtr = hexdigit(Mod, LowerCase);
+ X >>= 4;
+ }
+
+ return std::string(BufPtr, std::end(Buffer));
+}
+
+/// Convert buffer \p Input to its hexadecimal representation.
+/// The returned string is double the size of \p Input.
+inline std::string toHex(StringRef Input, bool LowerCase = false) {
+ static const char *const LUT = "0123456789ABCDEF";
+ const uint8_t Offset = LowerCase ? 32 : 0;
+ size_t Length = Input.size();
+
+ std::string Output;
+ Output.reserve(2 * Length);
+ for (size_t i = 0; i < Length; ++i) {
+ const unsigned char c = Input[i];
+ Output.push_back(LUT[c >> 4] | Offset);
+ Output.push_back(LUT[c & 15] | Offset);
+ }
+ return Output;
+}
+
+inline std::string toHex(ArrayRef<uint8_t> Input, bool LowerCase = false) {
+ return toHex(toStringRef(Input), LowerCase);
+}
+
+inline uint8_t hexFromNibbles(char MSB, char LSB) {
+ unsigned U1 = hexDigitValue(MSB);
+ unsigned U2 = hexDigitValue(LSB);
+ assert(U1 != -1U && U2 != -1U);
+
+ return static_cast<uint8_t>((U1 << 4) | U2);
+}
+
+/// Convert hexadecimal string \p Input to its binary representation.
+/// The return string is half the size of \p Input.
+inline std::string fromHex(StringRef Input) {
+ if (Input.empty())
+ return std::string();
+
+ std::string Output;
+ Output.reserve((Input.size() + 1) / 2);
+ if (Input.size() % 2 == 1) {
+ Output.push_back(hexFromNibbles('0', Input.front()));
+ Input = Input.drop_front();
+ }
+
+ assert(Input.size() % 2 == 0);
+ while (!Input.empty()) {
+ uint8_t Hex = hexFromNibbles(Input[0], Input[1]);
+ Output.push_back(Hex);
+ Input = Input.drop_front(2);
+ }
+ return Output;
+}
+
+/// Convert the string \p S to an integer of the specified type using
+/// the radix \p Base. If \p Base is 0, auto-detects the radix.
+/// Returns true if the number was successfully converted, false otherwise.
+template <typename N> bool to_integer(StringRef S, N &Num, unsigned Base = 0) {
+ return !S.getAsInteger(Base, Num);
+}
+
+namespace detail {
+template <typename N>
+inline bool to_float(const Twine &T, N &Num, N (*StrTo)(const char *, char **)) {
+ SmallString<32> Storage;
+ StringRef S = T.toNullTerminatedStringRef(Storage);
+ char *End;
+ N Temp = StrTo(S.data(), &End);
+ if (*End != '\0')
+ return false;
+ Num = Temp;
+ return true;
+}
+}
+
+inline bool to_float(const Twine &T, float &Num) {
+ return detail::to_float(T, Num, strtof);
+}
+
+inline bool to_float(const Twine &T, double &Num) {
+ return detail::to_float(T, Num, strtod);
+}
+
+inline bool to_float(const Twine &T, long double &Num) {
+ return detail::to_float(T, Num, strtold);
+}
+
+inline std::string utostr(uint64_t X, bool isNeg = false) {
+ char Buffer[21];
+ char *BufPtr = std::end(Buffer);
+
+ if (X == 0) *--BufPtr = '0'; // Handle special case...
+
+ while (X) {
+ *--BufPtr = '0' + char(X % 10);
+ X /= 10;
+ }
+
+ if (isNeg) *--BufPtr = '-'; // Add negative sign...
+ return std::string(BufPtr, std::end(Buffer));
+}
+
+inline std::string itostr(int64_t X) {
+ if (X < 0)
+ return utostr(static_cast<uint64_t>(-X), true);
+ else
+ return utostr(static_cast<uint64_t>(X));
+}
+
+/// 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 StrInStrNoCase(StringRef s1, StringRef s2);
+
+/// 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> getToken(StringRef Source,
+ StringRef Delimiters = " \t\n\v\f\r");
+
+/// SplitString - Split up the specified string according to the specified
+/// delimiters, appending the result fragments to the output list.
+void SplitString(StringRef Source,
+ SmallVectorImpl<StringRef> &OutFragments,
+ StringRef Delimiters = " \t\n\v\f\r");
+
+/// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th).
+inline StringRef getOrdinalSuffix(unsigned Val) {
+ // It is critically important that we do this perfectly for
+ // user-written sequences with over 100 elements.
+ switch (Val % 100) {
+ case 11:
+ case 12:
+ case 13:
+ return "th";
+ default:
+ switch (Val % 10) {
+ case 1: return "st";
+ case 2: return "nd";
+ case 3: return "rd";
+ default: return "th";
+ }
+ }
+}
+
+/// Print each character of the specified string, escaping it if it is not
+/// printable or if it is an escape char.
+void printEscapedString(StringRef Name, raw_ostream &Out);
+
+/// Print each character of the specified string, escaping HTML special
+/// characters.
+void printHTMLEscaped(StringRef String, raw_ostream &Out);
+
+/// printLowerCase - Print each character as lowercase if it is uppercase.
+void printLowerCase(StringRef String, raw_ostream &Out);
+
+namespace detail {
+
+template <typename IteratorT>
+inline std::string join_impl(IteratorT Begin, IteratorT End,
+ StringRef Separator, std::input_iterator_tag) {
+ std::string S;
+ if (Begin == End)
+ return S;
+
+ S += (*Begin);
+ while (++Begin != End) {
+ S += Separator;
+ S += (*Begin);
+ }
+ return S;
+}
+
+template <typename IteratorT>
+inline std::string join_impl(IteratorT Begin, IteratorT End,
+ StringRef Separator, std::forward_iterator_tag) {
+ std::string S;
+ if (Begin == End)
+ return S;
+
+ size_t Len = (std::distance(Begin, End) - 1) * Separator.size();
+ for (IteratorT I = Begin; I != End; ++I)
+ Len += (*Begin).size();
+ S.reserve(Len);
+ S += (*Begin);
+ while (++Begin != End) {
+ S += Separator;
+ S += (*Begin);
+ }
+ return S;
+}
+
+template <typename Sep>
+inline void join_items_impl(std::string &Result, Sep Separator) {}
+
+template <typename Sep, typename Arg>
+inline void join_items_impl(std::string &Result, Sep Separator,
+ const Arg &Item) {
+ Result += Item;
+}
+
+template <typename Sep, typename Arg1, typename... Args>
+inline void join_items_impl(std::string &Result, Sep Separator, const Arg1 &A1,
+ Args &&... Items) {
+ Result += A1;
+ Result += Separator;
+ join_items_impl(Result, Separator, std::forward<Args>(Items)...);
+}
+
+inline size_t join_one_item_size(char) { return 1; }
+inline size_t join_one_item_size(const char *S) { return S ? ::strlen(S) : 0; }
+
+template <typename T> inline size_t join_one_item_size(const T &Str) {
+ return Str.size();
+}
+
+inline size_t join_items_size() { return 0; }
+
+template <typename A1> inline size_t join_items_size(const A1 &A) {
+ return join_one_item_size(A);
+}
+template <typename A1, typename... Args>
+inline size_t join_items_size(const A1 &A, Args &&... Items) {
+ return join_one_item_size(A) + join_items_size(std::forward<Args>(Items)...);
+}
+
+} // end namespace detail
+
+/// Joins the strings in the range [Begin, End), adding Separator between
+/// the elements.
+template <typename IteratorT>
+inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) {
+ using tag = typename std::iterator_traits<IteratorT>::iterator_category;
+ return detail::join_impl(Begin, End, Separator, tag());
+}
+
+/// Joins the strings in the range [R.begin(), R.end()), adding Separator
+/// between the elements.
+template <typename Range>
+inline std::string join(Range &&R, StringRef Separator) {
+ return join(R.begin(), R.end(), Separator);
+}
+
+/// Joins the strings in the parameter pack \p Items, adding \p Separator
+/// between the elements. All arguments must be implicitly convertible to
+/// std::string, or there should be an overload of std::string::operator+=()
+/// that accepts the argument explicitly.
+template <typename Sep, typename... Args>
+inline std::string join_items(Sep Separator, Args &&... Items) {
+ std::string Result;
+ if (sizeof...(Items) == 0)
+ return Result;
+
+ size_t NS = detail::join_one_item_size(Separator);
+ size_t NI = detail::join_items_size(std::forward<Args>(Items)...);
+ Result.reserve(NI + (sizeof...(Items) - 1) * NS + 1);
+ detail::join_items_impl(Result, Separator, std::forward<Args>(Items)...);
+ return Result;
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_STRINGEXTRAS_H
diff --git a/third_party/llvm-project/include/llvm/ADT/StringMap.h b/third_party/llvm-project/include/llvm/ADT/StringMap.h
new file mode 100644
index 000000000..108185bd0
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/StringMap.h
@@ -0,0 +1,593 @@
+//===- StringMap.h - String Hash table map interface ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the StringMap class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STRINGMAP_H
+#define LLVM_ADT_STRINGMAP_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <initializer_list>
+#include <iterator>
+#include <utility>
+
+namespace llvm {
+
+template<typename ValueTy> class StringMapConstIterator;
+template<typename ValueTy> class StringMapIterator;
+template<typename ValueTy> class StringMapKeyIterator;
+
+/// StringMapEntryBase - Shared base class of StringMapEntry instances.
+class StringMapEntryBase {
+ size_t StrLen;
+
+public:
+ explicit StringMapEntryBase(size_t Len) : StrLen(Len) {}
+
+ size_t getKeyLength() const { return StrLen; }
+};
+
+/// StringMapImpl - This is the base class of StringMap that is shared among
+/// all of its instantiations.
+class StringMapImpl {
+protected:
+ // Array of NumBuckets pointers to entries, null pointers are holes.
+ // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed
+ // by an array of the actual hash values as unsigned integers.
+ StringMapEntryBase **TheTable = nullptr;
+ unsigned NumBuckets = 0;
+ unsigned NumItems = 0;
+ unsigned NumTombstones = 0;
+ unsigned ItemSize;
+
+protected:
+ explicit StringMapImpl(unsigned itemSize)
+ : ItemSize(itemSize) {}
+ StringMapImpl(StringMapImpl &&RHS)
+ : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets),
+ NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones),
+ ItemSize(RHS.ItemSize) {
+ RHS.TheTable = nullptr;
+ RHS.NumBuckets = 0;
+ RHS.NumItems = 0;
+ RHS.NumTombstones = 0;
+ }
+
+ StringMapImpl(unsigned InitSize, unsigned ItemSize);
+ unsigned RehashTable(unsigned BucketNo = 0);
+
+ /// 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 LookupBucketFor(StringRef Key);
+
+ /// 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 FindKey(StringRef Key) const;
+
+ /// RemoveKey - Remove the specified StringMapEntry from the table, but do not
+ /// delete it. This aborts if the value isn't in the table.
+ void RemoveKey(StringMapEntryBase *V);
+
+ /// 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 *RemoveKey(StringRef Key);
+
+ /// Allocate the table with the specified number of buckets and otherwise
+ /// setup the map as empty.
+ void init(unsigned Size);
+
+public:
+ static StringMapEntryBase *getTombstoneVal() {
+ uintptr_t Val = static_cast<uintptr_t>(-1);
+ Val <<= PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable;
+ return reinterpret_cast<StringMapEntryBase *>(Val);
+ }
+
+ unsigned getNumBuckets() const { return NumBuckets; }
+ unsigned getNumItems() const { return NumItems; }
+
+ bool empty() const { return NumItems == 0; }
+ unsigned size() const { return NumItems; }
+
+ void swap(StringMapImpl &Other) {
+ std::swap(TheTable, Other.TheTable);
+ std::swap(NumBuckets, Other.NumBuckets);
+ std::swap(NumItems, Other.NumItems);
+ std::swap(NumTombstones, Other.NumTombstones);
+ }
+};
+
+/// StringMapEntryStorage - Holds the value in a StringMapEntry.
+///
+/// Factored out into a separate base class to make it easier to specialize.
+/// This is primarily intended to support StringSet, which doesn't need a value
+/// stored at all.
+template<typename ValueTy>
+class StringMapEntryStorage : public StringMapEntryBase {
+public:
+ ValueTy second;
+
+ explicit StringMapEntryStorage(size_t strLen)
+ : StringMapEntryBase(strLen), second() {}
+ template <typename... InitTy>
+ StringMapEntryStorage(size_t strLen, InitTy &&... InitVals)
+ : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {}
+ StringMapEntryStorage(StringMapEntryStorage &E) = delete;
+
+ const ValueTy &getValue() const { return second; }
+ ValueTy &getValue() { return second; }
+
+ void setValue(const ValueTy &V) { second = V; }
+};
+
+template<>
+class StringMapEntryStorage<NoneType> : public StringMapEntryBase {
+public:
+ explicit StringMapEntryStorage(size_t strLen, NoneType none = None)
+ : StringMapEntryBase(strLen) {}
+ StringMapEntryStorage(StringMapEntryStorage &E) = delete;
+
+ NoneType getValue() const { return None; }
+};
+
+/// StringMapEntry - This is used to represent one value that is inserted into
+/// a StringMap. It contains the Value itself and the key: the string length
+/// and data.
+template<typename ValueTy>
+class StringMapEntry final : public StringMapEntryStorage<ValueTy> {
+public:
+ using StringMapEntryStorage<ValueTy>::StringMapEntryStorage;
+
+ StringRef getKey() const {
+ return StringRef(getKeyData(), this->getKeyLength());
+ }
+
+ /// getKeyData - Return the start of the string data that is the key for this
+ /// value. The string data is always stored immediately after the
+ /// StringMapEntry object.
+ const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);}
+
+ StringRef first() const {
+ return StringRef(getKeyData(), this->getKeyLength());
+ }
+
+ /// Create a StringMapEntry for the specified key construct the value using
+ /// \p InitiVals.
+ template <typename AllocatorTy, typename... InitTy>
+ static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator,
+ InitTy &&... InitVals) {
+ size_t KeyLength = Key.size();
+
+ // Allocate a new item with space for the string at the end and a null
+ // terminator.
+ size_t AllocSize = sizeof(StringMapEntry) + KeyLength + 1;
+ size_t Alignment = alignof(StringMapEntry);
+
+ StringMapEntry *NewItem =
+ static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment));
+ assert(NewItem && "Unhandled out-of-memory");
+
+ // Construct the value.
+ new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...);
+
+ // Copy the string information.
+ char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
+ if (KeyLength > 0)
+ memcpy(StrBuffer, Key.data(), KeyLength);
+ StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients.
+ return NewItem;
+ }
+
+ /// Create - Create a StringMapEntry with normal malloc/free.
+ template <typename... InitType>
+ static StringMapEntry *Create(StringRef Key, InitType &&... InitVal) {
+ MallocAllocator A;
+ return Create(Key, A, std::forward<InitType>(InitVal)...);
+ }
+
+ static StringMapEntry *Create(StringRef Key) {
+ return Create(Key, ValueTy());
+ }
+
+ /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
+ /// into a StringMapEntry, return the StringMapEntry itself.
+ static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
+ char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>);
+ return *reinterpret_cast<StringMapEntry*>(Ptr);
+ }
+
+ /// Destroy - Destroy this StringMapEntry, releasing memory back to the
+ /// specified allocator.
+ template<typename AllocatorTy>
+ void Destroy(AllocatorTy &Allocator) {
+ // Free memory referenced by the item.
+ size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1;
+ this->~StringMapEntry();
+ Allocator.Deallocate(static_cast<void *>(this), AllocSize);
+ }
+
+ /// Destroy this object, releasing memory back to the malloc allocator.
+ void Destroy() {
+ MallocAllocator A;
+ Destroy(A);
+ }
+};
+
+/// StringMap - This is an unconventional map that is specialized for handling
+/// keys that are "strings", which are basically ranges of bytes. This does some
+/// funky memory allocation and hashing things to make it extremely efficient,
+/// storing the string data *after* the value in the map.
+template<typename ValueTy, typename AllocatorTy = MallocAllocator>
+class StringMap : public StringMapImpl {
+ AllocatorTy Allocator;
+
+public:
+ using MapEntryTy = StringMapEntry<ValueTy>;
+
+ StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
+
+ explicit StringMap(unsigned InitialSize)
+ : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
+
+ explicit StringMap(AllocatorTy A)
+ : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {}
+
+ StringMap(unsigned InitialSize, AllocatorTy A)
+ : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))),
+ Allocator(A) {}
+
+ StringMap(std::initializer_list<std::pair<StringRef, ValueTy>> List)
+ : StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) {
+ for (const auto &P : List) {
+ insert(P);
+ }
+ }
+
+ StringMap(StringMap &&RHS)
+ : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {}
+
+ StringMap(const StringMap &RHS) :
+ StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))),
+ Allocator(RHS.Allocator) {
+ if (RHS.empty())
+ return;
+
+ // Allocate TheTable of the same size as RHS's TheTable, and set the
+ // sentinel appropriately (and NumBuckets).
+ init(RHS.NumBuckets);
+ unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1),
+ *RHSHashTable = (unsigned *)(RHS.TheTable + NumBuckets + 1);
+
+ NumItems = RHS.NumItems;
+ NumTombstones = RHS.NumTombstones;
+ for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
+ StringMapEntryBase *Bucket = RHS.TheTable[I];
+ if (!Bucket || Bucket == getTombstoneVal()) {
+ TheTable[I] = Bucket;
+ continue;
+ }
+
+ TheTable[I] = MapEntryTy::Create(
+ static_cast<MapEntryTy *>(Bucket)->getKey(), Allocator,
+ static_cast<MapEntryTy *>(Bucket)->getValue());
+ HashTable[I] = RHSHashTable[I];
+ }
+
+ // Note that here we've copied everything from the RHS into this object,
+ // tombstones included. We could, instead, have re-probed for each key to
+ // instantiate this new object without any tombstone buckets. The
+ // assumption here is that items are rarely deleted from most StringMaps,
+ // and so tombstones are rare, so the cost of re-probing for all inputs is
+ // not worthwhile.
+ }
+
+ StringMap &operator=(StringMap RHS) {
+ StringMapImpl::swap(RHS);
+ std::swap(Allocator, RHS.Allocator);
+ return *this;
+ }
+
+ ~StringMap() {
+ // Delete all the elements in the map, but don't reset the elements
+ // to default values. This is a copy of clear(), but avoids unnecessary
+ // work not required in the destructor.
+ if (!empty()) {
+ for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
+ StringMapEntryBase *Bucket = TheTable[I];
+ if (Bucket && Bucket != getTombstoneVal()) {
+ static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
+ }
+ }
+ }
+ free(TheTable);
+ }
+
+ AllocatorTy &getAllocator() { return Allocator; }
+ const AllocatorTy &getAllocator() const { return Allocator; }
+
+ using key_type = const char*;
+ using mapped_type = ValueTy;
+ using value_type = StringMapEntry<ValueTy>;
+ using size_type = size_t;
+
+ using const_iterator = StringMapConstIterator<ValueTy>;
+ using iterator = StringMapIterator<ValueTy>;
+
+ iterator begin() {
+ return iterator(TheTable, NumBuckets == 0);
+ }
+ iterator end() {
+ return iterator(TheTable+NumBuckets, true);
+ }
+ const_iterator begin() const {
+ return const_iterator(TheTable, NumBuckets == 0);
+ }
+ const_iterator end() const {
+ return const_iterator(TheTable+NumBuckets, true);
+ }
+
+ iterator_range<StringMapKeyIterator<ValueTy>> keys() const {
+ return make_range(StringMapKeyIterator<ValueTy>(begin()),
+ StringMapKeyIterator<ValueTy>(end()));
+ }
+
+ iterator find(StringRef Key) {
+ int Bucket = FindKey(Key);
+ if (Bucket == -1) return end();
+ return iterator(TheTable+Bucket, true);
+ }
+
+ const_iterator find(StringRef Key) const {
+ int Bucket = FindKey(Key);
+ if (Bucket == -1) return end();
+ return const_iterator(TheTable+Bucket, true);
+ }
+
+ /// lookup - Return the entry for the specified key, or a default
+ /// constructed value if no such entry exists.
+ ValueTy lookup(StringRef Key) const {
+ const_iterator it = find(Key);
+ if (it != end())
+ return it->second;
+ return ValueTy();
+ }
+
+ /// Lookup the ValueTy for the \p Key, or create a default constructed value
+ /// if the key is not in the map.
+ ValueTy &operator[](StringRef Key) { return try_emplace(Key).first->second; }
+
+ /// count - Return 1 if the element is in the map, 0 otherwise.
+ size_type count(StringRef Key) const {
+ return find(Key) == end() ? 0 : 1;
+ }
+
+ template <typename InputTy>
+ size_type count(const StringMapEntry<InputTy> &MapEntry) const {
+ return count(MapEntry.getKey());
+ }
+
+ /// insert - Insert the specified key/value pair into the map. If the key
+ /// already exists in the map, return false and ignore the request, otherwise
+ /// insert it and return true.
+ bool insert(MapEntryTy *KeyValue) {
+ unsigned BucketNo = LookupBucketFor(KeyValue->getKey());
+ StringMapEntryBase *&Bucket = TheTable[BucketNo];
+ if (Bucket && Bucket != getTombstoneVal())
+ return false; // Already exists in map.
+
+ if (Bucket == getTombstoneVal())
+ --NumTombstones;
+ Bucket = KeyValue;
+ ++NumItems;
+ assert(NumItems + NumTombstones <= NumBuckets);
+
+ RehashTable();
+ return true;
+ }
+
+ /// insert - Inserts the specified key/value pair into the map if the key
+ /// isn't already in the map. The bool component of the returned pair is true
+ /// if and only if the insertion takes place, and the iterator component of
+ /// the pair points to the element with key equivalent to the key of the pair.
+ std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) {
+ return try_emplace(KV.first, std::move(KV.second));
+ }
+
+ /// Inserts an element or assigns to the current element if the key already
+ /// exists. The return type is the same as try_emplace.
+ template <typename V>
+ std::pair<iterator, bool> insert_or_assign(StringRef Key, V &&Val) {
+ auto Ret = try_emplace(Key, std::forward<V>(Val));
+ if (!Ret.second)
+ Ret.first->second = std::forward<V>(Val);
+ return Ret;
+ }
+
+ /// Emplace a new element for the specified key into the map if the key isn't
+ /// already in the map. The bool component of the returned pair is true
+ /// if and only if the insertion takes place, and the iterator component of
+ /// the pair points to the element with key equivalent to the key of the pair.
+ template <typename... ArgsTy>
+ std::pair<iterator, bool> try_emplace(StringRef Key, ArgsTy &&... Args) {
+ unsigned BucketNo = LookupBucketFor(Key);
+ StringMapEntryBase *&Bucket = TheTable[BucketNo];
+ if (Bucket && Bucket != getTombstoneVal())
+ return std::make_pair(iterator(TheTable + BucketNo, false),
+ false); // Already exists in map.
+
+ if (Bucket == getTombstoneVal())
+ --NumTombstones;
+ Bucket = MapEntryTy::Create(Key, Allocator, std::forward<ArgsTy>(Args)...);
+ ++NumItems;
+ assert(NumItems + NumTombstones <= NumBuckets);
+
+ BucketNo = RehashTable(BucketNo);
+ return std::make_pair(iterator(TheTable + BucketNo, false), true);
+ }
+
+ // clear - Empties out the StringMap
+ void clear() {
+ if (empty()) return;
+
+ // Zap all values, resetting the keys back to non-present (not tombstone),
+ // which is safe because we're removing all elements.
+ for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
+ StringMapEntryBase *&Bucket = TheTable[I];
+ if (Bucket && Bucket != getTombstoneVal()) {
+ static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
+ }
+ Bucket = nullptr;
+ }
+
+ NumItems = 0;
+ NumTombstones = 0;
+ }
+
+ /// remove - Remove the specified key/value pair from the map, but do not
+ /// erase it. This aborts if the key is not in the map.
+ void remove(MapEntryTy *KeyValue) {
+ RemoveKey(KeyValue);
+ }
+
+ void erase(iterator I) {
+ MapEntryTy &V = *I;
+ remove(&V);
+ V.Destroy(Allocator);
+ }
+
+ bool erase(StringRef Key) {
+ iterator I = find(Key);
+ if (I == end()) return false;
+ erase(I);
+ return true;
+ }
+};
+
+template <typename DerivedTy, typename ValueTy>
+class StringMapIterBase
+ : public iterator_facade_base<DerivedTy, std::forward_iterator_tag,
+ ValueTy> {
+protected:
+ StringMapEntryBase **Ptr = nullptr;
+
+public:
+ StringMapIterBase() = default;
+
+ explicit StringMapIterBase(StringMapEntryBase **Bucket,
+ bool NoAdvance = false)
+ : Ptr(Bucket) {
+ if (!NoAdvance) AdvancePastEmptyBuckets();
+ }
+
+ DerivedTy &operator=(const DerivedTy &Other) {
+ Ptr = Other.Ptr;
+ return static_cast<DerivedTy &>(*this);
+ }
+
+ bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; }
+
+ DerivedTy &operator++() { // Preincrement
+ ++Ptr;
+ AdvancePastEmptyBuckets();
+ return static_cast<DerivedTy &>(*this);
+ }
+
+ DerivedTy operator++(int) { // Post-increment
+ DerivedTy Tmp(Ptr);
+ ++*this;
+ return Tmp;
+ }
+
+private:
+ void AdvancePastEmptyBuckets() {
+ while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal())
+ ++Ptr;
+ }
+};
+
+template <typename ValueTy>
+class StringMapConstIterator
+ : public StringMapIterBase<StringMapConstIterator<ValueTy>,
+ const StringMapEntry<ValueTy>> {
+ using base = StringMapIterBase<StringMapConstIterator<ValueTy>,
+ const StringMapEntry<ValueTy>>;
+
+public:
+ StringMapConstIterator() = default;
+ explicit StringMapConstIterator(StringMapEntryBase **Bucket,
+ bool NoAdvance = false)
+ : base(Bucket, NoAdvance) {}
+
+ const StringMapEntry<ValueTy> &operator*() const {
+ return *static_cast<const StringMapEntry<ValueTy> *>(*this->Ptr);
+ }
+};
+
+template <typename ValueTy>
+class StringMapIterator : public StringMapIterBase<StringMapIterator<ValueTy>,
+ StringMapEntry<ValueTy>> {
+ using base =
+ StringMapIterBase<StringMapIterator<ValueTy>, StringMapEntry<ValueTy>>;
+
+public:
+ StringMapIterator() = default;
+ explicit StringMapIterator(StringMapEntryBase **Bucket,
+ bool NoAdvance = false)
+ : base(Bucket, NoAdvance) {}
+
+ StringMapEntry<ValueTy> &operator*() const {
+ return *static_cast<StringMapEntry<ValueTy> *>(*this->Ptr);
+ }
+
+ operator StringMapConstIterator<ValueTy>() const {
+ return StringMapConstIterator<ValueTy>(this->Ptr, true);
+ }
+};
+
+template <typename ValueTy>
+class StringMapKeyIterator
+ : public iterator_adaptor_base<StringMapKeyIterator<ValueTy>,
+ StringMapConstIterator<ValueTy>,
+ std::forward_iterator_tag, StringRef> {
+ using base = iterator_adaptor_base<StringMapKeyIterator<ValueTy>,
+ StringMapConstIterator<ValueTy>,
+ std::forward_iterator_tag, StringRef>;
+
+public:
+ StringMapKeyIterator() = default;
+ explicit StringMapKeyIterator(StringMapConstIterator<ValueTy> Iter)
+ : base(std::move(Iter)) {}
+
+ StringRef &operator*() {
+ Key = this->wrapped()->getKey();
+ return Key;
+ }
+
+private:
+ StringRef Key;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_STRINGMAP_H
diff --git a/third_party/llvm-project/include/llvm/ADT/StringRef.h b/third_party/llvm-project/include/llvm/ADT/StringRef.h
new file mode 100644
index 000000000..e87a08f7e
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/StringRef.h
@@ -0,0 +1,920 @@
+//===- StringRef.h - Constant String Reference Wrapper ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STRINGREF_H
+#define LLVM_ADT_STRINGREF_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Compiler.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <limits>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+// Declare the __builtin_strlen intrinsic for MSVC so it can be used in
+// constexpr context.
+#if defined(_MSC_VER)
+extern "C" size_t __builtin_strlen(const char *);
+#endif
+
+namespace llvm {
+
+ class APInt;
+ class hash_code;
+ template <typename T> class SmallVectorImpl;
+ class StringRef;
+
+ /// Helper functions for StringRef::getAsInteger.
+ bool getAsUnsignedInteger(StringRef Str, unsigned Radix,
+ unsigned long long &Result);
+
+ bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result);
+
+ bool consumeUnsignedInteger(StringRef &Str, unsigned Radix,
+ unsigned long long &Result);
+ bool consumeSignedInteger(StringRef &Str, unsigned Radix, long long &Result);
+
+ /// StringRef - Represent a constant reference to a string, i.e. a character
+ /// array and a length, which need not be null terminated.
+ ///
+ /// This class does not own the string data, it is expected to be used in
+ /// situations where the character data resides in some other buffer, whose
+ /// lifetime extends past that of the StringRef. For this reason, it is not in
+ /// general safe to store a StringRef.
+ class StringRef {
+ public:
+ static const size_t npos = ~size_t(0);
+
+ using iterator = const char *;
+ using const_iterator = const char *;
+ using size_type = size_t;
+
+ private:
+ /// The start of the string, in an external buffer.
+ const char *Data = nullptr;
+
+ /// The length of the string.
+ size_t Length = 0;
+
+ // Workaround memcmp issue with null pointers (undefined behavior)
+ // by providing a specialized version
+ static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) {
+ if (Length == 0) { return 0; }
+ return ::memcmp(Lhs,Rhs,Length);
+ }
+
+ // Constexpr version of std::strlen.
+ static constexpr size_t strLen(const char *Str) {
+#if __cplusplus > 201402L
+ return std::char_traits<char>::length(Str);
+#elif __has_builtin(__builtin_strlen) || defined(__GNUC__) || defined(_MSC_VER)
+ return __builtin_strlen(Str);
+#else
+ const char *Begin = Str;
+ while (*Str != '\0')
+ ++Str;
+ return Str - Begin;
+#endif
+ }
+
+ public:
+ /// @name Constructors
+ /// @{
+
+ /// Construct an empty string ref.
+ /*implicit*/ StringRef() = default;
+
+ /// Disable conversion from nullptr. This prevents things like
+ /// if (S == nullptr)
+ StringRef(std::nullptr_t) = delete;
+
+ /// Construct a string ref from a cstring.
+ /*implicit*/ constexpr StringRef(const char *Str)
+ : Data(Str), Length(Str ? strLen(Str) : 0) {}
+
+ /// Construct a string ref from a pointer and length.
+ /*implicit*/ constexpr StringRef(const char *data, size_t length)
+ : Data(data), Length(length) {}
+
+ /// Construct a string ref from an std::string.
+ /*implicit*/ StringRef(const std::string &Str)
+ : Data(Str.data()), Length(Str.length()) {}
+
+ static StringRef withNullAsEmpty(const char *data) {
+ return StringRef(data ? data : "");
+ }
+
+ /// @}
+ /// @name Iterators
+ /// @{
+
+ iterator begin() const { return Data; }
+
+ iterator end() const { return Data + Length; }
+
+ const unsigned char *bytes_begin() const {
+ return reinterpret_cast<const unsigned char *>(begin());
+ }
+ const unsigned char *bytes_end() const {
+ return reinterpret_cast<const unsigned char *>(end());
+ }
+ iterator_range<const unsigned char *> bytes() const {
+ return make_range(bytes_begin(), bytes_end());
+ }
+
+ /// @}
+ /// @name String Operations
+ /// @{
+
+ /// data - Get a pointer to the start of the string (which may not be null
+ /// terminated).
+ LLVM_NODISCARD
+ const char *data() const { return Data; }
+
+ /// empty - Check if the string is empty.
+ LLVM_NODISCARD
+ bool empty() const { return Length == 0; }
+
+ /// size - Get the string size.
+ LLVM_NODISCARD
+ size_t size() const { return Length; }
+
+ /// front - Get the first character in the string.
+ LLVM_NODISCARD
+ char front() const {
+ assert(!empty());
+ return Data[0];
+ }
+
+ /// back - Get the last character in the string.
+ LLVM_NODISCARD
+ char back() const {
+ assert(!empty());
+ return Data[Length-1];
+ }
+
+ // copy - Allocate copy in Allocator and return StringRef to it.
+ template <typename Allocator>
+ LLVM_NODISCARD StringRef copy(Allocator &A) const {
+ // Don't request a length 0 copy from the allocator.
+ if (empty())
+ return StringRef();
+ char *S = A.template Allocate<char>(Length);
+ std::copy(begin(), end(), S);
+ return StringRef(S, Length);
+ }
+
+ /// equals - Check for string equality, this is more efficient than
+ /// compare() when the relative ordering of inequal strings isn't needed.
+ LLVM_NODISCARD
+ bool equals(StringRef RHS) const {
+ return (Length == RHS.Length &&
+ compareMemory(Data, RHS.Data, RHS.Length) == 0);
+ }
+
+ /// equals_lower - Check for string equality, ignoring case.
+ LLVM_NODISCARD
+ bool equals_lower(StringRef RHS) const {
+ return Length == RHS.Length && compare_lower(RHS) == 0;
+ }
+
+ /// compare - Compare two strings; the result is -1, 0, or 1 if this string
+ /// is lexicographically less than, equal to, or greater than the \p RHS.
+ LLVM_NODISCARD
+ int compare(StringRef RHS) const {
+ // Check the prefix for a mismatch.
+ if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length)))
+ return Res < 0 ? -1 : 1;
+
+ // Otherwise the prefixes match, so we only need to check the lengths.
+ if (Length == RHS.Length)
+ return 0;
+ return Length < RHS.Length ? -1 : 1;
+ }
+
+ /// compare_lower - Compare two strings, ignoring case.
+ LLVM_NODISCARD
+ int compare_lower(StringRef RHS) const;
+
+ /// compare_numeric - Compare two strings, treating sequences of digits as
+ /// numbers.
+ LLVM_NODISCARD
+ int compare_numeric(StringRef RHS) const;
+
+ /// Determine the edit distance between this string and another
+ /// string.
+ ///
+ /// \param Other the string to compare this string against.
+ ///
+ /// \param AllowReplacements whether to allow character
+ /// replacements (change one character into another) as a single
+ /// operation, rather than as two operations (an insertion and a
+ /// removal).
+ ///
+ /// \param MaxEditDistance If non-zero, the maximum edit distance that
+ /// this routine is allowed to compute. If the edit distance will exceed
+ /// that maximum, returns \c MaxEditDistance+1.
+ ///
+ /// \returns the minimum number of character insertions, removals,
+ /// or (if \p AllowReplacements is \c true) replacements needed to
+ /// transform one of the given strings into the other. If zero,
+ /// the strings are identical.
+ LLVM_NODISCARD
+ unsigned edit_distance(StringRef Other, bool AllowReplacements = true,
+ unsigned MaxEditDistance = 0) const;
+
+ /// str - Get the contents as an std::string.
+ LLVM_NODISCARD
+ std::string str() const {
+ if (!Data) return std::string();
+ return std::string(Data, Length);
+ }
+
+ /// @}
+ /// @name Operator Overloads
+ /// @{
+
+ LLVM_NODISCARD
+ char operator[](size_t Index) const {
+ assert(Index < Length && "Invalid index!");
+ return Data[Index];
+ }
+
+ /// Disallow accidental assignment from a temporary std::string.
+ ///
+ /// The declaration here is extra complicated so that `stringRef = {}`
+ /// and `stringRef = "abc"` continue to select the move assignment operator.
+ template <typename T>
+ typename std::enable_if<std::is_same<T, std::string>::value,
+ StringRef>::type &
+ operator=(T &&Str) = delete;
+
+ /// @}
+ /// @name Type Conversions
+ /// @{
+
+ operator std::string() const {
+ return str();
+ }
+
+ /// @}
+ /// @name String Predicates
+ /// @{
+
+ /// Check if this string starts with the given \p Prefix.
+ LLVM_NODISCARD
+ bool startswith(StringRef Prefix) const {
+ return Length >= Prefix.Length &&
+ compareMemory(Data, Prefix.Data, Prefix.Length) == 0;
+ }
+
+ /// Check if this string starts with the given \p Prefix, ignoring case.
+ LLVM_NODISCARD
+ bool startswith_lower(StringRef Prefix) const;
+
+ /// Check if this string ends with the given \p Suffix.
+ LLVM_NODISCARD
+ bool endswith(StringRef Suffix) const {
+ return Length >= Suffix.Length &&
+ compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0;
+ }
+
+ /// Check if this string ends with the given \p Suffix, ignoring case.
+ LLVM_NODISCARD
+ bool endswith_lower(StringRef Suffix) const;
+
+ /// @}
+ /// @name String Searching
+ /// @{
+
+ /// Search for the first character \p C in the string.
+ ///
+ /// \returns The index of the first occurrence of \p C, or npos if not
+ /// found.
+ LLVM_NODISCARD
+ size_t find(char C, size_t From = 0) const {
+ size_t FindBegin = std::min(From, Length);
+ if (FindBegin < Length) { // Avoid calling memchr with nullptr.
+ // Just forward to memchr, which is faster than a hand-rolled loop.
+ if (const void *P = ::memchr(Data + FindBegin, C, Length - FindBegin))
+ return static_cast<const char *>(P) - Data;
+ }
+ return npos;
+ }
+
+ /// Search for the first character \p C in the string, ignoring case.
+ ///
+ /// \returns The index of the first occurrence of \p C, or npos if not
+ /// found.
+ LLVM_NODISCARD
+ size_t find_lower(char C, size_t From = 0) const;
+
+ /// Search for the first character satisfying the predicate \p F
+ ///
+ /// \returns The index of the first character satisfying \p F starting from
+ /// \p From, or npos if not found.
+ LLVM_NODISCARD
+ size_t find_if(function_ref<bool(char)> F, size_t From = 0) const {
+ StringRef S = drop_front(From);
+ while (!S.empty()) {
+ if (F(S.front()))
+ return size() - S.size();
+ S = S.drop_front();
+ }
+ return npos;
+ }
+
+ /// Search for the first character not satisfying the predicate \p F
+ ///
+ /// \returns The index of the first character not satisfying \p F starting
+ /// from \p From, or npos if not found.
+ LLVM_NODISCARD
+ size_t find_if_not(function_ref<bool(char)> F, size_t From = 0) const {
+ return find_if([F](char c) { return !F(c); }, From);
+ }
+
+ /// Search for the first string \p Str in the string.
+ ///
+ /// \returns The index of the first occurrence of \p Str, or npos if not
+ /// found.
+ LLVM_NODISCARD
+ size_t find(StringRef Str, size_t From = 0) const;
+
+ /// Search for the first string \p Str in the string, ignoring case.
+ ///
+ /// \returns The index of the first occurrence of \p Str, or npos if not
+ /// found.
+ LLVM_NODISCARD
+ size_t find_lower(StringRef Str, size_t From = 0) const;
+
+ /// Search for the last character \p C in the string.
+ ///
+ /// \returns The index of the last occurrence of \p C, or npos if not
+ /// found.
+ LLVM_NODISCARD
+ size_t rfind(char C, size_t From = npos) const {
+ From = std::min(From, Length);
+ size_t i = From;
+ while (i != 0) {
+ --i;
+ if (Data[i] == C)
+ return i;
+ }
+ return npos;
+ }
+
+ /// Search for the last character \p C in the string, ignoring case.
+ ///
+ /// \returns The index of the last occurrence of \p C, or npos if not
+ /// found.
+ LLVM_NODISCARD
+ size_t rfind_lower(char C, size_t From = npos) const;
+
+ /// Search for the last string \p Str in the string.
+ ///
+ /// \returns The index of the last occurrence of \p Str, or npos if not
+ /// found.
+ LLVM_NODISCARD
+ size_t rfind(StringRef Str) const;
+
+ /// Search for the last string \p Str in the string, ignoring case.
+ ///
+ /// \returns The index of the last occurrence of \p Str, or npos if not
+ /// found.
+ LLVM_NODISCARD
+ size_t rfind_lower(StringRef Str) const;
+
+ /// Find the first character in the string that is \p C, or npos if not
+ /// found. Same as find.
+ LLVM_NODISCARD
+ size_t find_first_of(char C, size_t From = 0) const {
+ return find(C, From);
+ }
+
+ /// Find the first character in the string that is in \p Chars, or npos if
+ /// not found.
+ ///
+ /// Complexity: O(size() + Chars.size())
+ LLVM_NODISCARD
+ size_t find_first_of(StringRef Chars, size_t From = 0) const;
+
+ /// Find the first character in the string that is not \p C or npos if not
+ /// found.
+ LLVM_NODISCARD
+ size_t find_first_not_of(char C, size_t From = 0) const;
+
+ /// Find the first character in the string that is not in the string
+ /// \p Chars, or npos if not found.
+ ///
+ /// Complexity: O(size() + Chars.size())
+ LLVM_NODISCARD
+ size_t find_first_not_of(StringRef Chars, size_t From = 0) const;
+
+ /// Find the last character in the string that is \p C, or npos if not
+ /// found.
+ LLVM_NODISCARD
+ size_t find_last_of(char C, size_t From = npos) const {
+ return rfind(C, From);
+ }
+
+ /// Find the last character in the string that is in \p C, or npos if not
+ /// found.
+ ///
+ /// Complexity: O(size() + Chars.size())
+ LLVM_NODISCARD
+ size_t find_last_of(StringRef Chars, size_t From = npos) const;
+
+ /// Find the last character in the string that is not \p C, or npos if not
+ /// found.
+ LLVM_NODISCARD
+ size_t find_last_not_of(char C, size_t From = npos) const;
+
+ /// Find the last character in the string that is not in \p Chars, or
+ /// npos if not found.
+ ///
+ /// Complexity: O(size() + Chars.size())
+ LLVM_NODISCARD
+ size_t find_last_not_of(StringRef Chars, size_t From = npos) const;
+
+ /// Return true if the given string is a substring of *this, and false
+ /// otherwise.
+ LLVM_NODISCARD
+ bool contains(StringRef Other) const { return find(Other) != npos; }
+
+ /// Return true if the given character is contained in *this, and false
+ /// otherwise.
+ LLVM_NODISCARD
+ bool contains(char C) const { return find_first_of(C) != npos; }
+
+ /// Return true if the given string is a substring of *this, and false
+ /// otherwise.
+ LLVM_NODISCARD
+ bool contains_lower(StringRef Other) const {
+ return find_lower(Other) != npos;
+ }
+
+ /// Return true if the given character is contained in *this, and false
+ /// otherwise.
+ LLVM_NODISCARD
+ bool contains_lower(char C) const { return find_lower(C) != npos; }
+
+ /// @}
+ /// @name Helpful Algorithms
+ /// @{
+
+ /// Return the number of occurrences of \p C in the string.
+ LLVM_NODISCARD
+ size_t count(char C) const {
+ size_t Count = 0;
+ for (size_t i = 0, e = Length; i != e; ++i)
+ if (Data[i] == C)
+ ++Count;
+ return Count;
+ }
+
+ /// Return the number of non-overlapped occurrences of \p Str in
+ /// the string.
+ size_t count(StringRef Str) const;
+
+ /// Parse the current string as an integer of the specified radix. If
+ /// \p Radix is specified as zero, this does radix autosensing using
+ /// extended C rules: 0 is octal, 0x is hex, 0b is binary.
+ ///
+ /// If the string is invalid or if only a subset of the string is valid,
+ /// this returns true to signify the error. The string is considered
+ /// erroneous if empty or if it overflows T.
+ template <typename T>
+ typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type
+ getAsInteger(unsigned Radix, T &Result) const {
+ long long LLVal;
+ if (getAsSignedInteger(*this, Radix, LLVal) ||
+ static_cast<T>(LLVal) != LLVal)
+ return true;
+ Result = LLVal;
+ return false;
+ }
+
+ template <typename T>
+ typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
+ getAsInteger(unsigned Radix, T &Result) const {
+ unsigned long long ULLVal;
+ // The additional cast to unsigned long long is required to avoid the
+ // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type
+ // 'unsigned __int64' when instantiating getAsInteger with T = bool.
+ if (getAsUnsignedInteger(*this, Radix, ULLVal) ||
+ static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal)
+ return true;
+ Result = ULLVal;
+ return false;
+ }
+
+ /// Parse the current string as an integer of the specified radix. If
+ /// \p Radix is specified as zero, this does radix autosensing using
+ /// extended C rules: 0 is octal, 0x is hex, 0b is binary.
+ ///
+ /// If the string does not begin with a number of the specified radix,
+ /// this returns true to signify the error. The string is considered
+ /// erroneous if empty or if it overflows T.
+ /// The portion of the string representing the discovered numeric value
+ /// is removed from the beginning of the string.
+ template <typename T>
+ typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type
+ consumeInteger(unsigned Radix, T &Result) {
+ long long LLVal;
+ if (consumeSignedInteger(*this, Radix, LLVal) ||
+ static_cast<long long>(static_cast<T>(LLVal)) != LLVal)
+ return true;
+ Result = LLVal;
+ return false;
+ }
+
+ template <typename T>
+ typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
+ consumeInteger(unsigned Radix, T &Result) {
+ unsigned long long ULLVal;
+ if (consumeUnsignedInteger(*this, Radix, ULLVal) ||
+ static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal)
+ return true;
+ Result = ULLVal;
+ return false;
+ }
+
+ /// Parse the current string as an integer of the specified \p Radix, or of
+ /// an autosensed radix if the \p Radix given is 0. The current value in
+ /// \p Result is discarded, and the storage is changed to be wide enough to
+ /// store the parsed integer.
+ ///
+ /// \returns true if the string does not solely consist of a valid
+ /// non-empty number in the appropriate base.
+ ///
+ /// APInt::fromString is superficially similar but assumes the
+ /// string is well-formed in the given radix.
+ bool getAsInteger(unsigned Radix, APInt &Result) const;
+
+ /// Parse the current string as an IEEE double-precision floating
+ /// point value. The string must be a well-formed double.
+ ///
+ /// If \p AllowInexact is false, the function will fail if the string
+ /// cannot be represented exactly. Otherwise, the function only fails
+ /// in case of an overflow or underflow.
+ bool getAsDouble(double &Result, bool AllowInexact = true) const;
+
+ /// @}
+ /// @name String Operations
+ /// @{
+
+ // Convert the given ASCII string to lowercase.
+ LLVM_NODISCARD
+ std::string lower() const;
+
+ /// Convert the given ASCII string to uppercase.
+ LLVM_NODISCARD
+ std::string upper() const;
+
+ /// @}
+ /// @name Substring Operations
+ /// @{
+
+ /// Return a reference to the substring from [Start, Start + N).
+ ///
+ /// \param Start The index of the starting character in the substring; if
+ /// the index is npos or greater than the length of the string then the
+ /// empty substring will be returned.
+ ///
+ /// \param N The number of characters to included in the substring. If N
+ /// exceeds the number of characters remaining in the string, the string
+ /// suffix (starting with \p Start) will be returned.
+ LLVM_NODISCARD
+ StringRef substr(size_t Start, size_t N = npos) const {
+ Start = std::min(Start, Length);
+ return StringRef(Data + Start, std::min(N, Length - Start));
+ }
+
+ /// Return a StringRef equal to 'this' but with only the first \p N
+ /// elements remaining. If \p N is greater than the length of the
+ /// string, the entire string is returned.
+ LLVM_NODISCARD
+ StringRef take_front(size_t N = 1) const {
+ if (N >= size())
+ return *this;
+ return drop_back(size() - N);
+ }
+
+ /// Return a StringRef equal to 'this' but with only the last \p N
+ /// elements remaining. If \p N is greater than the length of the
+ /// string, the entire string is returned.
+ LLVM_NODISCARD
+ StringRef take_back(size_t N = 1) const {
+ if (N >= size())
+ return *this;
+ return drop_front(size() - N);
+ }
+
+ /// Return the longest prefix of 'this' such that every character
+ /// in the prefix satisfies the given predicate.
+ LLVM_NODISCARD
+ StringRef take_while(function_ref<bool(char)> F) const {
+ return substr(0, find_if_not(F));
+ }
+
+ /// Return the longest prefix of 'this' such that no character in
+ /// the prefix satisfies the given predicate.
+ LLVM_NODISCARD
+ StringRef take_until(function_ref<bool(char)> F) const {
+ return substr(0, find_if(F));
+ }
+
+ /// Return a StringRef equal to 'this' but with the first \p N elements
+ /// dropped.
+ LLVM_NODISCARD
+ StringRef drop_front(size_t N = 1) const {
+ assert(size() >= N && "Dropping more elements than exist");
+ return substr(N);
+ }
+
+ /// Return a StringRef equal to 'this' but with the last \p N elements
+ /// dropped.
+ LLVM_NODISCARD
+ StringRef drop_back(size_t N = 1) const {
+ assert(size() >= N && "Dropping more elements than exist");
+ return substr(0, size()-N);
+ }
+
+ /// Return a StringRef equal to 'this', but with all characters satisfying
+ /// the given predicate dropped from the beginning of the string.
+ LLVM_NODISCARD
+ StringRef drop_while(function_ref<bool(char)> F) const {
+ return substr(find_if_not(F));
+ }
+
+ /// Return a StringRef equal to 'this', but with all characters not
+ /// satisfying the given predicate dropped from the beginning of the string.
+ LLVM_NODISCARD
+ StringRef drop_until(function_ref<bool(char)> F) const {
+ return substr(find_if(F));
+ }
+
+ /// Returns true if this StringRef has the given prefix and removes that
+ /// prefix.
+ bool consume_front(StringRef Prefix) {
+ if (!startswith(Prefix))
+ return false;
+
+ *this = drop_front(Prefix.size());
+ return true;
+ }
+
+ /// Returns true if this StringRef has the given suffix and removes that
+ /// suffix.
+ bool consume_back(StringRef Suffix) {
+ if (!endswith(Suffix))
+ return false;
+
+ *this = drop_back(Suffix.size());
+ return true;
+ }
+
+ /// Return a reference to the substring from [Start, End).
+ ///
+ /// \param Start The index of the starting character in the substring; if
+ /// the index is npos or greater than the length of the string then the
+ /// empty substring will be returned.
+ ///
+ /// \param End The index following the last character to include in the
+ /// substring. If this is npos or exceeds the number of characters
+ /// remaining in the string, the string suffix (starting with \p Start)
+ /// will be returned. If this is less than \p Start, an empty string will
+ /// be returned.
+ LLVM_NODISCARD
+ StringRef slice(size_t Start, size_t End) const {
+ Start = std::min(Start, Length);
+ End = std::min(std::max(Start, End), Length);
+ return StringRef(Data + Start, End - Start);
+ }
+
+ /// Split into two substrings around the first occurrence of a separator
+ /// character.
+ ///
+ /// If \p Separator is in the string, then the result is a pair (LHS, RHS)
+ /// such that (*this == LHS + Separator + RHS) is true and RHS is
+ /// maximal. If \p Separator is not in the string, then the result is a
+ /// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
+ ///
+ /// \param Separator The character to split on.
+ /// \returns The split substrings.
+ LLVM_NODISCARD
+ std::pair<StringRef, StringRef> split(char Separator) const {
+ return split(StringRef(&Separator, 1));
+ }
+
+ /// Split into two substrings around the first occurrence of a separator
+ /// string.
+ ///
+ /// If \p Separator is in the string, then the result is a pair (LHS, RHS)
+ /// such that (*this == LHS + Separator + RHS) is true and RHS is
+ /// maximal. If \p Separator is not in the string, then the result is a
+ /// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
+ ///
+ /// \param Separator - The string to split on.
+ /// \return - The split substrings.
+ LLVM_NODISCARD
+ std::pair<StringRef, StringRef> split(StringRef Separator) const {
+ size_t Idx = find(Separator);
+ if (Idx == npos)
+ return std::make_pair(*this, StringRef());
+ return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos));
+ }
+
+ /// Split into two substrings around the last occurrence of a separator
+ /// string.
+ ///
+ /// If \p Separator is in the string, then the result is a pair (LHS, RHS)
+ /// such that (*this == LHS + Separator + RHS) is true and RHS is
+ /// minimal. If \p Separator is not in the string, then the result is a
+ /// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
+ ///
+ /// \param Separator - The string to split on.
+ /// \return - The split substrings.
+ LLVM_NODISCARD
+ std::pair<StringRef, StringRef> rsplit(StringRef Separator) const {
+ size_t Idx = rfind(Separator);
+ if (Idx == npos)
+ return std::make_pair(*this, StringRef());
+ return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos));
+ }
+
+ /// Split into substrings around the occurrences of a separator string.
+ ///
+ /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most
+ /// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1
+ /// elements are added to A.
+ /// If \p KeepEmpty is false, empty strings are not added to \p A. They
+ /// still count when considering \p MaxSplit
+ /// An useful invariant is that
+ /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true
+ ///
+ /// \param A - Where to put the substrings.
+ /// \param Separator - The string to split on.
+ /// \param MaxSplit - The maximum number of times the string is split.
+ /// \param KeepEmpty - True if empty substring should be added.
+ void split(SmallVectorImpl<StringRef> &A,
+ StringRef Separator, int MaxSplit = -1,
+ bool KeepEmpty = true) const;
+
+ /// Split into substrings around the occurrences of a separator character.
+ ///
+ /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most
+ /// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1
+ /// elements are added to A.
+ /// If \p KeepEmpty is false, empty strings are not added to \p A. They
+ /// still count when considering \p MaxSplit
+ /// An useful invariant is that
+ /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true
+ ///
+ /// \param A - Where to put the substrings.
+ /// \param Separator - The string to split on.
+ /// \param MaxSplit - The maximum number of times the string is split.
+ /// \param KeepEmpty - True if empty substring should be added.
+ void split(SmallVectorImpl<StringRef> &A, char Separator, int MaxSplit = -1,
+ bool KeepEmpty = true) const;
+
+ /// Split into two substrings around the last occurrence of a separator
+ /// character.
+ ///
+ /// If \p Separator is in the string, then the result is a pair (LHS, RHS)
+ /// such that (*this == LHS + Separator + RHS) is true and RHS is
+ /// minimal. If \p Separator is not in the string, then the result is a
+ /// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
+ ///
+ /// \param Separator - The character to split on.
+ /// \return - The split substrings.
+ LLVM_NODISCARD
+ std::pair<StringRef, StringRef> rsplit(char Separator) const {
+ return rsplit(StringRef(&Separator, 1));
+ }
+
+ /// Return string with consecutive \p Char characters starting from the
+ /// the left removed.
+ LLVM_NODISCARD
+ StringRef ltrim(char Char) const {
+ return drop_front(std::min(Length, find_first_not_of(Char)));
+ }
+
+ /// Return string with consecutive characters in \p Chars starting from
+ /// the left removed.
+ LLVM_NODISCARD
+ StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const {
+ return drop_front(std::min(Length, find_first_not_of(Chars)));
+ }
+
+ /// Return string with consecutive \p Char characters starting from the
+ /// right removed.
+ LLVM_NODISCARD
+ StringRef rtrim(char Char) const {
+ return drop_back(Length - std::min(Length, find_last_not_of(Char) + 1));
+ }
+
+ /// Return string with consecutive characters in \p Chars starting from
+ /// the right removed.
+ LLVM_NODISCARD
+ StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const {
+ return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1));
+ }
+
+ /// Return string with consecutive \p Char characters starting from the
+ /// left and right removed.
+ LLVM_NODISCARD
+ StringRef trim(char Char) const {
+ return ltrim(Char).rtrim(Char);
+ }
+
+ /// Return string with consecutive characters in \p Chars starting from
+ /// the left and right removed.
+ LLVM_NODISCARD
+ StringRef trim(StringRef Chars = " \t\n\v\f\r") const {
+ return ltrim(Chars).rtrim(Chars);
+ }
+
+ /// @}
+ };
+
+ /// A wrapper around a string literal that serves as a proxy for constructing
+ /// global tables of StringRefs with the length computed at compile time.
+ /// In order to avoid the invocation of a global constructor, StringLiteral
+ /// should *only* be used in a constexpr context, as such:
+ ///
+ /// constexpr StringLiteral S("test");
+ ///
+ class StringLiteral : public StringRef {
+ private:
+ constexpr StringLiteral(const char *Str, size_t N) : StringRef(Str, N) {
+ }
+
+ public:
+ template <size_t N>
+ constexpr StringLiteral(const char (&Str)[N])
+#if defined(__clang__) && __has_attribute(enable_if)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgcc-compat"
+ __attribute((enable_if(__builtin_strlen(Str) == N - 1,
+ "invalid string literal")))
+#pragma clang diagnostic pop
+#endif
+ : StringRef(Str, N - 1) {
+ }
+
+ // Explicit construction for strings like "foo\0bar".
+ template <size_t N>
+ static constexpr StringLiteral withInnerNUL(const char (&Str)[N]) {
+ return StringLiteral(Str, N - 1);
+ }
+ };
+
+ /// @name StringRef Comparison Operators
+ /// @{
+
+ inline bool operator==(StringRef LHS, StringRef RHS) {
+ return LHS.equals(RHS);
+ }
+
+ inline bool operator!=(StringRef LHS, StringRef RHS) { return !(LHS == RHS); }
+
+ inline bool operator<(StringRef LHS, StringRef RHS) {
+ return LHS.compare(RHS) == -1;
+ }
+
+ inline bool operator<=(StringRef LHS, StringRef RHS) {
+ return LHS.compare(RHS) != 1;
+ }
+
+ inline bool operator>(StringRef LHS, StringRef RHS) {
+ return LHS.compare(RHS) == 1;
+ }
+
+ inline bool operator>=(StringRef LHS, StringRef RHS) {
+ return LHS.compare(RHS) != -1;
+ }
+
+ inline std::string &operator+=(std::string &buffer, StringRef string) {
+ return buffer.append(string.data(), string.size());
+ }
+
+ /// @}
+
+ /// Compute a hash_code for a StringRef.
+ LLVM_NODISCARD
+ hash_code hash_value(StringRef S);
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_STRINGREF_H
diff --git a/third_party/llvm-project/include/llvm/ADT/StringSet.h b/third_party/llvm-project/include/llvm/ADT/StringSet.h
new file mode 100644
index 000000000..60be09d3c
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/StringSet.h
@@ -0,0 +1,58 @@
+//===- StringSet.h - The LLVM Compiler Driver -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// StringSet - A set-like wrapper for the StringMap.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STRINGSET_H
+#define LLVM_ADT_STRINGSET_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+#include <initializer_list>
+#include <utility>
+
+namespace llvm {
+
+ /// StringSet - A wrapper for StringMap that provides set-like functionality.
+ template <class AllocatorTy = MallocAllocator>
+ class StringSet : public StringMap<NoneType, AllocatorTy> {
+ using base = StringMap<NoneType, AllocatorTy>;
+
+ public:
+ StringSet() = default;
+ StringSet(std::initializer_list<StringRef> S) {
+ for (StringRef X : S)
+ insert(X);
+ }
+ explicit StringSet(AllocatorTy A) : base(A) {}
+
+ std::pair<typename base::iterator, bool> insert(StringRef Key) {
+ assert(!Key.empty());
+ return base::insert(std::make_pair(Key, None));
+ }
+
+ template <typename InputIt>
+ void insert(const InputIt &Begin, const InputIt &End) {
+ for (auto It = Begin; It != End; ++It)
+ base::insert(std::make_pair(*It, None));
+ }
+
+ template <typename ValueTy>
+ std::pair<typename base::iterator, bool>
+ insert(const StringMapEntry<ValueTy> &MapEntry) {
+ return insert(MapEntry.getKey());
+ }
+ };
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_STRINGSET_H
diff --git a/third_party/llvm-project/include/llvm/ADT/StringSwitch.h b/third_party/llvm-project/include/llvm/ADT/StringSwitch.h
new file mode 100644
index 000000000..fea911f69
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/StringSwitch.h
@@ -0,0 +1,196 @@
+//===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//===----------------------------------------------------------------------===/
+//
+// This file implements the StringSwitch template, which mimics a switch()
+// statement whose cases are string literals.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_ADT_STRINGSWITCH_H
+#define LLVM_ADT_STRINGSWITCH_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <cstring>
+
+namespace llvm {
+
+/// A switch()-like statement whose cases are string literals.
+///
+/// The StringSwitch class is a simple form of a switch() statement that
+/// determines whether the given string matches one of the given string
+/// literals. The template type parameter \p T is the type of the value that
+/// will be returned from the string-switch expression. For example,
+/// the following code switches on the name of a color in \c argv[i]:
+///
+/// \code
+/// Color color = StringSwitch<Color>(argv[i])
+/// .Case("red", Red)
+/// .Case("orange", Orange)
+/// .Case("yellow", Yellow)
+/// .Case("green", Green)
+/// .Case("blue", Blue)
+/// .Case("indigo", Indigo)
+/// .Cases("violet", "purple", Violet)
+/// .Default(UnknownColor);
+/// \endcode
+template<typename T, typename R = T>
+class StringSwitch {
+ /// The string we are matching.
+ const StringRef Str;
+
+ /// The pointer to the result of this switch statement, once known,
+ /// null before that.
+ Optional<T> Result;
+
+public:
+ explicit StringSwitch(StringRef S)
+ : Str(S), Result() { }
+
+ // StringSwitch is not copyable.
+ StringSwitch(const StringSwitch &) = delete;
+
+ // StringSwitch is not assignable due to 'Str' being 'const'.
+ void operator=(const StringSwitch &) = delete;
+ void operator=(StringSwitch &&other) = delete;
+
+ StringSwitch(StringSwitch &&other)
+ : Str(other.Str), Result(std::move(other.Result)) { }
+
+ ~StringSwitch() = default;
+
+ // Case-sensitive case matchers
+ StringSwitch &Case(StringLiteral S, T Value) {
+ if (!Result && Str == S) {
+ Result = std::move(Value);
+ }
+ return *this;
+ }
+
+ StringSwitch& EndsWith(StringLiteral S, T Value) {
+ if (!Result && Str.endswith(S)) {
+ Result = std::move(Value);
+ }
+ return *this;
+ }
+
+ StringSwitch& StartsWith(StringLiteral S, T Value) {
+ if (!Result && Str.startswith(S)) {
+ Result = std::move(Value);
+ }
+ return *this;
+ }
+
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, T Value) {
+ return Case(S0, Value).Case(S1, Value);
+ }
+
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ T Value) {
+ return Case(S0, Value).Cases(S1, S2, Value);
+ }
+
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, T Value) {
+ return Case(S0, Value).Cases(S1, S2, S3, Value);
+ }
+
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, T Value) {
+ return Case(S0, Value).Cases(S1, S2, S3, S4, Value);
+ }
+
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ T Value) {
+ return Case(S0, Value).Cases(S1, S2, S3, S4, S5, Value);
+ }
+
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, T Value) {
+ return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, Value);
+ }
+
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, StringLiteral S7, T Value) {
+ return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, Value);
+ }
+
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, StringLiteral S7, StringLiteral S8,
+ T Value) {
+ return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value);
+ }
+
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, StringLiteral S7, StringLiteral S8,
+ StringLiteral S9, T Value) {
+ return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, S9, Value);
+ }
+
+ // Case-insensitive case matchers.
+ StringSwitch &CaseLower(StringLiteral S, T Value) {
+ if (!Result && Str.equals_lower(S))
+ Result = std::move(Value);
+
+ return *this;
+ }
+
+ StringSwitch &EndsWithLower(StringLiteral S, T Value) {
+ if (!Result && Str.endswith_lower(S))
+ Result = Value;
+
+ return *this;
+ }
+
+ StringSwitch &StartsWithLower(StringLiteral S, T Value) {
+ if (!Result && Str.startswith_lower(S))
+ Result = std::move(Value);
+
+ return *this;
+ }
+
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, T Value) {
+ return CaseLower(S0, Value).CaseLower(S1, Value);
+ }
+
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ T Value) {
+ return CaseLower(S0, Value).CasesLower(S1, S2, Value);
+ }
+
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, T Value) {
+ return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value);
+ }
+
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, T Value) {
+ return CaseLower(S0, Value).CasesLower(S1, S2, S3, S4, Value);
+ }
+
+ LLVM_NODISCARD
+ R Default(T Value) {
+ if (Result)
+ return std::move(*Result);
+ return Value;
+ }
+
+ LLVM_NODISCARD
+ operator R() {
+ assert(Result && "Fell off the end of a string-switch");
+ return std::move(*Result);
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_STRINGSWITCH_H
diff --git a/third_party/llvm-project/include/llvm/ADT/Triple.h b/third_party/llvm-project/include/llvm/ADT/Triple.h
new file mode 100644
index 000000000..edeb31efa
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/Triple.h
@@ -0,0 +1,881 @@
+//===-- llvm/ADT/Triple.h - Target triple helper class ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_TRIPLE_H
+#define LLVM_ADT_TRIPLE_H
+
+#include "llvm/ADT/Twine.h"
+
+// Some system headers or GCC predefined macros conflict with identifiers in
+// this file. Undefine them here.
+#undef NetBSD
+#undef mips
+#undef sparc
+
+namespace llvm {
+
+/// Triple - Helper class for working with autoconf configuration names. For
+/// historical reasons, we also call these 'triples' (they used to contain
+/// exactly three fields).
+///
+/// Configuration names are strings in the canonical form:
+/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM
+/// or
+/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT
+///
+/// This class is used for clients which want to support arbitrary
+/// configuration names, but also want to implement certain special
+/// behavior for particular configurations. This class isolates the mapping
+/// from the components of the configuration name to well known IDs.
+///
+/// At its core the Triple class is designed to be a wrapper for a triple
+/// string; the constructor does not change or normalize the triple string.
+/// Clients that need to handle the non-canonical triples that users often
+/// specify should use the normalize method.
+///
+/// See autoconf/config.guess for a glimpse into what configuration names
+/// look like in practice.
+class Triple {
+public:
+ enum ArchType {
+ UnknownArch,
+
+ arm, // ARM (little endian): arm, armv.*, xscale
+ armeb, // ARM (big endian): armeb
+ aarch64, // AArch64 (little endian): aarch64
+ aarch64_be, // AArch64 (big endian): aarch64_be
+ aarch64_32, // AArch64 (little endian) ILP32: aarch64_32
+ arc, // ARC: Synopsys ARC
+ avr, // AVR: Atmel AVR microcontroller
+ bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
+ bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
+ hexagon, // Hexagon: hexagon
+ mips, // MIPS: mips, mipsallegrex, mipsr6
+ mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el
+ mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6
+ mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el
+ msp430, // MSP430: msp430
+ ppc, // PPC: powerpc
+ ppc64, // PPC64: powerpc64, ppu
+ ppc64le, // PPC64LE: powerpc64le
+ r600, // R600: AMD GPUs HD2XXX - HD6XXX
+ amdgcn, // AMDGCN: AMD GCN GPUs
+ riscv32, // RISC-V (32-bit): riscv32
+ riscv64, // RISC-V (64-bit): riscv64
+ sparc, // Sparc: sparc
+ sparcv9, // Sparcv9: Sparcv9
+ sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
+ systemz, // SystemZ: s390x
+ tce, // TCE (http://tce.cs.tut.fi/): tce
+ tcele, // TCE little endian (http://tce.cs.tut.fi/): tcele
+ thumb, // Thumb (little endian): thumb, thumbv.*
+ thumbeb, // Thumb (big endian): thumbeb
+ x86, // X86: i[3-9]86
+ x86_64, // X86-64: amd64, x86_64
+ xcore, // XCore: xcore
+ nvptx, // NVPTX: 32-bit
+ nvptx64, // NVPTX: 64-bit
+ le32, // le32: generic little-endian 32-bit CPU (PNaCl)
+ le64, // le64: generic little-endian 64-bit CPU (PNaCl)
+ amdil, // AMDIL
+ amdil64, // AMDIL with 64-bit pointers
+ hsail, // AMD HSAIL
+ hsail64, // AMD HSAIL with 64-bit pointers
+ spir, // SPIR: standard portable IR for OpenCL 32-bit version
+ spir64, // SPIR: standard portable IR for OpenCL 64-bit version
+ kalimba, // Kalimba: generic kalimba
+ shave, // SHAVE: Movidius vector VLIW processors
+ lanai, // Lanai: Lanai 32-bit
+ wasm32, // WebAssembly with 32-bit pointers
+ wasm64, // WebAssembly with 64-bit pointers
+ renderscript32, // 32-bit RenderScript
+ renderscript64, // 64-bit RenderScript
+ LastArchType = renderscript64
+ };
+ enum SubArchType {
+ NoSubArch,
+
+ ARMSubArch_v8_5a,
+ ARMSubArch_v8_4a,
+ ARMSubArch_v8_3a,
+ ARMSubArch_v8_2a,
+ ARMSubArch_v8_1a,
+ ARMSubArch_v8,
+ ARMSubArch_v8r,
+ ARMSubArch_v8m_baseline,
+ ARMSubArch_v8m_mainline,
+ ARMSubArch_v8_1m_mainline,
+ ARMSubArch_v7,
+ ARMSubArch_v7em,
+ ARMSubArch_v7m,
+ ARMSubArch_v7s,
+ ARMSubArch_v7k,
+ ARMSubArch_v7ve,
+ ARMSubArch_v6,
+ ARMSubArch_v6m,
+ ARMSubArch_v6k,
+ ARMSubArch_v6t2,
+ ARMSubArch_v5,
+ ARMSubArch_v5te,
+ ARMSubArch_v4t,
+
+ KalimbaSubArch_v3,
+ KalimbaSubArch_v4,
+ KalimbaSubArch_v5,
+
+ MipsSubArch_r6
+ };
+ enum VendorType {
+ UnknownVendor,
+
+ Apple,
+ PC,
+ SCEI,
+ BGP,
+ BGQ,
+ Freescale,
+ IBM,
+ ImaginationTechnologies,
+ MipsTechnologies,
+ NVIDIA,
+ CSR,
+ Myriad,
+ AMD,
+ Mesa,
+ SUSE,
+ OpenEmbedded,
+ LastVendorType = OpenEmbedded
+ };
+ enum OSType {
+ UnknownOS,
+
+ Ananas,
+ CloudABI,
+ Darwin,
+ DragonFly,
+ FreeBSD,
+ Fuchsia,
+ IOS,
+ KFreeBSD,
+ Linux,
+ Lv2, // PS3
+ MacOSX,
+ NetBSD,
+ OpenBSD,
+ Solaris,
+ Win32,
+ Haiku,
+ Minix,
+ RTEMS,
+ NaCl, // Native Client
+ CNK, // BG/P Compute-Node Kernel
+ AIX,
+ CUDA, // NVIDIA CUDA
+ NVCL, // NVIDIA OpenCL
+ AMDHSA, // AMD HSA Runtime
+ PS4,
+ ELFIAMCU,
+ TvOS, // Apple tvOS
+ WatchOS, // Apple watchOS
+ Mesa3D,
+ Contiki,
+ AMDPAL, // AMD PAL Runtime
+ HermitCore, // HermitCore Unikernel/Multikernel
+ Hurd, // GNU/Hurd
+ WASI, // Experimental WebAssembly OS
+ Emscripten,
+ LastOSType = Emscripten
+ };
+ enum EnvironmentType {
+ UnknownEnvironment,
+
+ GNU,
+ GNUABIN32,
+ GNUABI64,
+ GNUEABI,
+ GNUEABIHF,
+ GNUX32,
+ CODE16,
+ EABI,
+ EABIHF,
+ ELFv1,
+ ELFv2,
+ Android,
+ Musl,
+ MuslEABI,
+ MuslEABIHF,
+
+ MSVC,
+ Itanium,
+ Cygnus,
+ CoreCLR,
+ Simulator, // Simulator variants of other systems, e.g., Apple's iOS
+ MacABI, // Mac Catalyst variant of Apple's iOS deployment target.
+ LastEnvironmentType = MacABI
+ };
+ enum ObjectFormatType {
+ UnknownObjectFormat,
+
+ COFF,
+ ELF,
+ MachO,
+ Wasm,
+ XCOFF,
+ };
+
+private:
+ std::string Data;
+
+ /// The parsed arch type.
+ ArchType Arch;
+
+ /// The parsed subarchitecture type.
+ SubArchType SubArch;
+
+ /// The parsed vendor type.
+ VendorType Vendor;
+
+ /// The parsed OS type.
+ OSType OS;
+
+ /// The parsed Environment type.
+ EnvironmentType Environment;
+
+ /// The object format type.
+ ObjectFormatType ObjectFormat;
+
+public:
+ /// @name Constructors
+ /// @{
+
+ /// Default constructor is the same as an empty string and leaves all
+ /// triple fields unknown.
+ Triple()
+ : Data(), Arch(), SubArch(), Vendor(), OS(), Environment(),
+ ObjectFormat() {}
+
+ explicit Triple(const Twine &Str);
+ Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr);
+ Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,
+ const Twine &EnvironmentStr);
+
+ bool operator==(const Triple &Other) const {
+ return Arch == Other.Arch && SubArch == Other.SubArch &&
+ Vendor == Other.Vendor && OS == Other.OS &&
+ Environment == Other.Environment &&
+ ObjectFormat == Other.ObjectFormat;
+ }
+
+ bool operator!=(const Triple &Other) const {
+ return !(*this == Other);
+ }
+
+ /// @}
+ /// @name Normalization
+ /// @{
+
+ /// normalize - Turn an arbitrary machine specification into the canonical
+ /// triple form (or something sensible that the Triple class understands if
+ /// nothing better can reasonably be done). In particular, it handles the
+ /// common case in which otherwise valid components are in the wrong order.
+ static std::string normalize(StringRef Str);
+
+ /// Return the normalized form of this triple's string.
+ std::string normalize() const { return normalize(Data); }
+
+ /// @}
+ /// @name Typed Component Access
+ /// @{
+
+ /// getArch - Get the parsed architecture type of this triple.
+ ArchType getArch() const { return Arch; }
+
+ /// getSubArch - get the parsed subarchitecture type for this triple.
+ SubArchType getSubArch() const { return SubArch; }
+
+ /// getVendor - Get the parsed vendor type of this triple.
+ VendorType getVendor() const { return Vendor; }
+
+ /// getOS - Get the parsed operating system type of this triple.
+ OSType getOS() const { return OS; }
+
+ /// hasEnvironment - Does this triple have the optional environment
+ /// (fourth) component?
+ bool hasEnvironment() const {
+ return getEnvironmentName() != "";
+ }
+
+ /// getEnvironment - Get the parsed environment type of this triple.
+ EnvironmentType getEnvironment() const { return Environment; }
+
+ /// Parse the version number from the OS name component of the
+ /// triple, if present.
+ ///
+ /// For example, "fooos1.2.3" would return (1, 2, 3).
+ ///
+ /// If an entry is not defined, it will be returned as 0.
+ void getEnvironmentVersion(unsigned &Major, unsigned &Minor,
+ unsigned &Micro) const;
+
+ /// getFormat - Get the object format for this triple.
+ ObjectFormatType getObjectFormat() const { return ObjectFormat; }
+
+ /// getOSVersion - Parse the version number from the OS name component of the
+ /// triple, if present.
+ ///
+ /// For example, "fooos1.2.3" would return (1, 2, 3).
+ ///
+ /// If an entry is not defined, it will be returned as 0.
+ void getOSVersion(unsigned &Major, unsigned &Minor, unsigned &Micro) const;
+
+ /// getOSMajorVersion - Return just the major version number, this is
+ /// specialized because it is a common query.
+ unsigned getOSMajorVersion() const {
+ unsigned Maj, Min, Micro;
+ getOSVersion(Maj, Min, Micro);
+ return Maj;
+ }
+
+ /// getMacOSXVersion - Parse the version number as with getOSVersion and then
+ /// translate generic "darwin" versions to the corresponding OS X versions.
+ /// This may also be called with IOS triples but the OS X version number is
+ /// just set to a constant 10.4.0 in that case. Returns true if successful.
+ bool getMacOSXVersion(unsigned &Major, unsigned &Minor,
+ unsigned &Micro) const;
+
+ /// getiOSVersion - Parse the version number as with getOSVersion. This should
+ /// only be called with IOS or generic triples.
+ void getiOSVersion(unsigned &Major, unsigned &Minor,
+ unsigned &Micro) const;
+
+ /// getWatchOSVersion - Parse the version number as with getOSVersion. This
+ /// should only be called with WatchOS or generic triples.
+ void getWatchOSVersion(unsigned &Major, unsigned &Minor,
+ unsigned &Micro) const;
+
+ /// @}
+ /// @name Direct Component Access
+ /// @{
+
+ const std::string &str() const { return Data; }
+
+ const std::string &getTriple() const { return Data; }
+
+ /// getArchName - Get the architecture (first) component of the
+ /// triple.
+ StringRef getArchName() const;
+
+ /// getVendorName - Get the vendor (second) component of the triple.
+ StringRef getVendorName() const;
+
+ /// getOSName - Get the operating system (third) component of the
+ /// triple.
+ StringRef getOSName() const;
+
+ /// getEnvironmentName - Get the optional environment (fourth)
+ /// component of the triple, or "" if empty.
+ StringRef getEnvironmentName() const;
+
+ /// getOSAndEnvironmentName - Get the operating system and optional
+ /// environment components as a single string (separated by a '-'
+ /// if the environment component is present).
+ StringRef getOSAndEnvironmentName() const;
+
+ /// @}
+ /// @name Convenience Predicates
+ /// @{
+
+ /// Test whether the architecture is 64-bit
+ ///
+ /// Note that this tests for 64-bit pointer width, and nothing else. Note
+ /// that we intentionally expose only three predicates, 64-bit, 32-bit, and
+ /// 16-bit. The inner details of pointer width for particular architectures
+ /// is not summed up in the triple, and so only a coarse grained predicate
+ /// system is provided.
+ bool isArch64Bit() const;
+
+ /// Test whether the architecture is 32-bit
+ ///
+ /// Note that this tests for 32-bit pointer width, and nothing else.
+ bool isArch32Bit() const;
+
+ /// Test whether the architecture is 16-bit
+ ///
+ /// Note that this tests for 16-bit pointer width, and nothing else.
+ bool isArch16Bit() const;
+
+ /// isOSVersionLT - Helper function for doing comparisons against version
+ /// numbers included in the target triple.
+ bool isOSVersionLT(unsigned Major, unsigned Minor = 0,
+ unsigned Micro = 0) const {
+ unsigned LHS[3];
+ getOSVersion(LHS[0], LHS[1], LHS[2]);
+
+ if (LHS[0] != Major)
+ return LHS[0] < Major;
+ if (LHS[1] != Minor)
+ return LHS[1] < Minor;
+ if (LHS[2] != Micro)
+ return LHS[2] < Micro;
+
+ return false;
+ }
+
+ bool isOSVersionLT(const Triple &Other) const {
+ unsigned RHS[3];
+ Other.getOSVersion(RHS[0], RHS[1], RHS[2]);
+ return isOSVersionLT(RHS[0], RHS[1], RHS[2]);
+ }
+
+ /// isMacOSXVersionLT - Comparison function for checking OS X version
+ /// compatibility, which handles supporting skewed version numbering schemes
+ /// used by the "darwin" triples.
+ bool isMacOSXVersionLT(unsigned Major, unsigned Minor = 0,
+ unsigned Micro = 0) const {
+ assert(isMacOSX() && "Not an OS X triple!");
+
+ // If this is OS X, expect a sane version number.
+ if (getOS() == Triple::MacOSX)
+ return isOSVersionLT(Major, Minor, Micro);
+
+ // Otherwise, compare to the "Darwin" number.
+ assert(Major == 10 && "Unexpected major version");
+ return isOSVersionLT(Minor + 4, Micro, 0);
+ }
+
+ /// isMacOSX - Is this a Mac OS X triple. For legacy reasons, we support both
+ /// "darwin" and "osx" as OS X triples.
+ bool isMacOSX() const {
+ return getOS() == Triple::Darwin || getOS() == Triple::MacOSX;
+ }
+
+ /// Is this an iOS triple.
+ /// Note: This identifies tvOS as a variant of iOS. If that ever
+ /// changes, i.e., if the two operating systems diverge or their version
+ /// numbers get out of sync, that will need to be changed.
+ /// watchOS has completely different version numbers so it is not included.
+ bool isiOS() const {
+ return getOS() == Triple::IOS || isTvOS();
+ }
+
+ /// Is this an Apple tvOS triple.
+ bool isTvOS() const {
+ return getOS() == Triple::TvOS;
+ }
+
+ /// Is this an Apple watchOS triple.
+ bool isWatchOS() const {
+ return getOS() == Triple::WatchOS;
+ }
+
+ bool isWatchABI() const {
+ return getSubArch() == Triple::ARMSubArch_v7k;
+ }
+
+ /// isOSDarwin - Is this a "Darwin" OS (OS X, iOS, or watchOS).
+ bool isOSDarwin() const {
+ return isMacOSX() || isiOS() || isWatchOS();
+ }
+
+ bool isSimulatorEnvironment() const {
+ return getEnvironment() == Triple::Simulator;
+ }
+
+ bool isMacCatalystEnvironment() const {
+ return getEnvironment() == Triple::MacABI;
+ }
+
+ bool isOSNetBSD() const {
+ return getOS() == Triple::NetBSD;
+ }
+
+ bool isOSOpenBSD() const {
+ return getOS() == Triple::OpenBSD;
+ }
+
+ bool isOSFreeBSD() const {
+ return getOS() == Triple::FreeBSD;
+ }
+
+ bool isOSFuchsia() const {
+ return getOS() == Triple::Fuchsia;
+ }
+
+ bool isOSDragonFly() const { return getOS() == Triple::DragonFly; }
+
+ bool isOSSolaris() const {
+ return getOS() == Triple::Solaris;
+ }
+
+ bool isOSIAMCU() const {
+ return getOS() == Triple::ELFIAMCU;
+ }
+
+ bool isOSUnknown() const { return getOS() == Triple::UnknownOS; }
+
+ bool isGNUEnvironment() const {
+ EnvironmentType Env = getEnvironment();
+ return Env == Triple::GNU || Env == Triple::GNUABIN32 ||
+ Env == Triple::GNUABI64 || Env == Triple::GNUEABI ||
+ Env == Triple::GNUEABIHF || Env == Triple::GNUX32;
+ }
+
+ bool isOSContiki() const {
+ return getOS() == Triple::Contiki;
+ }
+
+ /// Tests whether the OS is Haiku.
+ bool isOSHaiku() const {
+ return getOS() == Triple::Haiku;
+ }
+
+ /// Tests whether the OS is Windows.
+ bool isOSWindows() const {
+ return getOS() == Triple::Win32;
+ }
+
+ /// Checks if the environment is MSVC.
+ bool isKnownWindowsMSVCEnvironment() const {
+ return isOSWindows() && getEnvironment() == Triple::MSVC;
+ }
+
+ /// Checks if the environment could be MSVC.
+ bool isWindowsMSVCEnvironment() const {
+ return isKnownWindowsMSVCEnvironment() ||
+ (isOSWindows() && getEnvironment() == Triple::UnknownEnvironment);
+ }
+
+ bool isWindowsCoreCLREnvironment() const {
+ return isOSWindows() && getEnvironment() == Triple::CoreCLR;
+ }
+
+ bool isWindowsItaniumEnvironment() const {
+ return isOSWindows() && getEnvironment() == Triple::Itanium;
+ }
+
+ bool isWindowsCygwinEnvironment() const {
+ return isOSWindows() && getEnvironment() == Triple::Cygnus;
+ }
+
+ bool isWindowsGNUEnvironment() const {
+ return isOSWindows() && getEnvironment() == Triple::GNU;
+ }
+
+ /// Tests for either Cygwin or MinGW OS
+ bool isOSCygMing() const {
+ return isWindowsCygwinEnvironment() || isWindowsGNUEnvironment();
+ }
+
+ /// Is this a "Windows" OS targeting a "MSVCRT.dll" environment.
+ bool isOSMSVCRT() const {
+ return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment() ||
+ isWindowsItaniumEnvironment();
+ }
+
+ /// Tests whether the OS is NaCl (Native Client)
+ bool isOSNaCl() const {
+ return getOS() == Triple::NaCl;
+ }
+
+ /// Tests whether the OS is Linux.
+ bool isOSLinux() const {
+ return getOS() == Triple::Linux;
+ }
+
+ /// Tests whether the OS is kFreeBSD.
+ bool isOSKFreeBSD() const {
+ return getOS() == Triple::KFreeBSD;
+ }
+
+ /// Tests whether the OS is Hurd.
+ bool isOSHurd() const {
+ return getOS() == Triple::Hurd;
+ }
+
+ /// Tests whether the OS is WASI.
+ bool isOSWASI() const {
+ return getOS() == Triple::WASI;
+ }
+
+ /// Tests whether the OS is Emscripten.
+ bool isOSEmscripten() const {
+ return getOS() == Triple::Emscripten;
+ }
+
+ /// Tests whether the OS uses glibc.
+ bool isOSGlibc() const {
+ return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD ||
+ getOS() == Triple::Hurd) &&
+ !isAndroid();
+ }
+
+ /// Tests whether the OS is AIX.
+ bool isOSAIX() const {
+ return getOS() == Triple::AIX;
+ }
+
+ /// Tests whether the OS uses the ELF binary format.
+ bool isOSBinFormatELF() const {
+ return getObjectFormat() == Triple::ELF;
+ }
+
+ /// Tests whether the OS uses the COFF binary format.
+ bool isOSBinFormatCOFF() const {
+ return getObjectFormat() == Triple::COFF;
+ }
+
+ /// Tests whether the environment is MachO.
+ bool isOSBinFormatMachO() const {
+ return getObjectFormat() == Triple::MachO;
+ }
+
+ /// Tests whether the OS uses the Wasm binary format.
+ bool isOSBinFormatWasm() const {
+ return getObjectFormat() == Triple::Wasm;
+ }
+
+ /// Tests whether the OS uses the XCOFF binary format.
+ bool isOSBinFormatXCOFF() const {
+ return getObjectFormat() == Triple::XCOFF;
+ }
+
+ /// Tests whether the target is the PS4 CPU
+ bool isPS4CPU() const {
+ return getArch() == Triple::x86_64 &&
+ getVendor() == Triple::SCEI &&
+ getOS() == Triple::PS4;
+ }
+
+ /// Tests whether the target is the PS4 platform
+ bool isPS4() const {
+ return getVendor() == Triple::SCEI &&
+ getOS() == Triple::PS4;
+ }
+
+ /// Tests whether the target is Android
+ bool isAndroid() const { return getEnvironment() == Triple::Android; }
+
+ bool isAndroidVersionLT(unsigned Major) const {
+ assert(isAndroid() && "Not an Android triple!");
+
+ unsigned Env[3];
+ getEnvironmentVersion(Env[0], Env[1], Env[2]);
+
+ // 64-bit targets did not exist before API level 21 (Lollipop).
+ if (isArch64Bit() && Env[0] < 21)
+ Env[0] = 21;
+
+ return Env[0] < Major;
+ }
+
+ /// Tests whether the environment is musl-libc
+ bool isMusl() const {
+ return getEnvironment() == Triple::Musl ||
+ getEnvironment() == Triple::MuslEABI ||
+ getEnvironment() == Triple::MuslEABIHF;
+ }
+
+ /// Tests whether the target is SPIR (32- or 64-bit).
+ bool isSPIR() const {
+ return getArch() == Triple::spir || getArch() == Triple::spir64;
+ }
+
+ /// Tests whether the target is NVPTX (32- or 64-bit).
+ bool isNVPTX() const {
+ return getArch() == Triple::nvptx || getArch() == Triple::nvptx64;
+ }
+
+ /// Tests whether the target is Thumb (little and big endian).
+ bool isThumb() const {
+ return getArch() == Triple::thumb || getArch() == Triple::thumbeb;
+ }
+
+ /// Tests whether the target is ARM (little and big endian).
+ bool isARM() const {
+ return getArch() == Triple::arm || getArch() == Triple::armeb;
+ }
+
+ /// Tests whether the target is AArch64 (little and big endian).
+ bool isAArch64() const {
+ return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be;
+ }
+
+ /// Tests whether the target is MIPS 32-bit (little and big endian).
+ bool isMIPS32() const {
+ return getArch() == Triple::mips || getArch() == Triple::mipsel;
+ }
+
+ /// Tests whether the target is MIPS 64-bit (little and big endian).
+ bool isMIPS64() const {
+ return getArch() == Triple::mips64 || getArch() == Triple::mips64el;
+ }
+
+ /// Tests whether the target is MIPS (little and big endian, 32- or 64-bit).
+ bool isMIPS() const {
+ return isMIPS32() || isMIPS64();
+ }
+
+ /// Tests whether the target is 64-bit PowerPC (little and big endian).
+ bool isPPC64() const {
+ return getArch() == Triple::ppc64 || getArch() == Triple::ppc64le;
+ }
+
+ /// Tests whether the target is RISC-V (32- and 64-bit).
+ bool isRISCV() const {
+ return getArch() == Triple::riscv32 || getArch() == Triple::riscv64;
+ }
+
+ /// Tests whether the target supports comdat
+ bool supportsCOMDAT() const {
+ return !isOSBinFormatMachO();
+ }
+
+ /// Tests whether the target uses emulated TLS as default.
+ bool hasDefaultEmulatedTLS() const {
+ return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment();
+ }
+
+ /// @}
+ /// @name Mutators
+ /// @{
+
+ /// setArch - Set the architecture (first) component of the triple
+ /// to a known type.
+ void setArch(ArchType Kind);
+
+ /// setVendor - Set the vendor (second) component of the triple to a
+ /// known type.
+ void setVendor(VendorType Kind);
+
+ /// setOS - Set the operating system (third) component of the triple
+ /// to a known type.
+ void setOS(OSType Kind);
+
+ /// setEnvironment - Set the environment (fourth) component of the triple
+ /// to a known type.
+ void setEnvironment(EnvironmentType Kind);
+
+ /// setObjectFormat - Set the object file format
+ void setObjectFormat(ObjectFormatType Kind);
+
+ /// setTriple - Set all components to the new triple \p Str.
+ void setTriple(const Twine &Str);
+
+ /// setArchName - Set the architecture (first) component of the
+ /// triple by name.
+ void setArchName(StringRef Str);
+
+ /// setVendorName - Set the vendor (second) component of the triple
+ /// by name.
+ void setVendorName(StringRef Str);
+
+ /// setOSName - Set the operating system (third) component of the
+ /// triple by name.
+ void setOSName(StringRef Str);
+
+ /// setEnvironmentName - Set the optional environment (fourth)
+ /// component of the triple by name.
+ void setEnvironmentName(StringRef Str);
+
+ /// setOSAndEnvironmentName - Set the operating system and optional
+ /// environment components with a single string.
+ void setOSAndEnvironmentName(StringRef Str);
+
+ /// @}
+ /// @name Helpers to build variants of a particular triple.
+ /// @{
+
+ /// Form a triple with a 32-bit variant of the current architecture.
+ ///
+ /// This can be used to move across "families" of architectures where useful.
+ ///
+ /// \returns A new triple with a 32-bit architecture or an unknown
+ /// architecture if no such variant can be found.
+ llvm::Triple get32BitArchVariant() const;
+
+ /// Form a triple with a 64-bit variant of the current architecture.
+ ///
+ /// This can be used to move across "families" of architectures where useful.
+ ///
+ /// \returns A new triple with a 64-bit architecture or an unknown
+ /// architecture if no such variant can be found.
+ llvm::Triple get64BitArchVariant() const;
+
+ /// Form a triple with a big endian variant of the current architecture.
+ ///
+ /// This can be used to move across "families" of architectures where useful.
+ ///
+ /// \returns A new triple with a big endian architecture or an unknown
+ /// architecture if no such variant can be found.
+ llvm::Triple getBigEndianArchVariant() const;
+
+ /// Form a triple with a little endian variant of the current architecture.
+ ///
+ /// This can be used to move across "families" of architectures where useful.
+ ///
+ /// \returns A new triple with a little endian architecture or an unknown
+ /// architecture if no such variant can be found.
+ llvm::Triple getLittleEndianArchVariant() const;
+
+ /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
+ ///
+ /// \param Arch the architecture name (e.g., "armv7s"). If it is an empty
+ /// string then the triple's arch name is used.
+ StringRef getARMCPUForArch(StringRef Arch = StringRef()) const;
+
+ /// Tests whether the target triple is little endian.
+ ///
+ /// \returns true if the triple is little endian, false otherwise.
+ bool isLittleEndian() const;
+
+ /// Test whether target triples are compatible.
+ bool isCompatibleWith(const Triple &Other) const;
+
+ /// Merge target triples.
+ std::string merge(const Triple &Other) const;
+
+ /// @}
+ /// @name Static helpers for IDs.
+ /// @{
+
+ /// getArchTypeName - Get the canonical name for the \p Kind architecture.
+ static StringRef getArchTypeName(ArchType Kind);
+
+ /// getArchTypePrefix - Get the "prefix" canonical name for the \p Kind
+ /// architecture. This is the prefix used by the architecture specific
+ /// builtins, and is suitable for passing to \see
+ /// Intrinsic::getIntrinsicForGCCBuiltin().
+ ///
+ /// \return - The architecture prefix, or 0 if none is defined.
+ static StringRef getArchTypePrefix(ArchType Kind);
+
+ /// getVendorTypeName - Get the canonical name for the \p Kind vendor.
+ static StringRef getVendorTypeName(VendorType Kind);
+
+ /// getOSTypeName - Get the canonical name for the \p Kind operating system.
+ static StringRef getOSTypeName(OSType Kind);
+
+ /// getEnvironmentTypeName - Get the canonical name for the \p Kind
+ /// environment.
+ static StringRef getEnvironmentTypeName(EnvironmentType Kind);
+
+ /// @}
+ /// @name Static helpers for converting alternate architecture names.
+ /// @{
+
+ /// getArchTypeForLLVMName - The canonical type for the given LLVM
+ /// architecture name (e.g., "x86").
+ static ArchType getArchTypeForLLVMName(StringRef Str);
+
+ /// @}
+};
+
+} // End llvm namespace
+
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/ADT/Twine.h b/third_party/llvm-project/include/llvm/ADT/Twine.h
new file mode 100644
index 000000000..2dc7486c9
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/Twine.h
@@ -0,0 +1,544 @@
+//===- Twine.h - Fast Temporary String Concatenation ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_TWINE_H
+#define LLVM_ADT_TWINE_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <cstdint>
+#include <string>
+
+namespace llvm {
+
+ class formatv_object_base;
+ class raw_ostream;
+
+ /// Twine - A lightweight data structure for efficiently representing the
+ /// concatenation of temporary values as strings.
+ ///
+ /// A Twine is a kind of rope, it represents a concatenated string using a
+ /// binary-tree, where the string is the preorder of the nodes. Since the
+ /// Twine can be efficiently rendered into a buffer when its result is used,
+ /// it avoids the cost of generating temporary values for intermediate string
+ /// results -- particularly in cases when the Twine result is never
+ /// required. By explicitly tracking the type of leaf nodes, we can also avoid
+ /// the creation of temporary strings for conversions operations (such as
+ /// appending an integer to a string).
+ ///
+ /// A Twine is not intended for use directly and should not be stored, its
+ /// implementation relies on the ability to store pointers to temporary stack
+ /// objects which may be deallocated at the end of a statement. Twines should
+ /// only be used accepted as const references in arguments, when an API wishes
+ /// to accept possibly-concatenated strings.
+ ///
+ /// Twines support a special 'null' value, which always concatenates to form
+ /// itself, and renders as an empty string. This can be returned from APIs to
+ /// effectively nullify any concatenations performed on the result.
+ ///
+ /// \b Implementation
+ ///
+ /// Given the nature of a Twine, it is not possible for the Twine's
+ /// concatenation method to construct interior nodes; the result must be
+ /// represented inside the returned value. For this reason a Twine object
+ /// actually holds two values, the left- and right-hand sides of a
+ /// concatenation. We also have nullary Twine objects, which are effectively
+ /// sentinel values that represent empty strings.
+ ///
+ /// Thus, a Twine can effectively have zero, one, or two children. The \see
+ /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for
+ /// testing the number of children.
+ ///
+ /// We maintain a number of invariants on Twine objects (FIXME: Why):
+ /// - Nullary twines are always represented with their Kind on the left-hand
+ /// side, and the Empty kind on the right-hand side.
+ /// - Unary twines are always represented with the value on the left-hand
+ /// side, and the Empty kind on the right-hand side.
+ /// - If a Twine has another Twine as a child, that child should always be
+ /// binary (otherwise it could have been folded into the parent).
+ ///
+ /// These invariants are check by \see isValid().
+ ///
+ /// \b Efficiency Considerations
+ ///
+ /// The Twine is designed to yield efficient and small code for common
+ /// situations. For this reason, the concat() method is inlined so that
+ /// concatenations of leaf nodes can be optimized into stores directly into a
+ /// single stack allocated object.
+ ///
+ /// In practice, not all compilers can be trusted to optimize concat() fully,
+ /// so we provide two additional methods (and accompanying operator+
+ /// overloads) to guarantee that particularly important cases (cstring plus
+ /// StringRef) codegen as desired.
+ class Twine {
+ /// NodeKind - Represent the type of an argument.
+ enum NodeKind : unsigned char {
+ /// An empty string; the result of concatenating anything with it is also
+ /// empty.
+ NullKind,
+
+ /// The empty string.
+ EmptyKind,
+
+ /// A pointer to a Twine instance.
+ TwineKind,
+
+ /// A pointer to a C string instance.
+ CStringKind,
+
+ /// A pointer to an std::string instance.
+ StdStringKind,
+
+ /// A pointer to a StringRef instance.
+ StringRefKind,
+
+ /// A pointer to a SmallString instance.
+ SmallStringKind,
+
+ /// A pointer to a formatv_object_base instance.
+ FormatvObjectKind,
+
+ /// A char value, to render as a character.
+ CharKind,
+
+ /// An unsigned int value, to render as an unsigned decimal integer.
+ DecUIKind,
+
+ /// An int value, to render as a signed decimal integer.
+ DecIKind,
+
+ /// A pointer to an unsigned long value, to render as an unsigned decimal
+ /// integer.
+ DecULKind,
+
+ /// A pointer to a long value, to render as a signed decimal integer.
+ DecLKind,
+
+ /// A pointer to an unsigned long long value, to render as an unsigned
+ /// decimal integer.
+ DecULLKind,
+
+ /// A pointer to a long long value, to render as a signed decimal integer.
+ DecLLKind,
+
+ /// A pointer to a uint64_t value, to render as an unsigned hexadecimal
+ /// integer.
+ UHexKind
+ };
+
+ union Child
+ {
+ const Twine *twine;
+ const char *cString;
+ const std::string *stdString;
+ const StringRef *stringRef;
+ const SmallVectorImpl<char> *smallString;
+ const formatv_object_base *formatvObject;
+ char character;
+ unsigned int decUI;
+ int decI;
+ const unsigned long *decUL;
+ const long *decL;
+ const unsigned long long *decULL;
+ const long long *decLL;
+ const uint64_t *uHex;
+ };
+
+ /// LHS - The prefix in the concatenation, which may be uninitialized for
+ /// Null or Empty kinds.
+ Child LHS = {0};
+
+ /// RHS - The suffix in the concatenation, which may be uninitialized for
+ /// Null or Empty kinds.
+ Child RHS = {0};
+
+ /// LHSKind - The NodeKind of the left hand side, \see getLHSKind().
+ NodeKind LHSKind = EmptyKind;
+
+ /// RHSKind - The NodeKind of the right hand side, \see getRHSKind().
+ NodeKind RHSKind = EmptyKind;
+
+ /// Construct a nullary twine; the kind must be NullKind or EmptyKind.
+ explicit Twine(NodeKind Kind) : LHSKind(Kind) {
+ assert(isNullary() && "Invalid kind!");
+ }
+
+ /// Construct a binary twine.
+ explicit Twine(const Twine &LHS, const Twine &RHS)
+ : LHSKind(TwineKind), RHSKind(TwineKind) {
+ this->LHS.twine = &LHS;
+ this->RHS.twine = &RHS;
+ assert(isValid() && "Invalid twine!");
+ }
+
+ /// Construct a twine from explicit values.
+ explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind)
+ : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) {
+ assert(isValid() && "Invalid twine!");
+ }
+
+ /// Check for the null twine.
+ bool isNull() const {
+ return getLHSKind() == NullKind;
+ }
+
+ /// Check for the empty twine.
+ bool isEmpty() const {
+ return getLHSKind() == EmptyKind;
+ }
+
+ /// Check if this is a nullary twine (null or empty).
+ bool isNullary() const {
+ return isNull() || isEmpty();
+ }
+
+ /// Check if this is a unary twine.
+ bool isUnary() const {
+ return getRHSKind() == EmptyKind && !isNullary();
+ }
+
+ /// Check if this is a binary twine.
+ bool isBinary() const {
+ return getLHSKind() != NullKind && getRHSKind() != EmptyKind;
+ }
+
+ /// Check if this is a valid twine (satisfying the invariants on
+ /// order and number of arguments).
+ bool isValid() const {
+ // Nullary twines always have Empty on the RHS.
+ if (isNullary() && getRHSKind() != EmptyKind)
+ return false;
+
+ // Null should never appear on the RHS.
+ if (getRHSKind() == NullKind)
+ return false;
+
+ // The RHS cannot be non-empty if the LHS is empty.
+ if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind)
+ return false;
+
+ // A twine child should always be binary.
+ if (getLHSKind() == TwineKind &&
+ !LHS.twine->isBinary())
+ return false;
+ if (getRHSKind() == TwineKind &&
+ !RHS.twine->isBinary())
+ return false;
+
+ return true;
+ }
+
+ /// Get the NodeKind of the left-hand side.
+ NodeKind getLHSKind() const { return LHSKind; }
+
+ /// Get the NodeKind of the right-hand side.
+ NodeKind getRHSKind() const { return RHSKind; }
+
+ /// Print one child from a twine.
+ void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const;
+
+ /// Print the representation of one child from a twine.
+ void printOneChildRepr(raw_ostream &OS, Child Ptr,
+ NodeKind Kind) const;
+
+ public:
+ /// @name Constructors
+ /// @{
+
+ /// Construct from an empty string.
+ /*implicit*/ Twine() {
+ assert(isValid() && "Invalid twine!");
+ }
+
+ Twine(const Twine &) = default;
+
+ /// Construct from a C string.
+ ///
+ /// We take care here to optimize "" into the empty twine -- this will be
+ /// optimized out for string constants. This allows Twine arguments have
+ /// default "" values, without introducing unnecessary string constants.
+ /*implicit*/ Twine(const char *Str) {
+ if (Str[0] != '\0') {
+ LHS.cString = Str;
+ LHSKind = CStringKind;
+ } else
+ LHSKind = EmptyKind;
+
+ assert(isValid() && "Invalid twine!");
+ }
+ /// Delete the implicit conversion from nullptr as Twine(const char *)
+ /// cannot take nullptr.
+ /*implicit*/ Twine(std::nullptr_t) = delete;
+
+ /// Construct from an std::string.
+ /*implicit*/ Twine(const std::string &Str) : LHSKind(StdStringKind) {
+ LHS.stdString = &Str;
+ assert(isValid() && "Invalid twine!");
+ }
+
+ /// Construct from a StringRef.
+ /*implicit*/ Twine(const StringRef &Str) : LHSKind(StringRefKind) {
+ LHS.stringRef = &Str;
+ assert(isValid() && "Invalid twine!");
+ }
+
+ /// Construct from a SmallString.
+ /*implicit*/ Twine(const SmallVectorImpl<char> &Str)
+ : LHSKind(SmallStringKind) {
+ LHS.smallString = &Str;
+ assert(isValid() && "Invalid twine!");
+ }
+
+ /// Construct from a formatv_object_base.
+ /*implicit*/ Twine(const formatv_object_base &Fmt)
+ : LHSKind(FormatvObjectKind) {
+ LHS.formatvObject = &Fmt;
+ assert(isValid() && "Invalid twine!");
+ }
+
+ /// Construct from a char.
+ explicit Twine(char Val) : LHSKind(CharKind) {
+ LHS.character = Val;
+ }
+
+ /// Construct from a signed char.
+ explicit Twine(signed char Val) : LHSKind(CharKind) {
+ LHS.character = static_cast<char>(Val);
+ }
+
+ /// Construct from an unsigned char.
+ explicit Twine(unsigned char Val) : LHSKind(CharKind) {
+ LHS.character = static_cast<char>(Val);
+ }
+
+ /// Construct a twine to print \p Val as an unsigned decimal integer.
+ explicit Twine(unsigned Val) : LHSKind(DecUIKind) {
+ LHS.decUI = Val;
+ }
+
+ /// Construct a twine to print \p Val as a signed decimal integer.
+ explicit Twine(int Val) : LHSKind(DecIKind) {
+ LHS.decI = Val;
+ }
+
+ /// Construct a twine to print \p Val as an unsigned decimal integer.
+ explicit Twine(const unsigned long &Val) : LHSKind(DecULKind) {
+ LHS.decUL = &Val;
+ }
+
+ /// Construct a twine to print \p Val as a signed decimal integer.
+ explicit Twine(const long &Val) : LHSKind(DecLKind) {
+ LHS.decL = &Val;
+ }
+
+ /// Construct a twine to print \p Val as an unsigned decimal integer.
+ explicit Twine(const unsigned long long &Val) : LHSKind(DecULLKind) {
+ LHS.decULL = &Val;
+ }
+
+ /// Construct a twine to print \p Val as a signed decimal integer.
+ explicit Twine(const long long &Val) : LHSKind(DecLLKind) {
+ LHS.decLL = &Val;
+ }
+
+ // FIXME: Unfortunately, to make sure this is as efficient as possible we
+ // need extra binary constructors from particular types. We can't rely on
+ // the compiler to be smart enough to fold operator+()/concat() down to the
+ // right thing. Yet.
+
+ /// Construct as the concatenation of a C string and a StringRef.
+ /*implicit*/ Twine(const char *LHS, const StringRef &RHS)
+ : LHSKind(CStringKind), RHSKind(StringRefKind) {
+ this->LHS.cString = LHS;
+ this->RHS.stringRef = &RHS;
+ assert(isValid() && "Invalid twine!");
+ }
+
+ /// Construct as the concatenation of a StringRef and a C string.
+ /*implicit*/ Twine(const StringRef &LHS, const char *RHS)
+ : LHSKind(StringRefKind), RHSKind(CStringKind) {
+ this->LHS.stringRef = &LHS;
+ this->RHS.cString = RHS;
+ assert(isValid() && "Invalid twine!");
+ }
+
+ /// Since the intended use of twines is as temporary objects, assignments
+ /// when concatenating might cause undefined behavior or stack corruptions
+ Twine &operator=(const Twine &) = delete;
+
+ /// Create a 'null' string, which is an empty string that always
+ /// concatenates to form another empty string.
+ static Twine createNull() {
+ return Twine(NullKind);
+ }
+
+ /// @}
+ /// @name Numeric Conversions
+ /// @{
+
+ // Construct a twine to print \p Val as an unsigned hexadecimal integer.
+ static Twine utohexstr(const uint64_t &Val) {
+ Child LHS, RHS;
+ LHS.uHex = &Val;
+ RHS.twine = nullptr;
+ return Twine(LHS, UHexKind, RHS, EmptyKind);
+ }
+
+ /// @}
+ /// @name Predicate Operations
+ /// @{
+
+ /// Check if this twine is trivially empty; a false return value does not
+ /// necessarily mean the twine is empty.
+ bool isTriviallyEmpty() const {
+ return isNullary();
+ }
+
+ /// Return true if this twine can be dynamically accessed as a single
+ /// StringRef value with getSingleStringRef().
+ bool isSingleStringRef() const {
+ if (getRHSKind() != EmptyKind) return false;
+
+ switch (getLHSKind()) {
+ case EmptyKind:
+ case CStringKind:
+ case StdStringKind:
+ case StringRefKind:
+ case SmallStringKind:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /// @}
+ /// @name String Operations
+ /// @{
+
+ Twine concat(const Twine &Suffix) const;
+
+ /// @}
+ /// @name Output & Conversion.
+ /// @{
+
+ /// Return the twine contents as a std::string.
+ std::string str() const;
+
+ /// Append the concatenated string into the given SmallString or SmallVector.
+ void toVector(SmallVectorImpl<char> &Out) const;
+
+ /// This returns the twine as a single StringRef. This method is only valid
+ /// if isSingleStringRef() is true.
+ StringRef getSingleStringRef() const {
+ assert(isSingleStringRef() &&"This cannot be had as a single stringref!");
+ switch (getLHSKind()) {
+ default: llvm_unreachable("Out of sync with isSingleStringRef");
+ case EmptyKind: return StringRef();
+ case CStringKind: return StringRef(LHS.cString);
+ case StdStringKind: return StringRef(*LHS.stdString);
+ case StringRefKind: return *LHS.stringRef;
+ case SmallStringKind:
+ return StringRef(LHS.smallString->data(), LHS.smallString->size());
+ }
+ }
+
+ /// This returns the twine as a single StringRef if it can be
+ /// represented as such. Otherwise the twine is written into the given
+ /// SmallVector and a StringRef to the SmallVector's data is returned.
+ StringRef toStringRef(SmallVectorImpl<char> &Out) const {
+ if (isSingleStringRef())
+ return getSingleStringRef();
+ toVector(Out);
+ return StringRef(Out.data(), Out.size());
+ }
+
+ /// This returns the twine as a single null terminated StringRef if it
+ /// can be represented as such. Otherwise the twine is written into the
+ /// given SmallVector and a StringRef to the SmallVector's data is returned.
+ ///
+ /// The returned StringRef's size does not include the null terminator.
+ StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const;
+
+ /// Write the concatenated string represented by this twine to the
+ /// stream \p OS.
+ void print(raw_ostream &OS) const;
+
+ /// Dump the concatenated string represented by this twine to stderr.
+ void dump() const;
+
+ /// Write the representation of this twine to the stream \p OS.
+ void printRepr(raw_ostream &OS) const;
+
+ /// Dump the representation of this twine to stderr.
+ void dumpRepr() const;
+
+ /// @}
+ };
+
+ /// @name Twine Inline Implementations
+ /// @{
+
+ inline Twine Twine::concat(const Twine &Suffix) const {
+ // Concatenation with null is null.
+ if (isNull() || Suffix.isNull())
+ return Twine(NullKind);
+
+ // Concatenation with empty yields the other side.
+ if (isEmpty())
+ return Suffix;
+ if (Suffix.isEmpty())
+ return *this;
+
+ // Otherwise we need to create a new node, taking care to fold in unary
+ // twines.
+ Child NewLHS, NewRHS;
+ NewLHS.twine = this;
+ NewRHS.twine = &Suffix;
+ NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind;
+ if (isUnary()) {
+ NewLHS = LHS;
+ NewLHSKind = getLHSKind();
+ }
+ if (Suffix.isUnary()) {
+ NewRHS = Suffix.LHS;
+ NewRHSKind = Suffix.getLHSKind();
+ }
+
+ return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind);
+ }
+
+ inline Twine operator+(const Twine &LHS, const Twine &RHS) {
+ return LHS.concat(RHS);
+ }
+
+ /// Additional overload to guarantee simplified codegen; this is equivalent to
+ /// concat().
+
+ inline Twine operator+(const char *LHS, const StringRef &RHS) {
+ return Twine(LHS, RHS);
+ }
+
+ /// Additional overload to guarantee simplified codegen; this is equivalent to
+ /// concat().
+
+ inline Twine operator+(const StringRef &LHS, const char *RHS) {
+ return Twine(LHS, RHS);
+ }
+
+ inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) {
+ RHS.print(OS);
+ return OS;
+ }
+
+ /// @}
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_TWINE_H
diff --git a/third_party/llvm-project/include/llvm/ADT/bit.h b/third_party/llvm-project/include/llvm/ADT/bit.h
new file mode 100644
index 000000000..a790d5ed2
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/bit.h
@@ -0,0 +1,58 @@
+//===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the C++20 <bit> header.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_BIT_H
+#define LLVM_ADT_BIT_H
+
+#include "llvm/Support/Compiler.h"
+#include <cstring>
+#include <type_traits>
+
+namespace llvm {
+
+// This implementation of bit_cast is different from the C++17 one in two ways:
+// - It isn't constexpr because that requires compiler support.
+// - It requires trivially-constructible To, to avoid UB in the implementation.
+template <typename To, typename From
+ , typename = typename std::enable_if<sizeof(To) == sizeof(From)>::type
+#if (__has_feature(is_trivially_constructible) && defined(_LIBCPP_VERSION)) || \
+ (defined(__GNUC__) && __GNUC__ >= 5)
+ , typename = typename std::is_trivially_constructible<To>::type
+#elif __has_feature(is_trivially_constructible)
+ , typename = typename std::enable_if<__is_trivially_constructible(To)>::type
+#else
+ // See comment below.
+#endif
+#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \
+ (defined(__GNUC__) && __GNUC__ >= 5)
+ , typename = typename std::enable_if<std::is_trivially_copyable<To>::value>::type
+ , typename = typename std::enable_if<std::is_trivially_copyable<From>::value>::type
+#elif __has_feature(is_trivially_copyable)
+ , typename = typename std::enable_if<__is_trivially_copyable(To)>::type
+ , typename = typename std::enable_if<__is_trivially_copyable(From)>::type
+#else
+// This case is GCC 4.x. clang with libc++ or libstdc++ never get here. Unlike
+// llvm/Support/type_traits.h's is_trivially_copyable we don't want to
+// provide a good-enough answer here: developers in that configuration will hit
+// compilation failures on the bots instead of locally. That's acceptable
+// because it's very few developers, and only until we move past C++11.
+#endif
+>
+inline To bit_cast(const From &from) noexcept {
+ To to;
+ std::memcpy(&to, &from, sizeof(To));
+ return to;
+}
+
+} // namespace llvm
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/ADT/edit_distance.h b/third_party/llvm-project/include/llvm/ADT/edit_distance.h
new file mode 100644
index 000000000..4f5134008
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/edit_distance.h
@@ -0,0 +1,102 @@
+//===-- llvm/ADT/edit_distance.h - Array edit distance function --- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a Levenshtein distance function that works for any two
+// sequences, with each element of each sequence being analogous to a character
+// in a string.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_EDIT_DISTANCE_H
+#define LLVM_ADT_EDIT_DISTANCE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include <algorithm>
+#include <memory>
+
+namespace llvm {
+
+/// Determine the edit distance between two sequences.
+///
+/// \param FromArray the first sequence to compare.
+///
+/// \param ToArray the second sequence to compare.
+///
+/// \param AllowReplacements whether to allow element replacements (change one
+/// element into another) as a single operation, rather than as two operations
+/// (an insertion and a removal).
+///
+/// \param MaxEditDistance If non-zero, the maximum edit distance that this
+/// routine is allowed to compute. If the edit distance will exceed that
+/// maximum, returns \c MaxEditDistance+1.
+///
+/// \returns the minimum number of element insertions, removals, or (if
+/// \p AllowReplacements is \c true) replacements needed to transform one of
+/// the given sequences into the other. If zero, the sequences are identical.
+template<typename T>
+unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray,
+ bool AllowReplacements = true,
+ unsigned MaxEditDistance = 0) {
+ // The algorithm implemented below is the "classic"
+ // dynamic-programming algorithm for computing the Levenshtein
+ // distance, which is described here:
+ //
+ // http://en.wikipedia.org/wiki/Levenshtein_distance
+ //
+ // Although the algorithm is typically described using an m x n
+ // array, only one row plus one element are used at a time, so this
+ // implementation just keeps one vector for the row. To update one entry,
+ // only the entries to the left, top, and top-left are needed. The left
+ // entry is in Row[x-1], the top entry is what's in Row[x] from the last
+ // iteration, and the top-left entry is stored in Previous.
+ typename ArrayRef<T>::size_type m = FromArray.size();
+ typename ArrayRef<T>::size_type n = ToArray.size();
+
+ const unsigned SmallBufferSize = 64;
+ unsigned SmallBuffer[SmallBufferSize];
+ std::unique_ptr<unsigned[]> Allocated;
+ unsigned *Row = SmallBuffer;
+ if (n + 1 > SmallBufferSize) {
+ Row = new unsigned[n + 1];
+ Allocated.reset(Row);
+ }
+
+ for (unsigned i = 1; i <= n; ++i)
+ Row[i] = i;
+
+ for (typename ArrayRef<T>::size_type y = 1; y <= m; ++y) {
+ Row[0] = y;
+ unsigned BestThisRow = Row[0];
+
+ unsigned Previous = y - 1;
+ for (typename ArrayRef<T>::size_type x = 1; x <= n; ++x) {
+ int OldRow = Row[x];
+ if (AllowReplacements) {
+ Row[x] = std::min(
+ Previous + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u),
+ std::min(Row[x-1], Row[x])+1);
+ }
+ else {
+ if (FromArray[y-1] == ToArray[x-1]) Row[x] = Previous;
+ else Row[x] = std::min(Row[x-1], Row[x]) + 1;
+ }
+ Previous = OldRow;
+ BestThisRow = std::min(BestThisRow, Row[x]);
+ }
+
+ if (MaxEditDistance && BestThisRow > MaxEditDistance)
+ return MaxEditDistance + 1;
+ }
+
+ unsigned Result = Row[n];
+ return Result;
+}
+
+} // End llvm namespace
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/ADT/fallible_iterator.h b/third_party/llvm-project/include/llvm/ADT/fallible_iterator.h
new file mode 100644
index 000000000..6501ad223
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/fallible_iterator.h
@@ -0,0 +1,243 @@
+//===--- fallible_iterator.h - Wrapper for fallible iterators ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_FALLIBLE_ITERATOR_H
+#define LLVM_ADT_FALLIBLE_ITERATOR_H
+
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Error.h"
+
+#include <type_traits>
+
+namespace llvm {
+
+/// A wrapper class for fallible iterators.
+///
+/// The fallible_iterator template wraps an underlying iterator-like class
+/// whose increment and decrement operations are replaced with fallible versions
+/// like:
+///
+/// @code{.cpp}
+/// Error inc();
+/// Error dec();
+/// @endcode
+///
+/// It produces an interface that is (mostly) compatible with a traditional
+/// c++ iterator, including ++ and -- operators that do not fail.
+///
+/// Instances of the wrapper are constructed with an instance of the
+/// underlying iterator and (for non-end iterators) a reference to an Error
+/// instance. If the underlying increment/decrement operations fail, the Error
+/// is returned via this reference, and the resulting iterator value set to an
+/// end-of-range sentinel value. This enables the following loop idiom:
+///
+/// @code{.cpp}
+/// class Archive { // E.g. Potentially malformed on-disk archive
+/// public:
+/// fallible_iterator<ArchiveChildItr> children_begin(Error &Err);
+/// fallible_iterator<ArchiveChildItr> children_end();
+/// iterator_range<fallible_iterator<ArchiveChildItr>>
+/// children(Error &Err) {
+/// return make_range(children_begin(Err), children_end());
+/// //...
+/// };
+///
+/// void walk(Archive &A) {
+/// Error Err = Error::success();
+/// for (auto &C : A.children(Err)) {
+/// // Loop body only entered when increment succeeds.
+/// }
+/// if (Err) {
+/// // handle error.
+/// }
+/// }
+/// @endcode
+///
+/// The wrapper marks the referenced Error as unchecked after each increment
+/// and/or decrement operation, and clears the unchecked flag when a non-end
+/// value is compared against end (since, by the increment invariant, not being
+/// an end value proves that there was no error, and is equivalent to checking
+/// that the Error is success). This allows early exits from the loop body
+/// without requiring redundant error checks.
+template <typename Underlying> class fallible_iterator {
+private:
+ template <typename T>
+ using enable_if_struct_deref_supported = std::enable_if<
+ !std::is_void<decltype(std::declval<T>().operator->())>::value,
+ decltype(std::declval<T>().operator->())>;
+
+public:
+ /// Construct a fallible iterator that *cannot* be used as an end-of-range
+ /// value.
+ ///
+ /// A value created by this method can be dereferenced, incremented,
+ /// decremented and compared, providing the underlying type supports it.
+ ///
+ /// The error that is passed in will be initially marked as checked, so if the
+ /// iterator is not used at all the Error need not be checked.
+ static fallible_iterator itr(Underlying I, Error &Err) {
+ (void)!!Err;
+ return fallible_iterator(std::move(I), &Err);
+ }
+
+ /// Construct a fallible iteratro that can be used as an end-of-range value.
+ ///
+ /// A value created by this method can be dereferenced (if the underlying
+ /// value points at a valid value) and compared, but not incremented or
+ /// decremented.
+ static fallible_iterator end(Underlying I) {
+ return fallible_iterator(std::move(I), nullptr);
+ }
+
+ /// Forward dereference to the underlying iterator.
+ auto operator*() -> decltype(*std::declval<Underlying>()) { return *I; }
+
+ /// Forward const dereference to the underlying iterator.
+ auto operator*() const -> decltype(*std::declval<const Underlying>()) {
+ return *I;
+ }
+
+ /// Forward structure dereference to the underlying iterator (if the
+ /// underlying iterator supports it).
+ template <typename T = Underlying>
+ typename enable_if_struct_deref_supported<T>::type operator->() {
+ return I.operator->();
+ }
+
+ /// Forward const structure dereference to the underlying iterator (if the
+ /// underlying iterator supports it).
+ template <typename T = Underlying>
+ typename enable_if_struct_deref_supported<const T>::type operator->() const {
+ return I.operator->();
+ }
+
+ /// Increment the fallible iterator.
+ ///
+ /// If the underlying 'inc' operation fails, this will set the Error value
+ /// and update this iterator value to point to end-of-range.
+ ///
+ /// The Error value is marked as needing checking, regardless of whether the
+ /// 'inc' operation succeeds or fails.
+ fallible_iterator &operator++() {
+ assert(getErrPtr() && "Cannot increment end iterator");
+ if (auto Err = I.inc())
+ handleError(std::move(Err));
+ else
+ resetCheckedFlag();
+ return *this;
+ }
+
+ /// Decrement the fallible iterator.
+ ///
+ /// If the underlying 'dec' operation fails, this will set the Error value
+ /// and update this iterator value to point to end-of-range.
+ ///
+ /// The Error value is marked as needing checking, regardless of whether the
+ /// 'dec' operation succeeds or fails.
+ fallible_iterator &operator--() {
+ assert(getErrPtr() && "Cannot decrement end iterator");
+ if (auto Err = I.dec())
+ handleError(std::move(Err));
+ else
+ resetCheckedFlag();
+ return *this;
+ }
+
+ /// Compare fallible iterators for equality.
+ ///
+ /// Returns true if both LHS and RHS are end-of-range values, or if both are
+ /// non-end-of-range values whose underlying iterator values compare equal.
+ ///
+ /// If this is a comparison between an end-of-range iterator and a
+ /// non-end-of-range iterator, then the Error (referenced by the
+ /// non-end-of-range value) is marked as checked: Since all
+ /// increment/decrement operations result in an end-of-range value, comparing
+ /// false against end-of-range is equivalent to checking that the Error value
+ /// is success. This flag management enables early returns from loop bodies
+ /// without redundant Error checks.
+ friend bool operator==(const fallible_iterator &LHS,
+ const fallible_iterator &RHS) {
+ // If both iterators are in the end state they compare
+ // equal, regardless of whether either is valid.
+ if (LHS.isEnd() && RHS.isEnd())
+ return true;
+
+ assert(LHS.isValid() && RHS.isValid() &&
+ "Invalid iterators can only be compared against end");
+
+ bool Equal = LHS.I == RHS.I;
+
+ // If the iterators differ and this is a comparison against end then mark
+ // the Error as checked.
+ if (!Equal) {
+ if (LHS.isEnd())
+ (void)!!*RHS.getErrPtr();
+ else
+ (void)!!*LHS.getErrPtr();
+ }
+
+ return Equal;
+ }
+
+ /// Compare fallible iterators for inequality.
+ ///
+ /// See notes for operator==.
+ friend bool operator!=(const fallible_iterator &LHS,
+ const fallible_iterator &RHS) {
+ return !(LHS == RHS);
+ }
+
+private:
+ fallible_iterator(Underlying I, Error *Err)
+ : I(std::move(I)), ErrState(Err, false) {}
+
+ Error *getErrPtr() const { return ErrState.getPointer(); }
+
+ bool isEnd() const { return getErrPtr() == nullptr; }
+
+ bool isValid() const { return !ErrState.getInt(); }
+
+ void handleError(Error Err) {
+ *getErrPtr() = std::move(Err);
+ ErrState.setPointer(nullptr);
+ ErrState.setInt(true);
+ }
+
+ void resetCheckedFlag() {
+ *getErrPtr() = Error::success();
+ }
+
+ Underlying I;
+ mutable PointerIntPair<Error *, 1> ErrState;
+};
+
+/// Convenience wrapper to make a fallible_iterator value from an instance
+/// of an underlying iterator and an Error reference.
+template <typename Underlying>
+fallible_iterator<Underlying> make_fallible_itr(Underlying I, Error &Err) {
+ return fallible_iterator<Underlying>::itr(std::move(I), Err);
+}
+
+/// Convenience wrapper to make a fallible_iterator end value from an instance
+/// of an underlying iterator.
+template <typename Underlying>
+fallible_iterator<Underlying> make_fallible_end(Underlying E) {
+ return fallible_iterator<Underlying>::end(std::move(E));
+}
+
+template <typename Underlying>
+iterator_range<fallible_iterator<Underlying>>
+make_fallible_range(Underlying I, Underlying E, Error &Err) {
+ return make_range(make_fallible_itr(std::move(I), Err),
+ make_fallible_end(std::move(E)));
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_FALLIBLE_ITERATOR_H
diff --git a/third_party/llvm-project/include/llvm/ADT/ilist_base.h b/third_party/llvm-project/include/llvm/ADT/ilist_base.h
new file mode 100644
index 000000000..b8c098b95
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/ilist_base.h
@@ -0,0 +1,92 @@
+//===- llvm/ADT/ilist_base.h - Intrusive List Base --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ILIST_BASE_H
+#define LLVM_ADT_ILIST_BASE_H
+
+#include "llvm/ADT/ilist_node_base.h"
+#include <cassert>
+
+namespace llvm {
+
+/// Implementations of list algorithms using ilist_node_base.
+template <bool EnableSentinelTracking> class ilist_base {
+public:
+ using node_base_type = ilist_node_base<EnableSentinelTracking>;
+
+ static void insertBeforeImpl(node_base_type &Next, node_base_type &N) {
+ node_base_type &Prev = *Next.getPrev();
+ N.setNext(&Next);
+ N.setPrev(&Prev);
+ Prev.setNext(&N);
+ Next.setPrev(&N);
+ }
+
+ static void removeImpl(node_base_type &N) {
+ node_base_type *Prev = N.getPrev();
+ node_base_type *Next = N.getNext();
+ Next->setPrev(Prev);
+ Prev->setNext(Next);
+
+ // Not strictly necessary, but helps catch a class of bugs.
+ N.setPrev(nullptr);
+ N.setNext(nullptr);
+ }
+
+ static void removeRangeImpl(node_base_type &First, node_base_type &Last) {
+ node_base_type *Prev = First.getPrev();
+ node_base_type *Final = Last.getPrev();
+ Last.setPrev(Prev);
+ Prev->setNext(&Last);
+
+ // Not strictly necessary, but helps catch a class of bugs.
+ First.setPrev(nullptr);
+ Final->setNext(nullptr);
+ }
+
+ static void transferBeforeImpl(node_base_type &Next, node_base_type &First,
+ node_base_type &Last) {
+ if (&Next == &Last || &First == &Last)
+ return;
+
+ // Position cannot be contained in the range to be transferred.
+ assert(&Next != &First &&
+ // Check for the most common mistake.
+ "Insertion point can't be one of the transferred nodes");
+
+ node_base_type &Final = *Last.getPrev();
+
+ // Detach from old list/position.
+ First.getPrev()->setNext(&Last);
+ Last.setPrev(First.getPrev());
+
+ // Splice [First, Final] into its new list/position.
+ node_base_type &Prev = *Next.getPrev();
+ Final.setNext(&Next);
+ First.setPrev(&Prev);
+ Prev.setNext(&First);
+ Next.setPrev(&Final);
+ }
+
+ template <class T> static void insertBefore(T &Next, T &N) {
+ insertBeforeImpl(Next, N);
+ }
+
+ template <class T> static void remove(T &N) { removeImpl(N); }
+ template <class T> static void removeRange(T &First, T &Last) {
+ removeRangeImpl(First, Last);
+ }
+
+ template <class T> static void transferBefore(T &Next, T &First, T &Last) {
+ transferBeforeImpl(Next, First, Last);
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_ILIST_BASE_H
diff --git a/third_party/llvm-project/include/llvm/ADT/ilist_iterator.h b/third_party/llvm-project/include/llvm/ADT/ilist_iterator.h
new file mode 100644
index 000000000..cbe5cefa9
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/ilist_iterator.h
@@ -0,0 +1,198 @@
+//===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ILIST_ITERATOR_H
+#define LLVM_ADT_ILIST_ITERATOR_H
+
+#include "llvm/ADT/ilist_node.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <type_traits>
+
+namespace llvm {
+
+namespace ilist_detail {
+
+/// Find const-correct node types.
+template <class OptionsT, bool IsConst> struct IteratorTraits;
+template <class OptionsT> struct IteratorTraits<OptionsT, false> {
+ using value_type = typename OptionsT::value_type;
+ using pointer = typename OptionsT::pointer;
+ using reference = typename OptionsT::reference;
+ using node_pointer = ilist_node_impl<OptionsT> *;
+ using node_reference = ilist_node_impl<OptionsT> &;
+};
+template <class OptionsT> struct IteratorTraits<OptionsT, true> {
+ using value_type = const typename OptionsT::value_type;
+ using pointer = typename OptionsT::const_pointer;
+ using reference = typename OptionsT::const_reference;
+ using node_pointer = const ilist_node_impl<OptionsT> *;
+ using node_reference = const ilist_node_impl<OptionsT> &;
+};
+
+template <bool IsReverse> struct IteratorHelper;
+template <> struct IteratorHelper<false> : ilist_detail::NodeAccess {
+ using Access = ilist_detail::NodeAccess;
+
+ template <class T> static void increment(T *&I) { I = Access::getNext(*I); }
+ template <class T> static void decrement(T *&I) { I = Access::getPrev(*I); }
+};
+template <> struct IteratorHelper<true> : ilist_detail::NodeAccess {
+ using Access = ilist_detail::NodeAccess;
+
+ template <class T> static void increment(T *&I) { I = Access::getPrev(*I); }
+ template <class T> static void decrement(T *&I) { I = Access::getNext(*I); }
+};
+
+} // end namespace ilist_detail
+
+/// Iterator for intrusive lists based on ilist_node.
+template <class OptionsT, bool IsReverse, bool IsConst>
+class ilist_iterator : ilist_detail::SpecificNodeAccess<OptionsT> {
+ friend ilist_iterator<OptionsT, IsReverse, !IsConst>;
+ friend ilist_iterator<OptionsT, !IsReverse, IsConst>;
+ friend ilist_iterator<OptionsT, !IsReverse, !IsConst>;
+
+ using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>;
+ using Access = ilist_detail::SpecificNodeAccess<OptionsT>;
+
+public:
+ using value_type = typename Traits::value_type;
+ using pointer = typename Traits::pointer;
+ using reference = typename Traits::reference;
+ using difference_type = ptrdiff_t;
+ using iterator_category = std::bidirectional_iterator_tag;
+ using const_pointer = typename OptionsT::const_pointer;
+ using const_reference = typename OptionsT::const_reference;
+
+private:
+ using node_pointer = typename Traits::node_pointer;
+ using node_reference = typename Traits::node_reference;
+
+ node_pointer NodePtr = nullptr;
+
+public:
+ /// Create from an ilist_node.
+ explicit ilist_iterator(node_reference N) : NodePtr(&N) {}
+
+ explicit ilist_iterator(pointer NP) : NodePtr(Access::getNodePtr(NP)) {}
+ explicit ilist_iterator(reference NR) : NodePtr(Access::getNodePtr(&NR)) {}
+ ilist_iterator() = default;
+
+ // This is templated so that we can allow constructing a const iterator from
+ // a nonconst iterator...
+ template <bool RHSIsConst>
+ ilist_iterator(
+ const ilist_iterator<OptionsT, IsReverse, RHSIsConst> &RHS,
+ typename std::enable_if<IsConst || !RHSIsConst, void *>::type = nullptr)
+ : NodePtr(RHS.NodePtr) {}
+
+ // This is templated so that we can allow assigning to a const iterator from
+ // a nonconst iterator...
+ template <bool RHSIsConst>
+ typename std::enable_if<IsConst || !RHSIsConst, ilist_iterator &>::type
+ operator=(const ilist_iterator<OptionsT, IsReverse, RHSIsConst> &RHS) {
+ NodePtr = RHS.NodePtr;
+ return *this;
+ }
+
+ /// Explicit conversion between forward/reverse iterators.
+ ///
+ /// Translate between forward and reverse iterators without changing range
+ /// boundaries. The resulting iterator will dereference (and have a handle)
+ /// to the previous node, which is somewhat unexpected; but converting the
+ /// two endpoints in a range will give the same range in reverse.
+ ///
+ /// This matches std::reverse_iterator conversions.
+ explicit ilist_iterator(
+ const ilist_iterator<OptionsT, !IsReverse, IsConst> &RHS)
+ : ilist_iterator(++RHS.getReverse()) {}
+
+ /// Get a reverse iterator to the same node.
+ ///
+ /// Gives a reverse iterator that will dereference (and have a handle) to the
+ /// same node. Converting the endpoint iterators in a range will give a
+ /// different range; for range operations, use the explicit conversions.
+ ilist_iterator<OptionsT, !IsReverse, IsConst> getReverse() const {
+ if (NodePtr)
+ return ilist_iterator<OptionsT, !IsReverse, IsConst>(*NodePtr);
+ return ilist_iterator<OptionsT, !IsReverse, IsConst>();
+ }
+
+ /// Const-cast.
+ ilist_iterator<OptionsT, IsReverse, false> getNonConst() const {
+ if (NodePtr)
+ return ilist_iterator<OptionsT, IsReverse, false>(
+ const_cast<typename ilist_iterator<OptionsT, IsReverse,
+ false>::node_reference>(*NodePtr));
+ return ilist_iterator<OptionsT, IsReverse, false>();
+ }
+
+ // Accessors...
+ reference operator*() const {
+ assert(!NodePtr->isKnownSentinel());
+ return *Access::getValuePtr(NodePtr);
+ }
+ pointer operator->() const { return &operator*(); }
+
+ // Comparison operators
+ friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) {
+ return LHS.NodePtr == RHS.NodePtr;
+ }
+ friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) {
+ return LHS.NodePtr != RHS.NodePtr;
+ }
+
+ // Increment and decrement operators...
+ ilist_iterator &operator--() {
+ NodePtr = IsReverse ? NodePtr->getNext() : NodePtr->getPrev();
+ return *this;
+ }
+ ilist_iterator &operator++() {
+ NodePtr = IsReverse ? NodePtr->getPrev() : NodePtr->getNext();
+ return *this;
+ }
+ ilist_iterator operator--(int) {
+ ilist_iterator tmp = *this;
+ --*this;
+ return tmp;
+ }
+ ilist_iterator operator++(int) {
+ ilist_iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ /// Get the underlying ilist_node.
+ node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
+
+ /// Check for end. Only valid if ilist_sentinel_tracking<true>.
+ bool isEnd() const { return NodePtr ? NodePtr->isSentinel() : false; }
+};
+
+template <typename From> struct simplify_type;
+
+/// Allow ilist_iterators to convert into pointers to a node automatically when
+/// used by the dyn_cast, cast, isa mechanisms...
+///
+/// FIXME: remove this, since there is no implicit conversion to NodeTy.
+template <class OptionsT, bool IsConst>
+struct simplify_type<ilist_iterator<OptionsT, false, IsConst>> {
+ using iterator = ilist_iterator<OptionsT, false, IsConst>;
+ using SimpleType = typename iterator::pointer;
+
+ static SimpleType getSimplifiedValue(const iterator &Node) { return &*Node; }
+};
+template <class OptionsT, bool IsConst>
+struct simplify_type<const ilist_iterator<OptionsT, false, IsConst>>
+ : simplify_type<ilist_iterator<OptionsT, false, IsConst>> {};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_ILIST_ITERATOR_H
diff --git a/third_party/llvm-project/include/llvm/ADT/ilist_node.h b/third_party/llvm-project/include/llvm/ADT/ilist_node.h
new file mode 100644
index 000000000..e040d9630
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/ilist_node.h
@@ -0,0 +1,305 @@
+//===- llvm/ADT/ilist_node.h - Intrusive Linked List Helper -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ilist_node class template, which is a convenient
+// base class for creating classes that can be used with ilists.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ILIST_NODE_H
+#define LLVM_ADT_ILIST_NODE_H
+
+#include "llvm/ADT/ilist_node_base.h"
+#include "llvm/ADT/ilist_node_options.h"
+
+namespace llvm {
+
+namespace ilist_detail {
+
+struct NodeAccess;
+
+} // end namespace ilist_detail
+
+template <class OptionsT, bool IsReverse, bool IsConst> class ilist_iterator;
+template <class OptionsT> class ilist_sentinel;
+
+/// Implementation for an ilist node.
+///
+/// Templated on an appropriate \a ilist_detail::node_options, usually computed
+/// by \a ilist_detail::compute_node_options.
+///
+/// This is a wrapper around \a ilist_node_base whose main purpose is to
+/// provide type safety: you can't insert nodes of \a ilist_node_impl into the
+/// wrong \a simple_ilist or \a iplist.
+template <class OptionsT> class ilist_node_impl : OptionsT::node_base_type {
+ using value_type = typename OptionsT::value_type;
+ using node_base_type = typename OptionsT::node_base_type;
+ using list_base_type = typename OptionsT::list_base_type;
+
+ friend typename OptionsT::list_base_type;
+ friend struct ilist_detail::NodeAccess;
+ friend class ilist_sentinel<OptionsT>;
+ friend class ilist_iterator<OptionsT, false, false>;
+ friend class ilist_iterator<OptionsT, false, true>;
+ friend class ilist_iterator<OptionsT, true, false>;
+ friend class ilist_iterator<OptionsT, true, true>;
+
+protected:
+ using self_iterator = ilist_iterator<OptionsT, false, false>;
+ using const_self_iterator = ilist_iterator<OptionsT, false, true>;
+ using reverse_self_iterator = ilist_iterator<OptionsT, true, false>;
+ using const_reverse_self_iterator = ilist_iterator<OptionsT, true, true>;
+
+ ilist_node_impl() = default;
+
+private:
+ ilist_node_impl *getPrev() {
+ return static_cast<ilist_node_impl *>(node_base_type::getPrev());
+ }
+
+ ilist_node_impl *getNext() {
+ return static_cast<ilist_node_impl *>(node_base_type::getNext());
+ }
+
+ const ilist_node_impl *getPrev() const {
+ return static_cast<ilist_node_impl *>(node_base_type::getPrev());
+ }
+
+ const ilist_node_impl *getNext() const {
+ return static_cast<ilist_node_impl *>(node_base_type::getNext());
+ }
+
+ void setPrev(ilist_node_impl *N) { node_base_type::setPrev(N); }
+ void setNext(ilist_node_impl *N) { node_base_type::setNext(N); }
+
+public:
+ self_iterator getIterator() { return self_iterator(*this); }
+ const_self_iterator getIterator() const { return const_self_iterator(*this); }
+
+ reverse_self_iterator getReverseIterator() {
+ return reverse_self_iterator(*this);
+ }
+
+ const_reverse_self_iterator getReverseIterator() const {
+ return const_reverse_self_iterator(*this);
+ }
+
+ // Under-approximation, but always available for assertions.
+ using node_base_type::isKnownSentinel;
+
+ /// Check whether this is the sentinel node.
+ ///
+ /// This requires sentinel tracking to be explicitly enabled. Use the
+ /// ilist_sentinel_tracking<true> option to get this API.
+ bool isSentinel() const {
+ static_assert(OptionsT::is_sentinel_tracking_explicit,
+ "Use ilist_sentinel_tracking<true> to enable isSentinel()");
+ return node_base_type::isSentinel();
+ }
+};
+
+/// An intrusive list node.
+///
+/// A base class to enable membership in intrusive lists, including \a
+/// simple_ilist, \a iplist, and \a ilist. The first template parameter is the
+/// \a value_type for the list.
+///
+/// An ilist node can be configured with compile-time options to change
+/// behaviour and/or add API.
+///
+/// By default, an \a ilist_node knows whether it is the list sentinel (an
+/// instance of \a ilist_sentinel) if and only if
+/// LLVM_ENABLE_ABI_BREAKING_CHECKS. The function \a isKnownSentinel() always
+/// returns \c false tracking is off. Sentinel tracking steals a bit from the
+/// "prev" link, which adds a mask operation when decrementing an iterator, but
+/// enables bug-finding assertions in \a ilist_iterator.
+///
+/// To turn sentinel tracking on all the time, pass in the
+/// ilist_sentinel_tracking<true> template parameter. This also enables the \a
+/// isSentinel() function. The same option must be passed to the intrusive
+/// list. (ilist_sentinel_tracking<false> turns sentinel tracking off all the
+/// time.)
+///
+/// A type can inherit from ilist_node multiple times by passing in different
+/// \a ilist_tag options. This allows a single instance to be inserted into
+/// multiple lists simultaneously, where each list is given the same tag.
+///
+/// \example
+/// struct A {};
+/// struct B {};
+/// struct N : ilist_node<N, ilist_tag<A>>, ilist_node<N, ilist_tag<B>> {};
+///
+/// void foo() {
+/// simple_ilist<N, ilist_tag<A>> ListA;
+/// simple_ilist<N, ilist_tag<B>> ListB;
+/// N N1;
+/// ListA.push_back(N1);
+/// ListB.push_back(N1);
+/// }
+/// \endexample
+///
+/// See \a is_valid_option for steps on adding a new option.
+template <class T, class... Options>
+class ilist_node
+ : public ilist_node_impl<
+ typename ilist_detail::compute_node_options<T, Options...>::type> {
+ static_assert(ilist_detail::check_options<Options...>::value,
+ "Unrecognized node option!");
+};
+
+namespace ilist_detail {
+
+/// An access class for ilist_node private API.
+///
+/// This gives access to the private parts of ilist nodes. Nodes for an ilist
+/// should friend this class if they inherit privately from ilist_node.
+///
+/// Using this class outside of the ilist implementation is unsupported.
+struct NodeAccess {
+protected:
+ template <class OptionsT>
+ static ilist_node_impl<OptionsT> *getNodePtr(typename OptionsT::pointer N) {
+ return N;
+ }
+
+ template <class OptionsT>
+ static const ilist_node_impl<OptionsT> *
+ getNodePtr(typename OptionsT::const_pointer N) {
+ return N;
+ }
+
+ template <class OptionsT>
+ static typename OptionsT::pointer getValuePtr(ilist_node_impl<OptionsT> *N) {
+ return static_cast<typename OptionsT::pointer>(N);
+ }
+
+ template <class OptionsT>
+ static typename OptionsT::const_pointer
+ getValuePtr(const ilist_node_impl<OptionsT> *N) {
+ return static_cast<typename OptionsT::const_pointer>(N);
+ }
+
+ template <class OptionsT>
+ static ilist_node_impl<OptionsT> *getPrev(ilist_node_impl<OptionsT> &N) {
+ return N.getPrev();
+ }
+
+ template <class OptionsT>
+ static ilist_node_impl<OptionsT> *getNext(ilist_node_impl<OptionsT> &N) {
+ return N.getNext();
+ }
+
+ template <class OptionsT>
+ static const ilist_node_impl<OptionsT> *
+ getPrev(const ilist_node_impl<OptionsT> &N) {
+ return N.getPrev();
+ }
+
+ template <class OptionsT>
+ static const ilist_node_impl<OptionsT> *
+ getNext(const ilist_node_impl<OptionsT> &N) {
+ return N.getNext();
+ }
+};
+
+template <class OptionsT> struct SpecificNodeAccess : NodeAccess {
+protected:
+ using pointer = typename OptionsT::pointer;
+ using const_pointer = typename OptionsT::const_pointer;
+ using node_type = ilist_node_impl<OptionsT>;
+
+ static node_type *getNodePtr(pointer N) {
+ return NodeAccess::getNodePtr<OptionsT>(N);
+ }
+
+ static const node_type *getNodePtr(const_pointer N) {
+ return NodeAccess::getNodePtr<OptionsT>(N);
+ }
+
+ static pointer getValuePtr(node_type *N) {
+ return NodeAccess::getValuePtr<OptionsT>(N);
+ }
+
+ static const_pointer getValuePtr(const node_type *N) {
+ return NodeAccess::getValuePtr<OptionsT>(N);
+ }
+};
+
+} // end namespace ilist_detail
+
+template <class OptionsT>
+class ilist_sentinel : public ilist_node_impl<OptionsT> {
+public:
+ ilist_sentinel() {
+ this->initializeSentinel();
+ reset();
+ }
+
+ void reset() {
+ this->setPrev(this);
+ this->setNext(this);
+ }
+
+ bool empty() const { return this == this->getPrev(); }
+};
+
+/// An ilist node that can access its parent list.
+///
+/// Requires \c NodeTy to have \a getParent() to find the parent node, and the
+/// \c ParentTy to have \a getSublistAccess() to get a reference to the list.
+template <typename NodeTy, typename ParentTy, class... Options>
+class ilist_node_with_parent : public ilist_node<NodeTy, Options...> {
+protected:
+ ilist_node_with_parent() = default;
+
+private:
+ /// Forward to NodeTy::getParent().
+ ///
+ /// Note: do not use the name "getParent()". We want a compile error
+ /// (instead of recursion) when the subclass fails to implement \a
+ /// getParent().
+ const ParentTy *getNodeParent() const {
+ return static_cast<const NodeTy *>(this)->getParent();
+ }
+
+public:
+ /// @name Adjacent Node Accessors
+ /// @{
+ /// Get the previous node, or \c nullptr for the list head.
+ NodeTy *getPrevNode() {
+ // Should be separated to a reused function, but then we couldn't use auto
+ // (and would need the type of the list).
+ const auto &List =
+ getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr));
+ return List.getPrevNode(*static_cast<NodeTy *>(this));
+ }
+
+ /// Get the previous node, or \c nullptr for the list head.
+ const NodeTy *getPrevNode() const {
+ return const_cast<ilist_node_with_parent *>(this)->getPrevNode();
+ }
+
+ /// Get the next node, or \c nullptr for the list tail.
+ NodeTy *getNextNode() {
+ // Should be separated to a reused function, but then we couldn't use auto
+ // (and would need the type of the list).
+ const auto &List =
+ getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr));
+ return List.getNextNode(*static_cast<NodeTy *>(this));
+ }
+
+ /// Get the next node, or \c nullptr for the list tail.
+ const NodeTy *getNextNode() const {
+ return const_cast<ilist_node_with_parent *>(this)->getNextNode();
+ }
+ /// @}
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_ILIST_NODE_H
diff --git a/third_party/llvm-project/include/llvm/ADT/ilist_node_base.h b/third_party/llvm-project/include/llvm/ADT/ilist_node_base.h
new file mode 100644
index 000000000..f6c518e6e
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/ilist_node_base.h
@@ -0,0 +1,52 @@
+//===- llvm/ADT/ilist_node_base.h - Intrusive List Node Base -----*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ILIST_NODE_BASE_H
+#define LLVM_ADT_ILIST_NODE_BASE_H
+
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace llvm {
+
+/// Base class for ilist nodes.
+///
+/// Optionally tracks whether this node is the sentinel.
+template <bool EnableSentinelTracking> class ilist_node_base;
+
+template <> class ilist_node_base<false> {
+ ilist_node_base *Prev = nullptr;
+ ilist_node_base *Next = nullptr;
+
+public:
+ void setPrev(ilist_node_base *Prev) { this->Prev = Prev; }
+ void setNext(ilist_node_base *Next) { this->Next = Next; }
+ ilist_node_base *getPrev() const { return Prev; }
+ ilist_node_base *getNext() const { return Next; }
+
+ bool isKnownSentinel() const { return false; }
+ void initializeSentinel() {}
+};
+
+template <> class ilist_node_base<true> {
+ PointerIntPair<ilist_node_base *, 1> PrevAndSentinel;
+ ilist_node_base *Next = nullptr;
+
+public:
+ void setPrev(ilist_node_base *Prev) { PrevAndSentinel.setPointer(Prev); }
+ void setNext(ilist_node_base *Next) { this->Next = Next; }
+ ilist_node_base *getPrev() const { return PrevAndSentinel.getPointer(); }
+ ilist_node_base *getNext() const { return Next; }
+
+ bool isSentinel() const { return PrevAndSentinel.getInt(); }
+ bool isKnownSentinel() const { return isSentinel(); }
+ void initializeSentinel() { PrevAndSentinel.setInt(true); }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_ILIST_NODE_BASE_H
diff --git a/third_party/llvm-project/include/llvm/ADT/ilist_node_options.h b/third_party/llvm-project/include/llvm/ADT/ilist_node_options.h
new file mode 100644
index 000000000..9b95cdbe0
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/ilist_node_options.h
@@ -0,0 +1,131 @@
+//===- llvm/ADT/ilist_node_options.h - ilist_node Options -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ILIST_NODE_OPTIONS_H
+#define LLVM_ADT_ILIST_NODE_OPTIONS_H
+
+#include "llvm/Config/abi-breaking.h"
+
+#include <type_traits>
+
+namespace llvm {
+
+template <bool EnableSentinelTracking> class ilist_node_base;
+template <bool EnableSentinelTracking> class ilist_base;
+
+/// Option to choose whether to track sentinels.
+///
+/// This option affects the ABI for the nodes. When not specified explicitly,
+/// the ABI depends on LLVM_ENABLE_ABI_BREAKING_CHECKS. Specify explicitly to
+/// enable \a ilist_node::isSentinel().
+template <bool EnableSentinelTracking> struct ilist_sentinel_tracking {};
+
+/// Option to specify a tag for the node type.
+///
+/// This option allows a single value type to be inserted in multiple lists
+/// simultaneously. See \a ilist_node for usage examples.
+template <class Tag> struct ilist_tag {};
+
+namespace ilist_detail {
+
+/// Helper trait for recording whether an option is specified explicitly.
+template <bool IsExplicit> struct explicitness {
+ static const bool is_explicit = IsExplicit;
+};
+typedef explicitness<true> is_explicit;
+typedef explicitness<false> is_implicit;
+
+/// Check whether an option is valid.
+///
+/// The steps for adding and enabling a new ilist option include:
+/// \li define the option, ilist_foo<Bar>, above;
+/// \li add new parameters for Bar to \a ilist_detail::node_options;
+/// \li add an extraction meta-function, ilist_detail::extract_foo;
+/// \li call extract_foo from \a ilist_detail::compute_node_options and pass it
+/// into \a ilist_detail::node_options; and
+/// \li specialize \c is_valid_option<ilist_foo<Bar>> to inherit from \c
+/// std::true_type to get static assertions passing in \a simple_ilist and \a
+/// ilist_node.
+template <class Option> struct is_valid_option : std::false_type {};
+
+/// Extract sentinel tracking option.
+///
+/// Look through \p Options for the \a ilist_sentinel_tracking option, with the
+/// default depending on LLVM_ENABLE_ABI_BREAKING_CHECKS.
+template <class... Options> struct extract_sentinel_tracking;
+template <bool EnableSentinelTracking, class... Options>
+struct extract_sentinel_tracking<
+ ilist_sentinel_tracking<EnableSentinelTracking>, Options...>
+ : std::integral_constant<bool, EnableSentinelTracking>, is_explicit {};
+template <class Option1, class... Options>
+struct extract_sentinel_tracking<Option1, Options...>
+ : extract_sentinel_tracking<Options...> {};
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+template <> struct extract_sentinel_tracking<> : std::true_type, is_implicit {};
+#else
+template <>
+struct extract_sentinel_tracking<> : std::false_type, is_implicit {};
+#endif
+template <bool EnableSentinelTracking>
+struct is_valid_option<ilist_sentinel_tracking<EnableSentinelTracking>>
+ : std::true_type {};
+
+/// Extract custom tag option.
+///
+/// Look through \p Options for the \a ilist_tag option, pulling out the
+/// custom tag type, using void as a default.
+template <class... Options> struct extract_tag;
+template <class Tag, class... Options>
+struct extract_tag<ilist_tag<Tag>, Options...> {
+ typedef Tag type;
+};
+template <class Option1, class... Options>
+struct extract_tag<Option1, Options...> : extract_tag<Options...> {};
+template <> struct extract_tag<> { typedef void type; };
+template <class Tag> struct is_valid_option<ilist_tag<Tag>> : std::true_type {};
+
+/// Check whether options are valid.
+///
+/// The conjunction of \a is_valid_option on each individual option.
+template <class... Options> struct check_options;
+template <> struct check_options<> : std::true_type {};
+template <class Option1, class... Options>
+struct check_options<Option1, Options...>
+ : std::integral_constant<bool, is_valid_option<Option1>::value &&
+ check_options<Options...>::value> {};
+
+/// Traits for options for \a ilist_node.
+///
+/// This is usually computed via \a compute_node_options.
+template <class T, bool EnableSentinelTracking, bool IsSentinelTrackingExplicit,
+ class TagT>
+struct node_options {
+ typedef T value_type;
+ typedef T *pointer;
+ typedef T &reference;
+ typedef const T *const_pointer;
+ typedef const T &const_reference;
+
+ static const bool enable_sentinel_tracking = EnableSentinelTracking;
+ static const bool is_sentinel_tracking_explicit = IsSentinelTrackingExplicit;
+ typedef TagT tag;
+ typedef ilist_node_base<enable_sentinel_tracking> node_base_type;
+ typedef ilist_base<enable_sentinel_tracking> list_base_type;
+};
+
+template <class T, class... Options> struct compute_node_options {
+ typedef node_options<T, extract_sentinel_tracking<Options...>::value,
+ extract_sentinel_tracking<Options...>::is_explicit,
+ typename extract_tag<Options...>::type>
+ type;
+};
+
+} // end namespace ilist_detail
+} // end namespace llvm
+
+#endif // LLVM_ADT_ILIST_NODE_OPTIONS_H
diff --git a/third_party/llvm-project/include/llvm/ADT/iterator.h b/third_party/llvm-project/include/llvm/ADT/iterator.h
new file mode 100644
index 000000000..467fd4c00
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/iterator.h
@@ -0,0 +1,366 @@
+//===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ITERATOR_H
+#define LLVM_ADT_ITERATOR_H
+
+#include "llvm/ADT/iterator_range.h"
+#include <algorithm>
+#include <cstddef>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+
+namespace llvm {
+
+/// CRTP base class which implements the entire standard iterator facade
+/// in terms of a minimal subset of the interface.
+///
+/// Use this when it is reasonable to implement most of the iterator
+/// functionality in terms of a core subset. If you need special behavior or
+/// there are performance implications for this, you may want to override the
+/// relevant members instead.
+///
+/// Note, one abstraction that this does *not* provide is implementing
+/// subtraction in terms of addition by negating the difference. Negation isn't
+/// always information preserving, and I can see very reasonable iterator
+/// designs where this doesn't work well. It doesn't really force much added
+/// boilerplate anyways.
+///
+/// Another abstraction that this doesn't provide is implementing increment in
+/// terms of addition of one. These aren't equivalent for all iterator
+/// categories, and respecting that adds a lot of complexity for little gain.
+///
+/// Classes wishing to use `iterator_facade_base` should implement the following
+/// methods:
+///
+/// Forward Iterators:
+/// (All of the following methods)
+/// - DerivedT &operator=(const DerivedT &R);
+/// - bool operator==(const DerivedT &R) const;
+/// - const T &operator*() const;
+/// - T &operator*();
+/// - DerivedT &operator++();
+///
+/// Bidirectional Iterators:
+/// (All methods of forward iterators, plus the following)
+/// - DerivedT &operator--();
+///
+/// Random-access Iterators:
+/// (All methods of bidirectional iterators excluding the following)
+/// - DerivedT &operator++();
+/// - DerivedT &operator--();
+/// (and plus the following)
+/// - bool operator<(const DerivedT &RHS) const;
+/// - DifferenceTypeT operator-(const DerivedT &R) const;
+/// - DerivedT &operator+=(DifferenceTypeT N);
+/// - DerivedT &operator-=(DifferenceTypeT N);
+///
+template <typename DerivedT, typename IteratorCategoryT, typename T,
+ typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *,
+ typename ReferenceT = T &>
+class iterator_facade_base
+ : public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT,
+ ReferenceT> {
+protected:
+ enum {
+ IsRandomAccess = std::is_base_of<std::random_access_iterator_tag,
+ IteratorCategoryT>::value,
+ IsBidirectional = std::is_base_of<std::bidirectional_iterator_tag,
+ IteratorCategoryT>::value,
+ };
+
+ /// A proxy object for computing a reference via indirecting a copy of an
+ /// iterator. This is used in APIs which need to produce a reference via
+ /// indirection but for which the iterator object might be a temporary. The
+ /// proxy preserves the iterator internally and exposes the indirected
+ /// reference via a conversion operator.
+ class ReferenceProxy {
+ friend iterator_facade_base;
+
+ DerivedT I;
+
+ ReferenceProxy(DerivedT I) : I(std::move(I)) {}
+
+ public:
+ operator ReferenceT() const { return *I; }
+ };
+
+public:
+ DerivedT operator+(DifferenceTypeT n) const {
+ static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
+ "Must pass the derived type to this template!");
+ static_assert(
+ IsRandomAccess,
+ "The '+' operator is only defined for random access iterators.");
+ DerivedT tmp = *static_cast<const DerivedT *>(this);
+ tmp += n;
+ return tmp;
+ }
+ friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) {
+ static_assert(
+ IsRandomAccess,
+ "The '+' operator is only defined for random access iterators.");
+ return i + n;
+ }
+ DerivedT operator-(DifferenceTypeT n) const {
+ static_assert(
+ IsRandomAccess,
+ "The '-' operator is only defined for random access iterators.");
+ DerivedT tmp = *static_cast<const DerivedT *>(this);
+ tmp -= n;
+ return tmp;
+ }
+
+ DerivedT &operator++() {
+ static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
+ "Must pass the derived type to this template!");
+ return static_cast<DerivedT *>(this)->operator+=(1);
+ }
+ DerivedT operator++(int) {
+ DerivedT tmp = *static_cast<DerivedT *>(this);
+ ++*static_cast<DerivedT *>(this);
+ return tmp;
+ }
+ DerivedT &operator--() {
+ static_assert(
+ IsBidirectional,
+ "The decrement operator is only defined for bidirectional iterators.");
+ return static_cast<DerivedT *>(this)->operator-=(1);
+ }
+ DerivedT operator--(int) {
+ static_assert(
+ IsBidirectional,
+ "The decrement operator is only defined for bidirectional iterators.");
+ DerivedT tmp = *static_cast<DerivedT *>(this);
+ --*static_cast<DerivedT *>(this);
+ return tmp;
+ }
+
+ bool operator!=(const DerivedT &RHS) const {
+ return !static_cast<const DerivedT *>(this)->operator==(RHS);
+ }
+
+ bool operator>(const DerivedT &RHS) const {
+ static_assert(
+ IsRandomAccess,
+ "Relational operators are only defined for random access iterators.");
+ return !static_cast<const DerivedT *>(this)->operator<(RHS) &&
+ !static_cast<const DerivedT *>(this)->operator==(RHS);
+ }
+ bool operator<=(const DerivedT &RHS) const {
+ static_assert(
+ IsRandomAccess,
+ "Relational operators are only defined for random access iterators.");
+ return !static_cast<const DerivedT *>(this)->operator>(RHS);
+ }
+ bool operator>=(const DerivedT &RHS) const {
+ static_assert(
+ IsRandomAccess,
+ "Relational operators are only defined for random access iterators.");
+ return !static_cast<const DerivedT *>(this)->operator<(RHS);
+ }
+
+ PointerT operator->() { return &static_cast<DerivedT *>(this)->operator*(); }
+ PointerT operator->() const {
+ return &static_cast<const DerivedT *>(this)->operator*();
+ }
+ ReferenceProxy operator[](DifferenceTypeT n) {
+ static_assert(IsRandomAccess,
+ "Subscripting is only defined for random access iterators.");
+ return ReferenceProxy(static_cast<DerivedT *>(this)->operator+(n));
+ }
+ ReferenceProxy operator[](DifferenceTypeT n) const {
+ static_assert(IsRandomAccess,
+ "Subscripting is only defined for random access iterators.");
+ return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n));
+ }
+};
+
+/// CRTP base class for adapting an iterator to a different type.
+///
+/// This class can be used through CRTP to adapt one iterator into another.
+/// Typically this is done through providing in the derived class a custom \c
+/// operator* implementation. Other methods can be overridden as well.
+template <
+ typename DerivedT, typename WrappedIteratorT,
+ typename IteratorCategoryT =
+ typename std::iterator_traits<WrappedIteratorT>::iterator_category,
+ typename T = typename std::iterator_traits<WrappedIteratorT>::value_type,
+ typename DifferenceTypeT =
+ typename std::iterator_traits<WrappedIteratorT>::difference_type,
+ typename PointerT = typename std::conditional<
+ std::is_same<T, typename std::iterator_traits<
+ WrappedIteratorT>::value_type>::value,
+ typename std::iterator_traits<WrappedIteratorT>::pointer, T *>::type,
+ typename ReferenceT = typename std::conditional<
+ std::is_same<T, typename std::iterator_traits<
+ WrappedIteratorT>::value_type>::value,
+ typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type>
+class iterator_adaptor_base
+ : public iterator_facade_base<DerivedT, IteratorCategoryT, T,
+ DifferenceTypeT, PointerT, ReferenceT> {
+ using BaseT = typename iterator_adaptor_base::iterator_facade_base;
+
+protected:
+ WrappedIteratorT I;
+
+ iterator_adaptor_base() = default;
+
+ explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {
+ static_assert(std::is_base_of<iterator_adaptor_base, DerivedT>::value,
+ "Must pass the derived type to this template!");
+ }
+
+ const WrappedIteratorT &wrapped() const { return I; }
+
+public:
+ using difference_type = DifferenceTypeT;
+
+ DerivedT &operator+=(difference_type n) {
+ static_assert(
+ BaseT::IsRandomAccess,
+ "The '+=' operator is only defined for random access iterators.");
+ I += n;
+ return *static_cast<DerivedT *>(this);
+ }
+ DerivedT &operator-=(difference_type n) {
+ static_assert(
+ BaseT::IsRandomAccess,
+ "The '-=' operator is only defined for random access iterators.");
+ I -= n;
+ return *static_cast<DerivedT *>(this);
+ }
+ using BaseT::operator-;
+ difference_type operator-(const DerivedT &RHS) const {
+ static_assert(
+ BaseT::IsRandomAccess,
+ "The '-' operator is only defined for random access iterators.");
+ return I - RHS.I;
+ }
+
+ // We have to explicitly provide ++ and -- rather than letting the facade
+ // forward to += because WrappedIteratorT might not support +=.
+ using BaseT::operator++;
+ DerivedT &operator++() {
+ ++I;
+ return *static_cast<DerivedT *>(this);
+ }
+ using BaseT::operator--;
+ DerivedT &operator--() {
+ static_assert(
+ BaseT::IsBidirectional,
+ "The decrement operator is only defined for bidirectional iterators.");
+ --I;
+ return *static_cast<DerivedT *>(this);
+ }
+
+ bool operator==(const DerivedT &RHS) const { return I == RHS.I; }
+ bool operator<(const DerivedT &RHS) const {
+ static_assert(
+ BaseT::IsRandomAccess,
+ "Relational operators are only defined for random access iterators.");
+ return I < RHS.I;
+ }
+
+ ReferenceT operator*() const { return *I; }
+};
+
+/// An iterator type that allows iterating over the pointees via some
+/// other iterator.
+///
+/// The typical usage of this is to expose a type that iterates over Ts, but
+/// which is implemented with some iterator over T*s:
+///
+/// \code
+/// using iterator = pointee_iterator<SmallVectorImpl<T *>::iterator>;
+/// \endcode
+template <typename WrappedIteratorT,
+ typename T = typename std::remove_reference<
+ decltype(**std::declval<WrappedIteratorT>())>::type>
+struct pointee_iterator
+ : iterator_adaptor_base<
+ pointee_iterator<WrappedIteratorT, T>, WrappedIteratorT,
+ typename std::iterator_traits<WrappedIteratorT>::iterator_category,
+ T> {
+ pointee_iterator() = default;
+ template <typename U>
+ pointee_iterator(U &&u)
+ : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {}
+
+ T &operator*() const { return **this->I; }
+};
+
+template <typename RangeT, typename WrappedIteratorT =
+ decltype(std::begin(std::declval<RangeT>()))>
+iterator_range<pointee_iterator<WrappedIteratorT>>
+make_pointee_range(RangeT &&Range) {
+ using PointeeIteratorT = pointee_iterator<WrappedIteratorT>;
+ return make_range(PointeeIteratorT(std::begin(std::forward<RangeT>(Range))),
+ PointeeIteratorT(std::end(std::forward<RangeT>(Range))));
+}
+
+template <typename WrappedIteratorT,
+ typename T = decltype(&*std::declval<WrappedIteratorT>())>
+class pointer_iterator
+ : public iterator_adaptor_base<
+ pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT,
+ typename std::iterator_traits<WrappedIteratorT>::iterator_category,
+ T> {
+ mutable T Ptr;
+
+public:
+ pointer_iterator() = default;
+
+ explicit pointer_iterator(WrappedIteratorT u)
+ : pointer_iterator::iterator_adaptor_base(std::move(u)) {}
+
+ T &operator*() { return Ptr = &*this->I; }
+ const T &operator*() const { return Ptr = &*this->I; }
+};
+
+template <typename RangeT, typename WrappedIteratorT =
+ decltype(std::begin(std::declval<RangeT>()))>
+iterator_range<pointer_iterator<WrappedIteratorT>>
+make_pointer_range(RangeT &&Range) {
+ using PointerIteratorT = pointer_iterator<WrappedIteratorT>;
+ return make_range(PointerIteratorT(std::begin(std::forward<RangeT>(Range))),
+ PointerIteratorT(std::end(std::forward<RangeT>(Range))));
+}
+
+// Wrapper iterator over iterator ItType, adding DataRef to the type of ItType,
+// to create NodeRef = std::pair<InnerTypeOfItType, DataRef>.
+template <typename ItType, typename NodeRef, typename DataRef>
+class WrappedPairNodeDataIterator
+ : public iterator_adaptor_base<
+ WrappedPairNodeDataIterator<ItType, NodeRef, DataRef>, ItType,
+ typename std::iterator_traits<ItType>::iterator_category, NodeRef,
+ std::ptrdiff_t, NodeRef *, NodeRef &> {
+ using BaseT = iterator_adaptor_base<
+ WrappedPairNodeDataIterator, ItType,
+ typename std::iterator_traits<ItType>::iterator_category, NodeRef,
+ std::ptrdiff_t, NodeRef *, NodeRef &>;
+
+ const DataRef DR;
+ mutable NodeRef NR;
+
+public:
+ WrappedPairNodeDataIterator(ItType Begin, const DataRef DR)
+ : BaseT(Begin), DR(DR) {
+ NR.first = DR;
+ }
+
+ NodeRef &operator*() const {
+ NR.second = *this->I;
+ return NR;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_ITERATOR_H
diff --git a/third_party/llvm-project/include/llvm/ADT/iterator_range.h b/third_party/llvm-project/include/llvm/ADT/iterator_range.h
new file mode 100644
index 000000000..aa8830943
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/iterator_range.h
@@ -0,0 +1,69 @@
+//===- iterator_range.h - A range adaptor for iterators ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This provides a very simple, boring adaptor for a begin and end iterator
+/// into a range type. This should be used to build range views that work well
+/// with range based for loops and range based constructors.
+///
+/// Note that code here follows more standards-based coding conventions as it
+/// is mirroring proposed interfaces for standardization.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_ITERATOR_RANGE_H
+#define LLVM_ADT_ITERATOR_RANGE_H
+
+#include <iterator>
+#include <utility>
+
+namespace llvm {
+
+/// A range adaptor for a pair of iterators.
+///
+/// This just wraps two iterators into a range-compatible interface. Nothing
+/// fancy at all.
+template <typename IteratorT>
+class iterator_range {
+ IteratorT begin_iterator, end_iterator;
+
+public:
+ //TODO: Add SFINAE to test that the Container's iterators match the range's
+ // iterators.
+ template <typename Container>
+ iterator_range(Container &&c)
+ //TODO: Consider ADL/non-member begin/end calls.
+ : begin_iterator(c.begin()), end_iterator(c.end()) {}
+ iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
+ : begin_iterator(std::move(begin_iterator)),
+ end_iterator(std::move(end_iterator)) {}
+
+ IteratorT begin() const { return begin_iterator; }
+ IteratorT end() const { return end_iterator; }
+ bool empty() const { return begin_iterator == end_iterator; }
+};
+
+/// Convenience function for iterating over sub-ranges.
+///
+/// This provides a bit of syntactic sugar to make using sub-ranges
+/// in for loops a bit easier. Analogous to std::make_pair().
+template <class T> iterator_range<T> make_range(T x, T y) {
+ return iterator_range<T>(std::move(x), std::move(y));
+}
+
+template <typename T> iterator_range<T> make_range(std::pair<T, T> p) {
+ return iterator_range<T>(std::move(p.first), std::move(p.second));
+}
+
+template <typename T>
+iterator_range<decltype(adl_begin(std::declval<T>()))> drop_begin(T &&t,
+ int n) {
+ return make_range(std::next(adl_begin(t), n), adl_end(t));
+}
+}
+
+#endif
diff --git a/third_party/llvm-project/include/llvm/ADT/simple_ilist.h b/third_party/llvm-project/include/llvm/ADT/simple_ilist.h
new file mode 100644
index 000000000..9257b47b9
--- /dev/null
+++ b/third_party/llvm-project/include/llvm/ADT/simple_ilist.h
@@ -0,0 +1,314 @@
+//===- llvm/ADT/simple_ilist.h - Simple Intrusive List ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SIMPLE_ILIST_H
+#define LLVM_ADT_SIMPLE_ILIST_H
+
+#include "llvm/ADT/ilist_base.h"
+#include "llvm/ADT/ilist_iterator.h"
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/ilist_node_options.h"
+#include "llvm/Support/Compiler.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <functional>
+#include <iterator>
+#include <utility>
+
+namespace llvm {
+
+/// A simple intrusive list implementation.
+///
+/// This is a simple intrusive list for a \c T that inherits from \c
+/// ilist_node<T>. The list never takes ownership of anything inserted in it.
+///
+/// Unlike \a iplist<T> and \a ilist<T>, \a simple_ilist<T> never allocates or
+/// deletes values, and has no callback traits.
+///
+/// The API for adding nodes include \a push_front(), \a push_back(), and \a
+/// insert(). These all take values by reference (not by pointer), except for
+/// the range version of \a insert().
+///
+/// There are three sets of API for discarding nodes from the list: \a
+/// remove(), which takes a reference to the node to remove, \a erase(), which
+/// takes an iterator or iterator range and returns the next one, and \a
+/// clear(), which empties out the container. All three are constant time
+/// operations. None of these deletes any nodes; in particular, if there is a
+/// single node in the list, then these have identical semantics:
+/// \li \c L.remove(L.front());
+/// \li \c L.erase(L.begin());
+/// \li \c L.clear();
+///
+/// As a convenience for callers, there are parallel APIs that take a \c
+/// Disposer (such as \c std::default_delete<T>): \a removeAndDispose(), \a
+/// eraseAndDispose(), and \a clearAndDispose(). These have different names
+/// because the extra semantic is otherwise non-obvious. They are equivalent
+/// to calling \a std::for_each() on the range to be discarded.
+///
+/// The currently available \p Options customize the nodes in the list. The
+/// same options must be specified in the \a ilist_node instantation for
+/// compatibility (although the order is irrelevant).
+/// \li Use \a ilist_tag to designate which ilist_node for a given \p T this
+/// list should use. This is useful if a type \p T is part of multiple,
+/// independent lists simultaneously.
+/// \li Use \a ilist_sentinel_tracking to always (or never) track whether a
+/// node is a sentinel. Specifying \c true enables the \a
+/// ilist_node::isSentinel() API. Unlike \a ilist_node::isKnownSentinel(),
+/// which is only appropriate for assertions, \a ilist_node::isSentinel() is
+/// appropriate for real logic.
+///
+/// Here are examples of \p Options usage:
+/// \li \c simple_ilist<T> gives the defaults. \li \c
+/// simple_ilist<T,ilist_sentinel_tracking<true>> enables the \a
+/// ilist_node::isSentinel() API.
+/// \li \c simple_ilist<T,ilist_tag<A>,ilist_sentinel_tracking<false>>
+/// specifies a tag of A and that tracking should be off (even when
+/// LLVM_ENABLE_ABI_BREAKING_CHECKS are enabled).
+/// \li \c simple_ilist<T,ilist_sentinel_tracking<false>,ilist_tag<A>> is
+/// equivalent to the last.
+///
+/// See \a is_valid_option for steps on adding a new option.
+template <typename T, class... Options>
+class simple_ilist
+ : ilist_detail::compute_node_options<T, Options...>::type::list_base_type,
+ ilist_detail::SpecificNodeAccess<
+ typename ilist_detail::compute_node_options<T, Options...>::type> {
+ static_assert(ilist_detail::check_options<Options...>::value,
+ "Unrecognized node option!");
+ using OptionsT =
+ typename ilist_detail::compute_node_options<T, Options...>::type;
+ using list_base_type = typename OptionsT::list_base_type;
+ ilist_sentinel<OptionsT> Sentinel;
+
+public:
+ using value_type = typename OptionsT::value_type;
+ using pointer = typename OptionsT::pointer;
+ using reference = typename OptionsT::reference;
+ using const_pointer = typename OptionsT::const_pointer;
+ using const_reference = typename OptionsT::const_reference;
+ using iterator = ilist_iterator<OptionsT, false, false>;
+ using const_iterator = ilist_iterator<OptionsT, false, true>;
+ using reverse_iterator = ilist_iterator<OptionsT, true, false>;
+ using const_reverse_iterator = ilist_iterator<OptionsT, true, true>;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+
+ simple_ilist() = default;
+ ~simple_ilist() = default;
+
+ // No copy constructors.
+ simple_ilist(const simple_ilist &) = delete;
+ simple_ilist &operator=(const simple_ilist &) = delete;
+
+ // Move constructors.
+ simple_ilist(simple_ilist &&X) { splice(end(), X); }
+ simple_ilist &operator=(simple_ilist &&X) {
+ clear();
+ splice(end(), X);
+ return *this;
+ }
+
+ iterator begin() { return ++iterator(Sentinel); }
+ const_iterator begin() const { return ++const_iterator(Sentinel); }
+ iterator end() { return iterator(Sentinel); }
+ const_iterator end() const { return const_iterator(Sentinel); }
+ reverse_iterator rbegin() { return ++reverse_iterator(Sentinel); }
+ const_reverse_iterator rbegin() const {
+ return ++const_reverse_iterator(Sentinel);
+ }
+ reverse_iterator rend() { return reverse_iterator(Sentinel); }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(Sentinel);
+ }
+
+ /// Check if the list is empty in constant time.
+ LLVM_NODISCARD bool empty() const { return Sentinel.empty(); }
+
+ /// Calculate the size of the list in linear time.
+ LLVM_NODISCARD size_type size() const {
+ return std::distance(begin(), end());
+ }
+
+ reference front() { return *begin(); }
+ const_reference front() const { return *begin(); }
+ reference back() { return *rbegin(); }
+ const_reference back() const { return *rbegin(); }
+
+ /// Insert a node at the front; never copies.
+ void push_front(reference Node) { insert(begin(), Node); }
+
+ /// Insert a node at the back; never copies.
+ void push_back(reference Node) { insert(end(), Node); }
+
+ /// Remove the node at the front; never deletes.
+ void pop_front() { erase(begin()); }
+
+ /// Remove the node at the back; never deletes.
+ void pop_back() { erase(--end()); }
+
+ /// Swap with another list in place using std::swap.
+ void swap(simple_ilist &X) { std::swap(*this, X); }
+
+ /// Insert a node by reference; never copies.
+ iterator insert(iterator I, reference Node) {
+ list_base_type::insertBefore(*I.getNodePtr(), *this->getNodePtr(&Node));
+ return iterator(&Node);
+ }
+
+ /// Insert a range of nodes; never copies.
+ template <class Iterator>
+ void insert(iterator I, Iterator First, Iterator Last) {
+ for (; First != Last; ++First)
+ insert(I, *First);
+ }
+
+ /// Clone another list.
+ template <class Cloner, class Disposer>
+ void cloneFrom(const simple_ilist &L2, Cloner clone, Disposer dispose) {
+ clearAndDispose(dispose);
+ for (const_reference V : L2)
+ push_back(*clone(V));
+ }
+
+ /// Remove a node by reference; never deletes.
+ ///
+ /// \see \a erase() for removing by iterator.
+ /// \see \a removeAndDispose() if the node should be deleted.
+ void remove(reference N) { list_base_type::remove(*this->getNodePtr(&N)); }
+
+ /// Remove a node by reference and dispose of it.
+ template <class Disposer>
+ void removeAndDispose(reference N, Disposer dispose) {
+ remove(N);
+ dispose(&N);
+ }
+
+ /// Remove a node by iterator; never deletes.
+ ///
+ /// \see \a remove() for removing by reference.
+ /// \see \a eraseAndDispose() it the node should be deleted.
+ iterator erase(iterator I) {
+ assert(I != end() && "Cannot remove end of list!");
+ remove(*I++);
+ return I;
+ }
+
+ /// Remove a range of nodes; never deletes.
+ ///
+ /// \see \a eraseAndDispose() if the nodes should be deleted.
+ iterator erase(iterator First, iterator Last) {
+ list_base_type::removeRange(*First.getNodePtr(), *Last.getNodePtr());
+ return Last;
+ }
+
+ /// Remove a node by iterator and dispose of it.
+ template <class Disposer>
+ iterator eraseAndDispose(iterator I, Disposer dispose) {
+ auto Next = std::next(I);
+ erase(I);
+ dispose(&*I);
+ return Next;
+ }
+
+ /// Remove a range of nodes and dispose of them.
+ template <class Disposer>
+ iterator eraseAndDispose(iterator First, iterator Last, Disposer dispose) {
+ while (First != Last)
+ First = eraseAndDispose(First, dispose);
+ return Last;
+ }
+
+ /// Clear the list; never deletes.
+ ///
+ /// \see \a clearAndDispose() if the nodes should be deleted.
+ void clear() { Sentinel.reset(); }
+
+ /// Clear the list and dispose of the nodes.
+ template <class Disposer> void clearAndDispose(Disposer dispose) {
+ eraseAndDispose(begin(), end(), dispose);
+ }
+
+ /// Splice in another list.
+ void splice(iterator I, simple_ilist &L2) {
+ splice(I, L2, L2.begin(), L2.end());
+ }
+
+ /// Splice in a node from another list.
+ void splice(iterator I, simple_ilist &L2, iterator Node) {
+ splice(I, L2, Node, std::next(Node));
+ }
+
+ /// Splice in a range of nodes from another list.
+ void splice(iterator I, simple_ilist &, iterator First, iterator Last) {
+ list_base_type::transferBefore(*I.getNodePtr(), *First.getNodePtr(),
+ *Last.getNodePtr());
+ }
+
+ /// Merge in another list.
+ ///
+ /// \pre \c this and \p RHS are sorted.
+ ///@{
+ void merge(simple_ilist &RHS) { merge(RHS, std::less<T>()); }
+ template <class Compare> void merge(simple_ilist &RHS, Compare comp);
+ ///@}
+
+ /// Sort the list.
+ ///@{
+ void sort() { sort(std::less<T>()); }
+ template <class Compare> void sort(Compare comp);
+ ///@}
+};
+
+template <class T, class... Options>
+template <class Compare>
+void simple_ilist<T, Options...>::merge(simple_ilist &RHS, Compare comp) {
+ if (this == &RHS || RHS.empty())
+ return;
+ iterator LI = begin(), LE = end();
+ iterator RI = RHS.begin(), RE = RHS.end();
+ while (LI != LE) {
+ if (comp(*RI, *LI)) {
+ // Transfer a run of at least size 1 from RHS to LHS.
+ iterator RunStart = RI++;
+ RI = std::find_if(RI, RE, [&](reference RV) { return !comp(RV, *LI); });
+ splice(LI, RHS, RunStart, RI);
+ if (RI == RE)
+ return;
+ }
+ ++LI;
+ }
+ // Transfer the remaining RHS nodes once LHS is finished.
+ splice(LE, RHS, RI, RE);
+}
+
+template <class T, class... Options>
+template <class Compare>
+void simple_ilist<T, Options...>::sort(Compare comp) {
+ // Vacuously sorted.
+ if (empty() || std::next(begin()) == end())
+ return;
+
+ // Split the list in the middle.
+ iterator Center = begin(), End = begin();
+ while (End != end() && ++End != end()) {
+ ++Center;
+ ++End;
+ }
+ simple_ilist RHS;
+ RHS.splice(RHS.end(), *this, Center, end());
+
+ // Sort the sublists and merge back together.
+ sort(comp);
+ RHS.sort(comp);
+ merge(RHS, comp);
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_SIMPLE_ILIST_H