aboutsummaryrefslogtreecommitdiff
path: root/libsupport/include
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-11-01 02:12:34 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-11-01 02:12:34 +0800
commit02b615c8704aeda9a94cf5457c9c78de847c911a (patch)
tree3257dd23e643ae732cb0abf14d62ab70b64893be /libsupport/include
parent2850abdb23a2ba4fde6268ea4191f4d062b9a01f (diff)
downloadrcc-project-master.tar.gz
rcc-project-master.tar.xz
Move support code into CoreLibHEADmaster
Diffstat (limited to 'libsupport/include')
-rw-r--r--libsupport/include/CoreLib/ADT/STLFunctionalExtras.h112
-rw-r--r--libsupport/include/CoreLib/ADT/SmallVector.h1926
-rw-r--r--libsupport/include/CoreLib/Compiler/Compiler.h853
-rw-r--r--libsupport/include/CoreLib/Error/ErrorHandling.h217
-rw-r--r--libsupport/include/CoreLib/Error/ErrorOr.h378
-rw-r--r--libsupport/include/CoreLib/Math/MathExtras.h1050
-rw-r--r--libsupport/include/CoreLib/Memory/MemAlloc.h124
-rw-r--r--libsupport/include/CoreLib/System/Errno.h64
8 files changed, 4724 insertions, 0 deletions
diff --git a/libsupport/include/CoreLib/ADT/STLFunctionalExtras.h b/libsupport/include/CoreLib/ADT/STLFunctionalExtras.h
new file mode 100644
index 0000000..993acc0
--- /dev/null
+++ b/libsupport/include/CoreLib/ADT/STLFunctionalExtras.h
@@ -0,0 +1,112 @@
+/*
+ R *CC-Project
+
+ Copyright (C) 2026 Richard Qin
+
+ This file is part of RCC-Project.
+
+ RCC-Project is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option) any
+ later version.
+
+ RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ RCC-Project; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>.
+ */
+
+//===- llvm/ADT/STLFunctionalExtras.h - Extras for <functional> -*- 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 extension to <functional>.
+//
+// No library is required when using these functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef RCC_ADT_STLFUNCTIONALEXTRAS_H
+#define RCC_ADT_STLFUNCTIONALEXTRAS_H
+
+#include "CoreLib/Compiler/Compiler.h"
+
+#include <cstddef
+#include <cstdint>
+#include <type_traits>
+#include <utility>
+
+namespace rcc
+{
+
+//===----------------------------------------------------------------------===//
+// Extra additions to <functional>
+//===----------------------------------------------------------------------===//
+
+/// 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 RCC_GSL_POINTER function_ref<Ret (Params...)>
+{
+ Ret (*callback) (intptr_t callable, Params... params) = nullptr;
+ intptr_t callable = 0;
+
+ 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 RCC_LIFETIME_BOUND,
+ // This is not the copy-constructor.
+ std::enable_if_t<!std::is_same<std::remove_cvref_t<Callable>,
+ function_ref>::value> * = nullptr,
+ // Functor must be callable and return a suitable type.
+ std::enable_if_t<std::is_void<Ret>::value ||
+ std::is_convertible<decltype (std::declval<Callable> () (
+ std::declval<Params> ()...)),
+ Ret>::value> * = nullptr)
+ : callback (callback_fn<std::remove_reference_t<Callable>>),
+ callable (reinterpret_cast<intptr_t> (&callable))
+ {
+ }
+
+ Ret
+ operator() (Params... params) const
+ {
+ return callback (callable, std::forward<Params> (params)...);
+ }
+
+ explicit
+ operator bool () const
+ {
+ return callback;
+ }
+};
+
+} // end namespace rcc
+
+#endif // RCC_ADT_STLFUNCTIONALEXTRAS_H
diff --git a/libsupport/include/CoreLib/ADT/SmallVector.h b/libsupport/include/CoreLib/ADT/SmallVector.h
new file mode 100644
index 0000000..8b9826a
--- /dev/null
+++ b/libsupport/include/CoreLib/ADT/SmallVector.h
@@ -0,0 +1,1926 @@
+/*
+ R *CC-Project
+
+ Copyright (C) 2026 Richard Qin
+
+ This file is part of RCC-Project.
+
+ RCC-Project is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option) any
+ later version.
+
+ RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ RCC-Project; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>.
+ */
+
+//===- rcc/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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file defines the SmallVector class.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef RCC_ADT_SMALLVECTOR_H
+#define RCC_ADT_SMALLVECTOR_H
+
+#include "CoreLib/Compiler/Compiler.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <functional>
+#include <initializer_list>
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <new>
+#include <ranges>
+#include <type_traits>
+#include <utility>
+
+namespace rcc
+{
+
+template <typename T> class ArrayRef;
+
+template <typename IteratorT> class iterator_range;
+
+template <class Iterator, class Tag>
+using HasIteratorTag = std::is_convertible<
+ typename std::iterator_traits<Iterator>::iterator_category, Tag>;
+
+template <class Iterator>
+using EnableIfConvertibleToInputIterator =
+ std::enable_if_t<HasIteratorTag<Iterator, std::input_iterator_tag>::value>;
+
+/// This is all the stuff common to all SmallVectors.
+///
+/// The template parameter specifies the type which should be used to hold the
+/// Size and Capacity of the SmallVector, so it can be adjusted.
+/// Using 32 bit size is desirable to shrink the size of the SmallVector.
+/// Using 64 bit size is desirable for cases like SmallVector<char>, where a
+/// 32 bit size would limit the vector to ~4GB. SmallVectors are used for
+/// buffering bitcode output - which can exceed 4GB.
+template <class Size_T> class SmallVectorBase
+{
+protected:
+ void *BeginX;
+ Size_T Size = 0, Capacity;
+
+ /// The maximum value of the Size_T used.
+ static constexpr size_t
+ SizeTypeMax ()
+ {
+ return std::numeric_limits<Size_T>::max ();
+ }
+
+ SmallVectorBase () = delete;
+ SmallVectorBase (void *FirstEl, size_t TotalCapacity)
+ : BeginX (FirstEl), Capacity (static_cast<Size_T> (TotalCapacity))
+ {
+ }
+
+ /// This is a helper for \a grow() that's out of line to reduce code
+ /// duplication. This function will report a fatal error if it can't grow at
+ /// least to \p MinSize.
+ RCC_ABI void *
+ mallocForGrow (void *FirstEl, size_t MinSize, size_t TSize,
+ size_t &NewCapacity);
+
+ /// 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.
+ /// This function will report a fatal error if it cannot increase capacity.
+ RCC_ABI void
+ grow_pod (void *FirstEl, size_t MinSize, size_t TSize);
+
+public:
+ size_t
+ size () const
+ {
+ return Size;
+ }
+ size_t
+ capacity () const
+ {
+ return Capacity;
+ }
+
+ [[nodiscard]] bool
+ empty () const
+ {
+ return !Size;
+ }
+
+protected:
+ /// 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.
+ void
+ set_size (size_t N)
+ {
+ assert (N <= capacity ()); // implies no overflow in assignment
+ Size = static_cast<Size_T> (N);
+ }
+
+ /// Set the array data pointer to \p Begin and capacity to \p N.
+ ///
+ /// This does not construct or destroy any elements in the vector.
+ // This does not clean up any existing allocation.
+ void
+ set_allocation_range (void *Begin, size_t N)
+ {
+ assert (N <= SizeTypeMax ());
+ BeginX = Begin;
+ Capacity = static_cast<Size_T> (N);
+ }
+};
+
+template <class T>
+using SmallVectorSizeType =
+ std::conditional_t<sizeof (T) < 4 && sizeof (void *) >= 8, uint64_t,
+ uint32_t>;
+
+/// Figure out the offset of the first element.
+template <class T, typename = void> struct SmallVectorAlignmentAndSize
+{
+ alignas (SmallVectorBase<SmallVectorSizeType<T>>) char Base[sizeof (
+ SmallVectorBase<SmallVectorSizeType<T>>)];
+ alignas (T) char FirstEl[sizeof (T)];
+};
+
+/// 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<SmallVectorSizeType<T>>
+{
+ using Base = SmallVectorBase<SmallVectorSizeType<T>>;
+
+protected:
+ /// 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.
+
+ SmallVectorTemplateCommon (size_t SizeArg) : Base (getFirstEl (), SizeArg)
+ {
+ }
+
+ void
+ grow_pod (size_t MinSize, size_t TSize)
+ {
+ Base::grow_pod (getFirstEl (), MinSize, TSize);
+ }
+
+ /// Return true if this is a smallvector which has not had dynamic
+ /// memory allocated for it.
+ bool
+ isSmall () const
+ {
+ return this->BeginX == getFirstEl ();
+ }
+
+ /// Put this vector in a state of being small.
+ void
+ resetToSmall ()
+ {
+ this->BeginX = getFirstEl ();
+ // The inline capacity is unknown here. SmallVector restores it when moving
+ // from the same concrete type; moves through SmallVectorImpl leave it at 0.
+ this->Size = this->Capacity = 0;
+ }
+
+ /// Return true if V is an internal reference to the given range.
+ bool
+ isReferenceToRange (const void *V, const void *First, const void *Last) const
+ {
+ // Use std::less to avoid UB.
+ std::less<> LessThan;
+ return !LessThan (V, First) && LessThan (V, Last);
+ }
+
+ /// Return true if V is an internal reference to this vector.
+ bool
+ isReferenceToStorage (const void *V) const
+ {
+ return isReferenceToRange (V, this->begin (), this->end ());
+ }
+
+ /// Return true if First and Last form a valid (possibly empty) range in this
+ /// vector's storage.
+ bool
+ isRangeInStorage (const void *First, const void *Last) const
+ {
+ // Use std::less to avoid UB.
+ std::less<> LessThan;
+ return !LessThan (First, this->begin ()) && !LessThan (Last, First) &&
+ !LessThan (this->end (), Last);
+ }
+
+ /// Return true unless Elt will be invalidated by resizing the vector to
+ /// NewSize.
+ bool
+ isSafeToReferenceAfterResize (const void *Elt, size_t NewSize)
+ {
+ // Past the end.
+ if (RCC_LIKELY (!isReferenceToStorage (Elt)))
+ {
+ return true;
+ }
+
+ // Return false if Elt will be destroyed by shrinking.
+ if (NewSize <= this->size ())
+ {
+ return Elt < this->begin () + NewSize;
+ }
+
+ // Return false if we need to grow.
+ return NewSize <= this->capacity ();
+ }
+
+ /// Check whether Elt will be invalidated by resizing the vector to NewSize.
+ void
+ assertSafeToReferenceAfterResize (const void *Elt, size_t NewSize)
+ {
+ assert (isSafeToReferenceAfterResize (Elt, NewSize) &&
+ "Attempting to reference an element of the vector in an operation "
+ "that invalidates it");
+ }
+
+ /// Check whether Elt will be invalidated by increasing the size of the
+ /// vector by N.
+ void
+ assertSafeToAdd (const void *Elt, size_t N = 1)
+ {
+ this->assertSafeToReferenceAfterResize (Elt, this->size () + N);
+ }
+
+ /// Check whether any part of the range will be invalidated by clearing.
+ template <class ItTy>
+ void
+ assertSafeToReferenceAfterClear (ItTy From, ItTy To)
+ {
+ if constexpr (std::is_pointer_v<ItTy> &&
+ std::is_same_v<
+ std::remove_const_t<std::remove_pointer_t<ItTy>>,
+ std::remove_const_t<T>>)
+ {
+ if (From == To)
+ {
+ return;
+ }
+ this->assertSafeToReferenceAfterResize (From, 0);
+ this->assertSafeToReferenceAfterResize (To - 1, 0);
+ }
+ (void)From;
+ (void)To;
+ }
+
+ /// Check whether any part of the range will be invalidated by growing.
+ template <class ItTy>
+ void
+ assertSafeToAddRange (ItTy From, ItTy To)
+ {
+ if constexpr (std::is_pointer_v<ItTy> &&
+ std::is_same_v<std::remove_cv_t<std::remove_pointer_t<ItTy>>,
+ T>)
+ {
+ if (From == To)
+ {
+ return;
+ }
+ this->assertSafeToAdd (From, To - From);
+ this->assertSafeToAdd (To - 1, To - From);
+ }
+ (void)From;
+ (void)To;
+ }
+
+ /// Reserve enough space to add one element, and return the updated element
+ /// pointer in case it was a reference to the storage.
+ template <class U>
+ static const T *
+ reserveForParamAndGetAddressImpl (U *This, const T &Elt, size_t N)
+ {
+ size_t NewSize = This->size () + N;
+ if (RCC_LIKELY (NewSize <= This->capacity ()))
+ {
+ return &Elt;
+ }
+
+ bool ReferencesStorage = false;
+ int64_t Index = -1;
+ if (!U::TakesParamByValue)
+ {
+ if (RCC_UNLIKELY (This->isReferenceToStorage (&Elt)))
+ {
+ ReferencesStorage = true;
+ Index = &Elt - This->begin ();
+ }
+ }
+ This->grow (NewSize);
+ return ReferencesStorage ? This->begin () + Index : &Elt;
+ }
+
+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 *;
+
+ using Base::capacity;
+ using Base::empty;
+ using Base::size;
+
+ // 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 std::min (this->SizeTypeMax (), 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-trivial T's.
+///
+/// We approximate is_trivially_copyable with trivial move/copy construction and
+/// trivial destruction. While the standard doesn't specify that you're allowed
+/// copy these types with memcpy, there is no way for the type to observe this.
+/// This catches the important case of std::pair<POD, POD>, which is not
+/// trivially assignable.
+template <typename T, bool = (std::is_trivially_copy_constructible<T>::value) &&
+ (std::is_trivially_move_constructible<T>::value) &&
+ std::is_trivially_destructible<T>::value>
+class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T>
+{
+ friend class SmallVectorTemplateCommon<T>;
+
+protected:
+ static constexpr bool TakesParamByValue = false;
+ using ValueParamT = const T &;
+
+ SmallVectorTemplateBase (size_t SizeArg)
+ : SmallVectorTemplateCommon<T> (SizeArg)
+ {
+ }
+
+ 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_move (I, 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);
+
+ /// Create a new allocation big enough for \p MinSize and pass back its size
+ /// in \p NewCapacity. This is the first section of \a grow().
+ T *
+ mallocForGrow (size_t MinSize, size_t &NewCapacity);
+
+ /// Move existing elements over to the new allocation \p NewElts, the middle
+ /// section of \a grow().
+ void
+ moveElementsForGrow (T *NewElts);
+
+ /// Transfer ownership of the allocation, finishing up \a grow().
+ void
+ takeAllocationForGrow (T *NewElts, size_t NewCapacity);
+
+ /// Reserve enough space to add one element, and return the updated element
+ /// pointer in case it was a reference to the storage.
+ const T *
+ reserveForParamAndGetAddress (const T &Elt, size_t N = 1)
+ {
+ return this->reserveForParamAndGetAddressImpl (this, Elt, N);
+ }
+
+ /// Reserve enough space to add one element, and return the updated element
+ /// pointer in case it was a reference to the storage.
+ T *
+ reserveForParamAndGetAddress (T &Elt, size_t N = 1)
+ {
+ return const_cast<T *> (
+ this->reserveForParamAndGetAddressImpl (this, Elt, N));
+ }
+
+ static T &&
+ forward_value_param (T &&V)
+ {
+ return std::move (V);
+ }
+ static const T &
+ forward_value_param (const T &V)
+ {
+ return V;
+ }
+
+ void
+ growAndAssign (size_t NumElts, const T &Elt)
+ {
+ // Grow manually in case Elt is an internal reference.
+ size_t NewCapacity;
+ T *NewElts = mallocForGrow (NumElts, NewCapacity);
+ std::uninitialized_fill_n (NewElts, NumElts, Elt);
+ this->destroy_range (this->begin (), this->end ());
+ takeAllocationForGrow (NewElts, NewCapacity);
+ this->set_size (NumElts);
+ }
+
+ template <typename... ArgTypes>
+ T &
+ growAndEmplaceBack (ArgTypes &&...Args)
+ {
+ // Grow manually in case one of Args is an internal reference.
+ size_t NewCapacity;
+ T *NewElts = mallocForGrow (0, NewCapacity);
+ ::new ((void *)(NewElts + this->size ()))
+ T (std::forward<ArgTypes> (Args)...);
+ moveElementsForGrow (NewElts);
+ takeAllocationForGrow (NewElts, NewCapacity);
+ this->set_size (this->size () + 1);
+ return this->back ();
+ }
+
+public:
+ void
+ push_back (const T &Elt)
+ {
+ const T *EltPtr = reserveForParamAndGetAddress (Elt);
+ ::new ((void *)this->end ()) T (*EltPtr);
+ this->set_size (this->size () + 1);
+ }
+
+ void
+ push_back (T &&Elt)
+ {
+ T *EltPtr = reserveForParamAndGetAddress (Elt);
+ ::new ((void *)this->end ()) T (::std::move (*EltPtr));
+ 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)
+{
+ size_t NewCapacity;
+ T *NewElts = mallocForGrow (MinSize, NewCapacity);
+ moveElementsForGrow (NewElts);
+ takeAllocationForGrow (NewElts, NewCapacity);
+}
+
+template <typename T, bool TriviallyCopyable>
+T *
+SmallVectorTemplateBase<T, TriviallyCopyable>::mallocForGrow (
+ size_t MinSize, size_t &NewCapacity)
+{
+ return static_cast<T *> (
+ SmallVectorBase<SmallVectorSizeType<T>>::mallocForGrow (
+ this->getFirstEl (), MinSize, sizeof (T), NewCapacity));
+}
+
+// Define this out-of-line to dissuade the C++ compiler from inlining it.
+template <typename T, bool TriviallyCopyable>
+void
+SmallVectorTemplateBase<T, TriviallyCopyable>::moveElementsForGrow (T *NewElts)
+{
+ // Move the elements over.
+ this->uninitialized_move (this->begin (), this->end (), NewElts);
+
+ // Destroy the original elements.
+ destroy_range (this->begin (), this->end ());
+}
+
+// Define this out-of-line to dissuade the C++ compiler from inlining it.
+template <typename T, bool TriviallyCopyable>
+void
+SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow (
+ T *NewElts, size_t NewCapacity)
+{
+ // If this wasn't grown from the inline copy, deallocate the old space.
+ if (!this->isSmall ())
+ {
+ free (this->begin ());
+ }
+
+ this->set_allocation_range (NewElts, NewCapacity);
+}
+
+/// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
+/// method implementations that are designed to work with trivially copyable
+/// T's. This allows using memcpy in place of copy/move construction and
+/// skipping destruction.
+template <typename T>
+class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T>
+{
+ friend class SmallVectorTemplateCommon<T>;
+
+protected:
+ /// True if it's cheap enough to take parameters by value. Doing so avoids
+ /// overhead related to mitigations for reference invalidation.
+ static constexpr bool TakesParamByValue = sizeof (T) <= 2 * sizeof (void *);
+
+ /// Either const T& or T, depending on whether it's cheap enough to take
+ /// parameters by value.
+ using ValueParamT = std::conditional_t<TakesParamByValue, T, const T &>;
+
+ SmallVectorTemplateBase (size_t SizeArg)
+ : SmallVectorTemplateCommon<T> (SizeArg)
+ {
+ }
+
+ // 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)
+ {
+ if constexpr (std::is_pointer_v<It1> && std::is_pointer_v<It2> &&
+ std::is_same_v<
+ std::remove_const_t<std::remove_pointer_t<It1>>,
+ std::remove_pointer_t<It2>>)
+ {
+ // 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)
+ {
+ std::memcpy (reinterpret_cast<void *> (Dest), I, (E - I) * sizeof (T));
+ }
+ }
+ else
+ {
+ // Arbitrary iterator types; just use the basic implementation.
+ std::uninitialized_copy (I, E, Dest);
+ }
+ }
+
+ /// 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));
+ }
+
+ /// Reserve enough space to add one element, and return the updated element
+ /// pointer in case it was a reference to the storage.
+ const T *
+ reserveForParamAndGetAddress (const T &Elt, size_t N = 1)
+ {
+ return this->reserveForParamAndGetAddressImpl (this, Elt, N);
+ }
+
+ /// Reserve enough space to add one element, and return the updated element
+ /// pointer in case it was a reference to the storage.
+ T *
+ reserveForParamAndGetAddress (T &Elt, size_t N = 1)
+ {
+ return const_cast<T *> (
+ this->reserveForParamAndGetAddressImpl (this, Elt, N));
+ }
+
+ /// Copy \p V or return a reference, depending on \a ValueParamT.
+ static ValueParamT
+ forward_value_param (ValueParamT V)
+ {
+ return V;
+ }
+
+ void
+ growAndAssign (size_t NumElts, T Elt)
+ {
+ // Elt has been copied in case it's an internal reference, side-stepping
+ // reference invalidation problems without losing the realloc optimization.
+ this->set_size (0);
+ this->grow (NumElts);
+ std::uninitialized_fill_n (this->begin (), NumElts, Elt);
+ this->set_size (NumElts);
+ }
+
+ template <typename... ArgTypes>
+ T &
+ growAndEmplaceBack (ArgTypes &&...Args)
+ {
+ // Use push_back with a copy in case Args has an internal reference,
+ // side-stepping reference invalidation problems without losing the realloc
+ // optimization.
+ push_back (T (std::forward<ArgTypes> (Args)...));
+ return this->back ();
+ }
+
+ // Out-of-line slow path so the inline push_back needs no callee-saved
+ // registers or stack frame on its hot path.
+ RCC_ATTRIBUTE_NOINLINE void
+ growAndPushBack (ValueParamT Elt)
+ {
+ // Copy in case Elt is an internal reference invalidated by grow.
+ T Tmp = Elt;
+ this->grow (this->size () + 1);
+ std::memcpy (reinterpret_cast<void *> (this->end ()), &Tmp, sizeof (T));
+ this->set_size (this->size () + 1);
+ }
+
+public:
+ void
+ push_back (ValueParamT Elt)
+ {
+ if (RCC_UNLIKELY (this->size () >= this->capacity ()))
+ {
+ return growAndPushBack (Elt);
+ }
+ std::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:
+ using SmallVectorTemplateBase<T>::TakesParamByValue;
+ using ValueParamT = typename SuperClass::ValueParamT;
+
+ // Default ctor - Initialize to empty.
+ explicit SmallVectorImpl (unsigned N) : SmallVectorTemplateBase<T> (N)
+ {
+ }
+
+ void
+ assignRemote (SmallVectorImpl &&RHS)
+ {
+ 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 ();
+ }
+
+ void
+ moveConstructFrom (SmallVectorImpl &&RHS)
+ {
+ assert (this->empty () && "move construction requires an empty vector");
+ if (!RHS.isSmall ())
+ {
+ assignRemote (std::move (RHS));
+ return;
+ }
+
+ // Construct inline elements directly instead of requiring T to be move
+ // assignable through the general move-assignment implementation.
+ size_type RHSSize = RHS.size ();
+ reserve (RHSSize);
+ this->uninitialized_move (RHS.begin (), RHS.end (), this->begin ());
+ this->set_size (RHSSize);
+ RHS.clear ();
+ }
+
+ ~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 ());
+ }
+ }
+
+public:
+ SmallVectorImpl (const SmallVectorImpl &) = delete;
+
+ void
+ clear ()
+ {
+ this->destroy_range (this->begin (), this->end ());
+ this->Size = 0;
+ }
+
+private:
+ // Make set_size() private to avoid misuse in subclasses.
+ using SuperClass::set_size;
+
+ template <bool ForOverwrite>
+ void
+ resizeImpl (size_type N)
+ {
+ if (N == this->size ())
+ {
+ return;
+ }
+
+ if (N < this->size ())
+ {
+ this->truncate (N);
+ return;
+ }
+
+ this->reserve (N);
+ for (auto I = this->end (), E = this->begin () + N; I != E; ++I)
+ {
+ if (ForOverwrite)
+ {
+ new (&*I) T;
+ }
+ else
+ {
+ new (&*I) T ();
+ }
+ }
+ this->set_size (N);
+ }
+
+public:
+ void
+ resize (size_type N)
+ {
+ resizeImpl<false> (N);
+ }
+
+ /// Like resize, but \ref T is POD, the new values won't be initialized.
+ void
+ resize_for_overwrite (size_type N)
+ {
+ resizeImpl<true> (N);
+ }
+
+ /// Like resize, but requires that \p N is less than \a size().
+ void
+ truncate (size_type N)
+ {
+ assert (this->size () >= N && "Cannot increase size with truncate");
+ this->destroy_range (this->begin () + N, this->end ());
+ this->set_size (N);
+ }
+
+ void
+ resize (size_type N, ValueParamT NV)
+ {
+ if (N == this->size ())
+ {
+ return;
+ }
+
+ if (N < this->size ())
+ {
+ this->truncate (N);
+ return;
+ }
+
+ // N > this->size(). Defer to append.
+ this->append (N - this->size (), NV);
+ }
+
+ void
+ reserve (size_type N)
+ {
+ if (this->capacity () < N)
+ {
+ this->grow (N);
+ }
+ }
+
+ void
+ pop_back_n (size_type NumItems)
+ {
+ assert (this->size () >= NumItems);
+ truncate (this->size () - NumItems);
+ }
+
+ [[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 ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
+ void
+ append (ItTy in_start, ItTy in_end)
+ {
+ if constexpr (HasIteratorTag<ItTy, std::forward_iterator_tag>::value)
+ {
+ this->assertSafeToAddRange (in_start, in_end);
+ size_type NumInputs = std::distance (in_start, in_end);
+ this->reserve (this->size () + NumInputs);
+ this->uninitialized_copy (in_start, in_end, this->end ());
+ this->set_size (this->size () + NumInputs);
+ }
+ else
+ {
+ // Input iterator, we can't know ahead how many elements we'll add.
+ for (; in_start != in_end; ++in_start)
+ {
+ this->emplace_back (*in_start);
+ }
+ }
+ }
+
+ /// Append \p NumInputs copies of \p Elt to the end.
+ void
+ append (size_type NumInputs, ValueParamT Elt)
+ {
+ const T *EltPtr = this->reserveForParamAndGetAddress (Elt, NumInputs);
+ std::uninitialized_fill_n (this->end (), NumInputs, *EltPtr);
+ this->set_size (this->size () + NumInputs);
+ }
+
+ void
+ append (std::initializer_list<T> IL)
+ {
+ append (IL.begin (), IL.end ());
+ }
+
+ void
+ append (const SmallVectorImpl &RHS)
+ {
+ append (RHS.begin (), RHS.end ());
+ }
+
+ void
+ assign (size_type NumElts, ValueParamT Elt)
+ {
+ // Note that Elt could be an internal reference.
+ if (NumElts > this->capacity ())
+ {
+ this->growAndAssign (NumElts, Elt);
+ return;
+ }
+
+ // Assign over existing elements.
+ std::fill_n (this->begin (), std::min (NumElts, this->size ()), Elt);
+ if (NumElts > this->size ())
+ {
+ std::uninitialized_fill_n (this->end (), NumElts - this->size (), Elt);
+ }
+ else if (NumElts < this->size ())
+ {
+ this->destroy_range (this->begin () + NumElts, this->end ());
+ }
+ this->set_size (NumElts);
+ }
+
+ // FIXME: Consider assigning over existing elements, rather than clearing &
+ // re-initializing them - for all assign(...) variants.
+
+ template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
+ void
+ assign (ItTy in_start, ItTy in_end)
+ {
+ this->assertSafeToReferenceAfterClear (in_start, in_end);
+ clear ();
+ append (in_start, in_end);
+ }
+
+ void
+ assign (std::initializer_list<T> IL)
+ {
+ clear ();
+ append (IL);
+ }
+
+ void
+ assign (const SmallVectorImpl &RHS)
+ {
+ assign (RHS.begin (), RHS.end ());
+ }
+
+ template <typename U,
+ typename = std::enable_if_t<std::is_convertible_v<U, T>>>
+ void
+ assign (ArrayRef<U> AR)
+ {
+ assign (AR.begin (), AR.end ());
+ }
+
+ iterator
+ erase (const_iterator CI)
+ {
+ // Just cast away constness because this is a non-const member function.
+ iterator I = const_cast<iterator> (CI);
+
+ assert (this->isReferenceToStorage (CI) &&
+ "Iterator to erase is out of bounds.");
+
+ 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 (this->isRangeInStorage (S, E) &&
+ "Range to erase is out of bounds.");
+
+ 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);
+ }
+
+private:
+ template <class ArgType>
+ iterator
+ insert_one_impl (iterator I, ArgType &&Elt)
+ {
+ // Callers ensure that ArgType is derived from T.
+ static_assert (
+ std::is_same<std::remove_const_t<std::remove_reference_t<ArgType>>,
+ T>::value,
+ "ArgType must be derived from T!");
+
+ if (I == this->end ())
+ { // Important special case for empty vector.
+ this->push_back (::std::forward<ArgType> (Elt));
+ return this->end () - 1;
+ }
+
+ assert (this->isReferenceToStorage (I) &&
+ "Insertion iterator is out of bounds.");
+
+ // Grow if necessary.
+ size_t Index = I - this->begin ();
+ std::remove_reference_t<ArgType> *EltPtr =
+ this->reserveForParamAndGetAddress (Elt);
+ I = this->begin () + Index;
+
+ ::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 (never happens if TakesParamByValue).
+ static_assert (!TakesParamByValue || std::is_same<ArgType, T>::value,
+ "ArgType must be 'T' when taking by value!");
+ if (!TakesParamByValue &&
+ this->isReferenceToRange (EltPtr, I, this->end ()))
+ {
+ ++EltPtr;
+ }
+
+ *I = ::std::forward<ArgType> (*EltPtr);
+ return I;
+ }
+
+public:
+ iterator
+ insert (iterator I, T &&Elt)
+ {
+ return insert_one_impl (I, this->forward_value_param (std::move (Elt)));
+ }
+
+ iterator
+ insert (iterator I, const T &Elt)
+ {
+ return insert_one_impl (I, this->forward_value_param (Elt));
+ }
+
+ iterator
+ insert (iterator I, size_type NumToInsert, ValueParamT 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 (this->isReferenceToStorage (I) &&
+ "Insertion iterator is out of bounds.");
+
+ // Ensure there is enough space, and get the (maybe updated) address of
+ // Elt.
+ const T *EltPtr = this->reserveForParamAndGetAddress (Elt, 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);
+
+ // If we just moved the element we're inserting, be sure to update
+ // the reference (never happens if TakesParamByValue).
+ if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end ())
+ {
+ EltPtr += NumToInsert;
+ }
+
+ std::fill_n (I, NumToInsert, *EltPtr);
+ 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);
+
+ // If we just moved the element we're inserting, be sure to update
+ // the reference (never happens if TakesParamByValue).
+ if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end ())
+ {
+ EltPtr += NumToInsert;
+ }
+
+ // Replace the overwritten part.
+ std::fill_n (I, NumOverwritten, *EltPtr);
+
+ // Insert the non-overwritten middle part.
+ std::uninitialized_fill_n (OldEnd, NumToInsert - NumOverwritten, *EltPtr);
+ return I;
+ }
+
+ template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
+ 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;
+ }
+
+ if constexpr (!HasIteratorTag<ItTy, std::forward_iterator_tag>::value)
+ {
+ // For input iterators, we don't know the number of elements to insert.
+ size_t OldSize = this->size ();
+ append (From, To);
+ I = this->begin () + InsertElt; // Uninvalidate the iterator.
+ std::rotate (I, this->begin () + OldSize, this->end ());
+ return I;
+ }
+
+ assert (this->isReferenceToStorage (I) &&
+ "Insertion iterator is out of bounds.");
+
+ // Check that the reserve that follows doesn't invalidate the iterators.
+ this->assertSafeToAddRange (From, To);
+
+ 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 (RCC_UNLIKELY (this->size () >= this->capacity ()))
+ {
+ return this->growAndEmplaceBack (std::forward<ArgTypes> (Args)...);
+ }
+
+ ::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 ());
+ }
+ bool
+ operator> (const SmallVectorImpl &RHS) const
+ {
+ return RHS < *this;
+ }
+ bool
+ operator<= (const SmallVectorImpl &RHS) const
+ {
+ return !(*this > RHS);
+ }
+ bool
+ operator>= (const SmallVectorImpl &RHS) const
+ {
+ return !(*this < RHS);
+ }
+};
+
+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;
+ }
+ this->reserve (RHS.size ());
+ RHS.reserve (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->clear ();
+ 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->assignRemote (std::move (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 = 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->clear ();
+ 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
+{
+ alignas (T) char InlineElts[N * sizeof (T)];
+};
+
+/// 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 (T) SmallVectorStorage<T, 0>
+{
+};
+
+/// Forward declaration of SmallVector so that
+/// calculateSmallVectorDefaultInlinedElements can reference
+/// `sizeof(SmallVector<T, 0>)`.
+template <typename T, unsigned N> class RCC_GSL_OWNER SmallVector;
+
+/// Helper class for calculating the default number of inline elements for
+/// `SmallVector<T>`.
+///
+/// This should be migrated to a constexpr function when our minimum
+/// compiler support is enough for multi-statement constexpr functions.
+template <typename T> struct CalculateSmallVectorDefaultInlinedElements
+{
+ // Parameter controlling the default number of inlined elements
+ // for `SmallVector<T>`.
+ //
+ // The default number of inlined elements ensures that
+ // 1. There is at least one inlined element.
+ // 2. `sizeof(SmallVector<T>) <= kPreferredSmallVectorSizeof` unless
+ // it contradicts 1.
+ static constexpr size_t kPreferredSmallVectorSizeof = 64;
+
+ // static_assert that sizeof(T) is not "too big".
+ //
+ // Because our policy guarantees at least one inlined element, it is possible
+ // for an arbitrarily large inlined element to allocate an arbitrarily large
+ // amount of inline storage. We generally consider it an antipattern for a
+ // SmallVector to allocate an excessive amount of inline storage, so we want
+ // to call attention to these cases and make sure that users are making an
+ // intentional decision if they request a lot of inline storage.
+ //
+ // We want this assertion to trigger in pathological cases, but otherwise
+ // not be too easy to hit. To accomplish that, the cutoff is actually somewhat
+ // larger than kPreferredSmallVectorSizeof (otherwise,
+ // `SmallVector<SmallVector<T>>` would be one easy way to trip it, and that
+ // pattern seems useful in practice).
+ //
+ // One wrinkle is that this assertion is in theory non-portable, since
+ // sizeof(T) is in general platform-dependent. However, we don't expect this
+ // to be much of an issue, because most LLVM development happens on 64-bit
+ // hosts, and therefore sizeof(T) is expected to *decrease* when compiled for
+ // 32-bit hosts, dodging the issue. The reverse situation, where development
+ // happens on a 32-bit host and then fails due to sizeof(T) *increasing* on a
+ // 64-bit host, is expected to be very rare.
+ static_assert (
+ sizeof (T) <= 256,
+ "You are trying to use a default number of inlined elements for "
+ "`SmallVector<T>` but `sizeof(T)` is really big! Please use an "
+ "explicit number of inlined elements with `SmallVector<T, N>` to make "
+ "sure you really want that much inline storage.");
+
+ // Discount the size of the header itself when calculating the maximum inline
+ // bytes.
+ static constexpr size_t PreferredInlineBytes =
+ kPreferredSmallVectorSizeof - sizeof (SmallVector<T, 0>);
+ static constexpr size_t NumElementsThatFit =
+ PreferredInlineBytes / sizeof (T);
+ static constexpr size_t value =
+ NumElementsThatFit == 0 ? 1 : NumElementsThatFit;
+};
+
+/// 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
+/// In the absence of a well-motivated choice for the number of inlined
+/// elements \p N, it is recommended to use \c SmallVector<T> (that is,
+/// omitting the \p N). This will choose a default number of inlined elements
+/// reasonable for allocation on the stack (for example, trying to keep \c
+/// sizeof(SmallVector<T>) around 64 bytes).
+///
+/// \warning This does not attempt to be exception safe.
+///
+/// \see https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h
+template <typename T,
+ unsigned N = CalculateSmallVectorDefaultInlinedElements<T>::value>
+class RCC_GSL_OWNER 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 SizeArg) : SmallVectorImpl<T> (N)
+ {
+ this->resize (SizeArg);
+ }
+
+ SmallVector (size_t SizeArg, const T &Value) : SmallVectorImpl<T> (N)
+ {
+ this->assign (SizeArg, Value);
+ }
+
+ template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
+ 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->append (IL);
+ }
+
+ template <typename U,
+ typename = std::enable_if_t<std::is_convertible_v<U, T>>>
+ explicit SmallVector (ArrayRef<U> A) : SmallVectorImpl<T> (N)
+ {
+ this->append (A.begin (), A.end ());
+ }
+
+ SmallVector (const SmallVector &RHS) : SmallVectorImpl<T> (N)
+ {
+ if (!RHS.empty ())
+ {
+ SmallVectorImpl<T>::operator= (RHS);
+ }
+ }
+
+ SmallVector &
+ operator= (const SmallVector &RHS)
+ {
+ SmallVectorImpl<T>::operator= (RHS);
+ return *this;
+ }
+
+ // Reuse the move-assignment instantiation for trivially move-assignable
+ // elements. Calling moveConstructFrom unconditionally would emit an
+ // additional per-T wrapper at -O0, increasing object size.
+ // std::is_move_assignable_v<T> is too broad: it can be a false positive for
+ // types with an unconstrained assignment operator whose body is ill-formed.
+ SmallVector (SmallVector &&RHS) : SmallVectorImpl<T> (N)
+ {
+ if (!RHS.empty ())
+ {
+ bool StoleAllocation = N > 0 && !RHS.isSmall ();
+ if constexpr (std::is_trivially_move_assignable_v<T>)
+ {
+ SmallVectorImpl<T>::operator= (::std::move (RHS));
+ }
+ else
+ {
+ this->moveConstructFrom (::std::move (RHS));
+ }
+ if constexpr (N > 0)
+ {
+ if (StoleAllocation)
+ {
+ RHS.set_allocation_range (RHS.begin (), N);
+ }
+ }
+ }
+ }
+
+ SmallVector (SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T> (N)
+ {
+ if (!RHS.empty ())
+ {
+ if constexpr (std::is_trivially_move_assignable_v<T>)
+ {
+ SmallVectorImpl<T>::operator= (::std::move (RHS));
+ }
+ else
+ {
+ this->moveConstructFrom (::std::move (RHS));
+ }
+ }
+ }
+
+ SmallVector &
+ operator= (SmallVector &&RHS)
+ {
+ if (N)
+ {
+ bool StoleAllocation = this != &RHS && !RHS.isSmall ();
+ SmallVectorImpl<T>::operator= (::std::move (RHS));
+ // Restore the inline capacity after stealing RHS's allocation.
+ if (StoleAllocation)
+ {
+ RHS.set_allocation_range (RHS.begin (), N);
+ }
+ return *this;
+ }
+ // SmallVectorImpl<T>::operator= does not leverage N==0. Optimize the
+ // case.
+ if (this == &RHS)
+ {
+ return *this;
+ }
+ if (RHS.empty ())
+ {
+ this->destroy_range (this->begin (), this->end ());
+ this->Size = 0;
+ }
+ else
+ {
+ this->assignRemote (std::move (RHS));
+ }
+ return *this;
+ }
+
+ SmallVector &
+ operator= (SmallVectorImpl<T> &&RHS)
+ {
+ SmallVectorImpl<T>::operator= (::std::move (RHS));
+ return *this;
+ }
+
+ 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 ();
+}
+
+template <typename RangeType>
+using ValueTypeFromRangeType = std::ranges::range_value_t<RangeType>;
+
+/// 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<ValueTypeFromRangeType<R>, Size>
+to_vector (R &&Range)
+{
+ return SmallVector<ValueTypeFromRangeType<R>, Size> (
+ std::ranges::begin (Range), std::ranges::end (Range));
+}
+template <typename R>
+SmallVector<ValueTypeFromRangeType<R>>
+to_vector (R &&Range)
+{
+ return SmallVector<ValueTypeFromRangeType<R>> (std::ranges::begin (Range),
+ std::ranges::end (Range));
+}
+
+template <typename Out, unsigned Size, typename R>
+SmallVector<Out, Size>
+to_vector_of (R &&Range)
+{
+ return SmallVector<Out, Size> (std::ranges::begin (Range),
+ std::ranges::end (Range));
+}
+
+template <typename Out, typename R>
+SmallVector<Out>
+to_vector_of (R &&Range)
+{
+ return SmallVector<Out> (std::ranges::begin (Range),
+ std::ranges::end (Range));
+}
+
+// Explicit instantiations
+extern template class rcc::SmallVectorBase<uint32_t>;
+#if SIZE_MAX > UINT32_MAX
+extern template class rcc::SmallVectorBase<uint64_t>;
+#endif
+
+} // end namespace rcc
+
+namespace std
+{
+
+template <typename T, unsigned N> struct hash<rcc::SmallVector<T, N>>
+{
+ size_t
+ operator() (const rcc::SmallVector<T, N> &Value) const
+ {
+ size_t Seed = 0;
+ for (const T &Element : Value)
+ {
+ size_t ElementHash = std::hash<T>{}(Element);
+ Seed ^= ElementHash + static_cast<size_t> (0x9e3779b9U) + (Seed << 6) +
+ (Seed >> 2);
+ }
+ return Seed;
+ }
+};
+
+/// Implement std::swap in terms of SmallVector swap.
+template <typename T>
+inline void
+swap (rcc::SmallVectorImpl<T> &LHS, rcc::SmallVectorImpl<T> &RHS)
+{
+ LHS.swap (RHS);
+}
+
+/// Implement std::swap in terms of SmallVector swap.
+template <typename T, unsigned N>
+inline void
+swap (rcc::SmallVector<T, N> &LHS, rcc::SmallVector<T, N> &RHS)
+{
+ LHS.swap (RHS);
+}
+
+} // end namespace std
+
+#endif // RCC_ADT_SMALLVECTOR_H
diff --git a/libsupport/include/CoreLib/Compiler/Compiler.h b/libsupport/include/CoreLib/Compiler/Compiler.h
new file mode 100644
index 0000000..511c4cd
--- /dev/null
+++ b/libsupport/include/CoreLib/Compiler/Compiler.h
@@ -0,0 +1,853 @@
+/*
+ RCC-Project
+
+ Copyright (C) 2026 Richard Qin
+
+ This file is part of RCC-Project.
+
+ RCC-Project is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option) any
+ later version.
+
+ RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ RCC-Project; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>.
+*/
+
+//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines several macros, based on the current compiler. This allows
+// use of compiler-specific features in a way that remains portable. This header
+// can be included from either C or C++.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef RCC_SUPPORT_COMPILER_H
+#define RCC_SUPPORT_COMPILER_H
+
+#include "rcc/Config/rcc-config.h"
+
+#include <stddef.h>
+
+#if defined(_MSC_VER)
+#include <sal.h>
+#endif
+
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+
+#ifndef __has_extension
+#define __has_extension(x) 0
+#endif
+
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+
+#ifndef __has_warning
+#define __has_warning(x) 0
+#endif
+
+// Only use __has_cpp_attribute in C++ mode. GCC defines __has_cpp_attribute in
+// C mode, but the :: in __has_cpp_attribute(scoped::attribute) is invalid.
+#ifndef RCC_HAS_CPP_ATTRIBUTE
+#if defined(__cplusplus) && defined(__has_cpp_attribute)
+#define RCC_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute (x)
+#else
+#define RCC_HAS_CPP_ATTRIBUTE(x) 0
+#endif
+#endif
+
+/// \macro RCC_GNUC_PREREQ
+/// Extend the default __GNUC_PREREQ even if glibc's features.h isn't
+/// available.
+#ifndef RCC_GNUC_PREREQ
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+#define RCC_GNUC_PREREQ(maj, min, patch) \
+ ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
+ ((maj) << 20) + ((min) << 10) + (patch))
+#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
+#define RCC_GNUC_PREREQ(maj, min, patch) \
+ ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
+#else
+#define RCC_GNUC_PREREQ(maj, min, patch) 0
+#endif
+#endif
+
+/// \macro RCC_MSC_PREREQ
+/// Is the compiler MSVC of at least the specified version?
+/// The common \param version values to check for are:
+/// * 1910: VS2017, version 15.1 & 15.2
+/// * 1911: VS2017, version 15.3 & 15.4
+/// * 1912: VS2017, version 15.5
+/// * 1913: VS2017, version 15.6
+/// * 1914: VS2017, version 15.7
+/// * 1915: VS2017, version 15.8
+/// * 1916: VS2017, version 15.9
+/// * 1920: VS2019, version 16.0
+/// * 1921: VS2019, version 16.1
+/// * 1922: VS2019, version 16.2
+/// * 1923: VS2019, version 16.3
+/// * 1924: VS2019, version 16.4
+/// * 1925: VS2019, version 16.5
+/// * 1926: VS2019, version 16.6
+/// * 1927: VS2019, version 16.7
+/// * 1928: VS2019, version 16.8 + 16.9
+/// * 1929: VS2019, version 16.10 + 16.11
+/// * 1930: VS2022, version 17.0
+#ifdef _MSC_VER
+#define RCC_MSC_PREREQ(version) (_MSC_VER >= (version))
+
+// We require at least VS 2019.
+#if !defined(RCC_FORCE_USE_OLD_TOOLCHAIN)
+#if !RCC_MSC_PREREQ(1920)
+#error RCC requires at least VS 2019.
+#endif
+#endif
+
+#else
+#define RCC_MSC_PREREQ(version) 0
+#endif
+
+/// RCC_LIBRARY_VISIBILITY - If a class marked with this attribute is linked
+/// into a shared library, then the class should be private to the library and
+/// not accessible from outside it. Can also be used to mark variables and
+/// functions, making them private to any shared library they are linked into.
+/// On PE/COFF targets, library visibility is the default, so this isn't needed.
+///
+/// RCC_EXTERNAL_VISIBILITY - classes, functions, and variables marked with
+/// this attribute will be made public and visible outside of any shared library
+/// they are linked in to.
+
+#if RCC_HAS_CPP_ATTRIBUTE(gnu::visibility) && defined(__GNUC__) && \
+ !defined(__clang__)
+#define RCC_ATTRIBUTE_VISIBILITY_HIDDEN [[gnu::visibility ("hidden")]]
+#define RCC_ATTRIBUTE_VISIBILITY_DEFAULT [[gnu::visibility ("default")]]
+#elif __has_attribute(visibility)
+#define RCC_ATTRIBUTE_VISIBILITY_HIDDEN __attribute__ ((visibility ("hidden")))
+#define RCC_ATTRIBUTE_VISIBILITY_DEFAULT \
+ __attribute__ ((visibility ("default")))
+#else
+#define RCC_ATTRIBUTE_VISIBILITY_HIDDEN
+#define RCC_ATTRIBUTE_VISIBILITY_DEFAULT
+#endif
+
+#if defined(RCC_BUILD_RCC_DYLIB) || defined(RCC_BUILD_SHARED_LIBS)
+#define RCC_EXTERNAL_VISIBILITY RCC_ATTRIBUTE_VISIBILITY_DEFAULT
+#else
+#define RCC_EXTERNAL_VISIBILITY
+#endif
+
+#if (!(defined(_WIN32) || defined(__CYGWIN__)) || \
+ ((defined(__MINGW32__) || defined(__CYGWIN__)) && defined(__clang__)))
+#define RCC_LIBRARY_VISIBILITY RCC_ATTRIBUTE_VISIBILITY_HIDDEN
+// Clang compilers older then 15 do not support gnu style attributes on
+// namespaces.
+#if defined(__clang__) && __clang_major__ < 15
+#define RCC_LIBRARY_VISIBILITY_NAMESPACE [[gnu::visibility ("hidden")]]
+#else
+#define RCC_LIBRARY_VISIBILITY_NAMESPACE RCC_ATTRIBUTE_VISIBILITY_HIDDEN
+#endif
+#define RCC_ALWAYS_EXPORT RCC_ATTRIBUTE_VISIBILITY_DEFAULT
+#elif defined(_WIN32)
+#define RCC_ALWAYS_EXPORT __declspec (dllexport)
+#define RCC_LIBRARY_VISIBILITY
+#define RCC_LIBRARY_VISIBILITY_NAMESPACE
+#else
+#define RCC_LIBRARY_VISIBILITY
+#define RCC_ALWAYS_EXPORT
+#define RCC_LIBRARY_VISIBILITY_NAMESPACE
+#endif
+
+/// RCC_ABI is the main export/visibility macro to mark something as explicitly
+/// exported when rcc is built as a shared library with everything else that is
+/// unannotated will have internal visibility.
+///
+/// RCC_ABI_EXPORT is for the special case for things like plugin symbol
+/// declarations or definitions where we don't want the macro to be switching
+/// between dllexport and dllimport on windows based on what codebase is being
+/// built, it will only be dllexport. For non windows platforms this macro
+/// behaves the same as RCC_ABI.
+///
+/// RCC_EXPORT_TEMPLATE is used on explicit template instantiations in source
+/// files that were declared extern in a header. This macro is only set as a
+/// compiler export attribute on windows, on other platforms it does nothing.
+///
+/// RCC_TEMPLATE_ABI is for annotating extern template declarations in headers
+/// for both functions and classes. On windows its turned in to dllimport for
+/// library consumers, for other platforms its a default visibility attribute.
+///
+/// RCC_ABI_FOR_TEST is for annotating symbols that are exported from a
+/// library-internal header solely so that unit tests can link against them.
+/// Symbols in RCC's public headers are part of the RCC public interface and
+/// should use RCC_ABI. RCC_ABI_FOR_TEST is reserved for internal headers,
+/// whose symbols could be conditionally excluded when not building tests in the
+/// future.
+///
+#ifndef RCC_ABI_GENERATING_ANNOTATIONS
+// Marker to add to classes or functions in public headers that should not have
+// export macros added to them by the clang tool
+#define RCC_ABI_NOT_EXPORTED
+// TODO(https://github.com/rcc/rcc-project/issues/145406): eliminate need for
+// two preprocessor definitions to gate RCC_ABI macro definitions.
+#if defined(RCC_ENABLE_RCC_EXPORT_ANNOTATIONS) && !defined(RCC_BUILD_STATIC)
+#if defined(_WIN32) && !defined(__MINGW32__)
+#if defined(RCC_EXPORTS)
+#define RCC_ABI __declspec (dllexport)
+#define RCC_TEMPLATE_ABI
+#define RCC_EXPORT_TEMPLATE __declspec (dllexport)
+#else
+#define RCC_ABI __declspec (dllimport)
+#define RCC_TEMPLATE_ABI __declspec (dllimport)
+#define RCC_EXPORT_TEMPLATE
+#endif
+#define RCC_ABI_EXPORT __declspec (dllexport)
+#elif __has_attribute(visibility)
+#if defined(__ELF__) || defined(__MINGW32__) || defined(_AIX) || \
+ defined(__MVS__) || defined(__CYGWIN__)
+#define RCC_ABI __attribute__ ((visibility ("default")))
+#define RCC_TEMPLATE_ABI RCC_ABI
+#define RCC_EXPORT_TEMPLATE
+#define RCC_ABI_EXPORT RCC_ABI
+#elif defined(__MACH__) || defined(__wasm__) || defined(__EMSCRIPTEN__)
+#define RCC_ABI __attribute__ ((visibility ("default")))
+#define RCC_TEMPLATE_ABI
+#define RCC_EXPORT_TEMPLATE
+#define RCC_ABI_EXPORT RCC_ABI
+#endif
+#endif
+#endif
+#if !defined(RCC_ABI)
+#define RCC_ABI
+#define RCC_TEMPLATE_ABI
+#define RCC_EXPORT_TEMPLATE
+#define RCC_ABI_EXPORT
+#endif
+#define RCC_ABI_FOR_TEST RCC_ABI
+#endif
+
+#if defined(__GNUC__)
+#define RCC_PREFETCH(addr, rw, locality) __builtin_prefetch (addr, rw, locality)
+#else
+#define RCC_PREFETCH(addr, rw, locality)
+#endif
+
+#if __has_attribute(uninitialized)
+#define RCC_ATTRIBUTE_UNINITIALIZED __attribute__ ((uninitialized))
+#else
+#define RCC_ATTRIBUTE_UNINITIALIZED
+#endif
+
+#if __has_attribute(used)
+#define RCC_ATTRIBUTE_USED __attribute__ ((__used__))
+#else
+#define RCC_ATTRIBUTE_USED
+#endif
+
+#if __has_attribute(warn_unused)
+#define RCC_ATTRIBUTE_WARN_UNUSED __attribute__ ((warn_unused))
+#else
+#define RCC_ATTRIBUTE_WARN_UNUSED
+#endif
+
+// Only enabled for clang:
+// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99587
+// GCC may produce "warning: 'retain' attribute ignored" (despite
+// __has_attribute(retain) being 1).
+#if defined(__clang__) && __has_attribute(retain)
+#define RCC_ATTRIBUTE_RETAIN __attribute__ ((__retain__))
+#else
+#define RCC_ATTRIBUTE_RETAIN
+#endif
+
+// For deprecations that are not a simple rename, use [[deprecated(MSG)]]
+// instead.
+#if defined(__clang__)
+#define RCC_DEPRECATED_WITH_FIXIT(MSG, FIX) \
+ __attribute__ ((deprecated (MSG, FIX)))
+#else
+#define RCC_DEPRECATED_WITH_FIXIT(MSG, FIX) [[deprecated (MSG)]]
+#endif
+
+// clang-format off
+#if defined(__clang__) || defined(__GNUC__)
+#define RCC_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#define RCC_SUPPRESS_DEPRECATED_DECLARATIONS_POP \
+ _Pragma("GCC diagnostic pop")
+#elif defined(_MSC_VER)
+#define RCC_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH \
+ __pragma(warning(push)) \
+ __pragma(warning(disable : 4996))
+#define RCC_SUPPRESS_DEPRECATED_DECLARATIONS_POP \
+ __pragma(warning(pop))
+#else
+#define RCC_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH
+#define RCC_SUPPRESS_DEPRECATED_DECLARATIONS_POP
+#endif
+// clang-format on
+
+// Indicate that a non-static, non-const C++ member function reinitializes
+// the entire object to a known state, independent of the previous state of
+// the object.
+//
+// The clang-tidy check bugprone-use-after-move recognizes this attribute as a
+// marker that a moved-from object has left the indeterminate state and can be
+// reused.
+#if RCC_HAS_CPP_ATTRIBUTE(clang::reinitializes)
+#define RCC_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]
+#else
+#define RCC_ATTRIBUTE_REINITIALIZES
+#endif
+
+// Some compilers warn about unused functions. When a function is sometimes
+// used or not depending on build settings (e.g. a function only called from
+// within "assert"), this attribute can be used to suppress such warnings.
+//
+// However, it shouldn't be used for unused *variables*, as those have a much
+// more portable solution:
+// (void)unused_var_name;
+// Prefer cast-to-void wherever it is sufficient.
+#if __has_attribute(unused)
+#define RCC_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#else
+#define RCC_ATTRIBUTE_UNUSED
+#endif
+
+// FIXME: Provide this for PE/COFF targets.
+#if __has_attribute(weak) && !defined(__MINGW32__) && !defined(__CYGWIN__) && \
+ !defined(_WIN32)
+#define RCC_HAS_ATTRIBUTE_WEAK 1
+#else
+#define RCC_HAS_ATTRIBUTE_WEAK 0
+#endif
+#if RCC_HAS_ATTRIBUTE_WEAK
+#define RCC_ATTRIBUTE_WEAK __attribute__ ((__weak__))
+#else
+#define RCC_ATTRIBUTE_WEAK
+#endif
+
+// Prior to clang 3.2, clang did not accept any spelling of
+// __has_attribute(const), so assume it is supported.
+#if defined(__clang__) || defined(__GNUC__)
+// aka 'CONST' but following RCC Conventions.
+#define RCC_READNONE __attribute__ ((__const__))
+#else
+#define RCC_READNONE
+#endif
+
+#if __has_attribute(pure) || defined(__GNUC__)
+// aka 'PURE' but following RCC Conventions.
+#define RCC_READONLY __attribute__ ((__pure__))
+#else
+#define RCC_READONLY
+#endif
+
+#if __has_attribute(minsize)
+#define RCC_ATTRIBUTE_MINSIZE __attribute__ ((minsize))
+#else
+#define RCC_ATTRIBUTE_MINSIZE
+#endif
+
+#if __has_builtin(__builtin_expect) || defined(__GNUC__)
+#define RCC_LIKELY(EXPR) __builtin_expect ((bool)(EXPR), true)
+#define RCC_UNLIKELY(EXPR) __builtin_expect ((bool)(EXPR), false)
+#else
+#define RCC_LIKELY(EXPR) (EXPR)
+#define RCC_UNLIKELY(EXPR) (EXPR)
+#endif
+
+/// RCC_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so,
+/// mark a method "not for inlining".
+#if __has_attribute(noinline)
+#define RCC_ATTRIBUTE_NOINLINE __attribute__ ((noinline))
+#elif defined(_MSC_VER)
+#define RCC_ATTRIBUTE_NOINLINE __declspec (noinline)
+#else
+#define RCC_ATTRIBUTE_NOINLINE
+#endif
+
+/// RCC_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do
+/// so, mark a method "always inline" because it is performance sensitive.
+#if __has_attribute(always_inline)
+#define RCC_ATTRIBUTE_ALWAYS_INLINE inline __attribute__ ((always_inline))
+#elif defined(_MSC_VER)
+#define RCC_ATTRIBUTE_ALWAYS_INLINE __forceinline
+#else
+#define RCC_ATTRIBUTE_ALWAYS_INLINE inline
+#endif
+
+/// RCC_ATTRIBUTE_ALWAYS_INLINE_UNLESS_DEBUG - Like
+/// RCC_ATTRIBUTE_ALWAYS_INLINE but disabled in debug builds to avoid stack
+/// overflow with deep recursion.
+#if defined(NDEBUG)
+#define RCC_ATTRIBUTE_ALWAYS_INLINE_UNLESS_DEBUG RCC_ATTRIBUTE_ALWAYS_INLINE
+#else
+#define RCC_ATTRIBUTE_ALWAYS_INLINE_UNLESS_DEBUG inline
+#endif
+
+/// RCC_ATTRIBUTE_NO_DEBUG - On compilers where we have a directive to do
+/// so, mark a method "no debug" because debug info makes the debugger
+/// experience worse.
+#if __has_attribute(nodebug)
+#define RCC_ATTRIBUTE_NODEBUG __attribute__ ((nodebug))
+#else
+#define RCC_ATTRIBUTE_NODEBUG
+#endif
+
+#if __has_attribute(returns_nonnull)
+#define RCC_ATTRIBUTE_RETURNS_NONNULL __attribute__ ((returns_nonnull))
+#elif defined(_MSC_VER)
+#define RCC_ATTRIBUTE_RETURNS_NONNULL _Ret_notnull_
+#else
+#define RCC_ATTRIBUTE_RETURNS_NONNULL
+#endif
+
+/// RCC_ATTRIBUTE_RESTRICT - Annotates a pointer to tell the compiler that
+/// it is not aliased in the current scope.
+#if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
+#define RCC_ATTRIBUTE_RESTRICT __restrict
+#else
+#define RCC_ATTRIBUTE_RESTRICT
+#endif
+
+/// \macro RCC_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a
+/// pointer that does not alias any other valid pointer.
+#ifdef __GNUC__
+#define RCC_ATTRIBUTE_RETURNS_NOALIAS __attribute__ ((__malloc__))
+#elif defined(_MSC_VER)
+#define RCC_ATTRIBUTE_RETURNS_NOALIAS __declspec (restrict)
+#else
+#define RCC_ATTRIBUTE_RETURNS_NOALIAS
+#endif
+
+/// RCC_FALLTHROUGH - Mark fallthrough cases in switch statements.
+#if defined(__cplusplus) && __cplusplus > 201402L && \
+ RCC_HAS_CPP_ATTRIBUTE(fallthrough)
+#define RCC_FALLTHROUGH [[fallthrough]]
+#elif RCC_HAS_CPP_ATTRIBUTE(gnu::fallthrough)
+#define RCC_FALLTHROUGH [[gnu::fallthrough]]
+#elif __has_attribute(fallthrough)
+#define RCC_FALLTHROUGH __attribute__ ((fallthrough))
+#elif RCC_HAS_CPP_ATTRIBUTE(clang::fallthrough)
+#define RCC_FALLTHROUGH [[clang::fallthrough]]
+#else
+#define RCC_FALLTHROUGH
+#endif
+
+/// RCC_REQUIRE_CONSTANT_INITIALIZATION - Apply this to globals to ensure that
+/// they are constant initialized.
+#if RCC_HAS_CPP_ATTRIBUTE(clang::require_constant_initialization)
+#define RCC_REQUIRE_CONSTANT_INITIALIZATION \
+ [[clang::require_constant_initialization]]
+#else
+#define RCC_REQUIRE_CONSTANT_INITIALIZATION
+#endif
+
+/// RCC_GSL_OWNER - Apply this to owning classes like SmallVector to enable
+/// lifetime warnings.
+#if RCC_HAS_CPP_ATTRIBUTE(gsl::Owner)
+#define RCC_GSL_OWNER [[gsl::Owner]]
+#else
+#define RCC_GSL_OWNER
+#endif
+
+/// RCC_GSL_POINTER - Apply this to non-owning classes like
+/// StringRef to enable lifetime warnings.
+#if RCC_HAS_CPP_ATTRIBUTE(gsl::Pointer)
+#define RCC_GSL_POINTER [[gsl::Pointer]]
+#else
+#define RCC_GSL_POINTER
+#endif
+
+#if RCC_HAS_CPP_ATTRIBUTE(clang::lifetimebound)
+#define RCC_LIFETIME_BOUND [[clang::lifetimebound]]
+#else
+#define RCC_LIFETIME_BOUND
+#endif
+
+#if RCC_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L
+#define RCC_CTOR_NODISCARD [[nodiscard]]
+#else
+#define RCC_CTOR_NODISCARD
+#endif
+
+// Macro to suppress the MSVC warning C4848:
+// "support for attribute [[msvc::no_unique_address]] in C++17 and earlier
+// is a vendor extension".
+// This warning is removed in versions >= 19.43.
+#if !defined(_MSC_VER) || _MSC_VER >= 1943 || defined(__clang__)
+#define RCC_SUPPRESS_MSVC_ATTR_IS_VENDOR_EXT_PUSH
+#define RCC_SUPPRESS_MSVC_ATTR_IS_VENDOR_EXT_POP
+#else // MSVC < 19.43
+#define RCC_SUPPRESS_MSVC_ATTR_IS_VENDOR_EXT_PUSH \
+ __pragma (warning (push)) __pragma (warning (disable : 4848))
+#define RCC_SUPPRESS_MSVC_ATTR_IS_VENDOR_EXT_POP __pragma (warning (pop))
+#endif
+
+#if RCC_HAS_CPP_ATTRIBUTE(no_unique_address)
+#define RCC_NO_UNIQUE_ADDRESS [[no_unique_address]]
+#elif RCC_HAS_CPP_ATTRIBUTE(msvc::no_unique_address)
+#define RCC_NO_UNIQUE_ADDRESS \
+ RCC_SUPPRESS_MSVC_ATTR_IS_VENDOR_EXT_PUSH \
+ [[msvc::no_unique_address]] RCC_SUPPRESS_MSVC_ATTR_IS_VENDOR_EXT_POP
+#else
+#define RCC_NO_UNIQUE_ADDRESS
+#endif
+
+/// RCC_EXTENSION - Support compilers where we have a keyword to suppress
+/// pedantic diagnostics.
+#ifdef __GNUC__
+#define RCC_EXTENSION __extension__
+#else
+#define RCC_EXTENSION
+#endif
+
+/// RCC_BUILTIN_UNREACHABLE - On compilers which support it, expands
+/// to an expression which states that it is undefined behavior for the
+/// compiler to reach this point. Otherwise is not defined.
+///
+/// '#else' is intentionally left out so that other macro logic (e.g.,
+/// RCC_ASSUME_ALIGNED and rcc_unreachable()) can detect whether
+/// RCC_BUILTIN_UNREACHABLE has a definition.
+#if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
+#define RCC_BUILTIN_UNREACHABLE __builtin_unreachable ()
+#elif defined(_MSC_VER)
+#define RCC_BUILTIN_UNREACHABLE __assume (false)
+#endif
+
+/// RCC_BUILTIN_TRAP - On compilers which support it, expands to an expression
+/// which causes the program to exit abnormally.
+#if __has_builtin(__builtin_trap) || defined(__GNUC__)
+#define RCC_BUILTIN_TRAP __builtin_trap ()
+#elif defined(_MSC_VER)
+// The __debugbreak intrinsic is supported by MSVC, does not require forward
+// declarations involving platform-specific typedefs (unlike RaiseException),
+// results in a call to vectored exception handlers, and encodes to a short
+// instruction that still causes the trapping behavior we want.
+#define RCC_BUILTIN_TRAP __debugbreak ()
+#else
+#define RCC_BUILTIN_TRAP *(volatile int *)0x11 = 0
+#endif
+
+/// RCC_BUILTIN_DEBUGTRAP - On compilers which support it, expands to
+/// an expression which causes the program to break while running
+/// under a debugger.
+#if __has_builtin(__builtin_debugtrap)
+#define RCC_BUILTIN_DEBUGTRAP __builtin_debugtrap ()
+#elif defined(_MSC_VER)
+// The __debugbreak intrinsic is supported by MSVC and breaks while
+// running under the debugger, and also supports invoking a debugger
+// when the OS is configured appropriately.
+#define RCC_BUILTIN_DEBUGTRAP __debugbreak ()
+#else
+// Just continue execution when built with compilers that have no
+// support. This is a debugging aid and not intended to force the
+// program to abort if encountered.
+#define RCC_BUILTIN_DEBUGTRAP
+#endif
+
+/// \macro RCC_ASSUME_ALIGNED
+/// Returns a pointer with an assumed alignment.
+#if __has_builtin(__builtin_assume_aligned) || defined(__GNUC__)
+#define RCC_ASSUME_ALIGNED(p, a) __builtin_assume_aligned (p, a)
+#elif defined(RCC_BUILTIN_UNREACHABLE)
+#define RCC_ASSUME_ALIGNED(p, a) \
+ (((uintptr_t (p) % (a)) == 0) ? (p) : (RCC_BUILTIN_UNREACHABLE, (p)))
+#else
+#define RCC_ASSUME_ALIGNED(p, a) (p)
+#endif
+
+/// \macro RCC_PACKED
+/// Used to specify a packed structure.
+/// RCC_PACKED(
+/// struct A {
+/// int i;
+/// int j;
+/// int k;
+/// long long l;
+/// });
+///
+/// RCC_PACKED_START
+/// struct B {
+/// int i;
+/// int j;
+/// int k;
+/// long long l;
+/// };
+/// RCC_PACKED_END
+#ifdef _MSC_VER
+#define RCC_PACKED(d) __pragma (pack (push, 1)) d __pragma (pack (pop))
+#define RCC_PACKED_START __pragma (pack (push, 1))
+#define RCC_PACKED_END __pragma (pack (pop))
+#else
+#define RCC_PACKED(d) d __attribute__ ((packed))
+#define RCC_PACKED_START _Pragma ("pack(push, 1)")
+#define RCC_PACKED_END _Pragma ("pack(pop)")
+#endif
+
+/// \macro RCC_MEMORY_SANITIZER_BUILD
+/// Whether RCC itself is built with MemorySanitizer instrumentation.
+#if __has_feature(memory_sanitizer)
+#define RCC_MEMORY_SANITIZER_BUILD 1
+#include <sanitizer/msan_interface.h>
+#define RCC_NO_SANITIZE_MEMORY_ATTRIBUTE __attribute__ ((no_sanitize_memory))
+#else
+#define RCC_MEMORY_SANITIZER_BUILD 0
+#define __msan_allocated_memory(p, size)
+#define __msan_unpoison(p, size)
+#define RCC_NO_SANITIZE_MEMORY_ATTRIBUTE
+#endif
+
+/// \macro RCC_ADDRESS_SANITIZER_BUILD
+/// Whether RCC itself is built with AddressSanitizer instrumentation.
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+#define RCC_ADDRESS_SANITIZER_BUILD 1
+#if __has_include(<sanitizer/asan_interface.h>)
+#include <sanitizer/asan_interface.h>
+#else
+// These declarations exist to support ASan with MSVC. If MSVC eventually ships
+// asan_interface.h in their headers, then we can remove this.
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ void
+ __asan_poison_memory_region (void const volatile *addr, size_t size);
+ void
+ __asan_unpoison_memory_region (void const volatile *addr, size_t size);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+#endif
+#else
+#define RCC_ADDRESS_SANITIZER_BUILD 0
+#define __asan_poison_memory_region(p, size)
+#define __asan_unpoison_memory_region(p, size)
+#endif
+
+/// \macro RCC_HWADDRESS_SANITIZER_BUILD
+/// Whether RCC itself is built with HWAddressSanitizer instrumentation.
+#if __has_feature(hwaddress_sanitizer)
+#define RCC_HWADDRESS_SANITIZER_BUILD 1
+#else
+#define RCC_HWADDRESS_SANITIZER_BUILD 0
+#endif
+
+/// \macro RCC_THREAD_SANITIZER_BUILD
+/// Whether RCC itself is built with ThreadSanitizer instrumentation.
+#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
+#define RCC_THREAD_SANITIZER_BUILD 1
+#else
+#define RCC_THREAD_SANITIZER_BUILD 0
+#endif
+
+#if RCC_THREAD_SANITIZER_BUILD
+// Thread Sanitizer is a tool that finds races in code.
+// See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations .
+// tsan detects these exact functions by name.
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ void
+ AnnotateHappensAfter (const char *file, int line, const volatile void *cv);
+ void
+ AnnotateHappensBefore (const char *file, int line, const volatile void *cv);
+ void
+ AnnotateIgnoreWritesBegin (const char *file, int line);
+ void
+ AnnotateIgnoreWritesEnd (const char *file, int line);
+#ifdef __cplusplus
+}
+#endif
+
+// This marker is used to define a happens-before arc. The race detector will
+// infer an arc from the begin to the end when they share the same pointer
+// argument.
+#define TsanHappensBefore(cv) AnnotateHappensBefore (__FILE__, __LINE__, cv)
+
+// This marker defines the destination of a happens-before arc.
+#define TsanHappensAfter(cv) AnnotateHappensAfter (__FILE__, __LINE__, cv)
+
+// Ignore any races on writes between here and the next TsanIgnoreWritesEnd.
+#define TsanIgnoreWritesBegin() AnnotateIgnoreWritesBegin (__FILE__, __LINE__)
+
+// Resume checking for racy writes.
+#define TsanIgnoreWritesEnd() AnnotateIgnoreWritesEnd (__FILE__, __LINE__)
+#else
+#define TsanHappensBefore(cv)
+#define TsanHappensAfter(cv)
+#define TsanIgnoreWritesBegin()
+#define TsanIgnoreWritesEnd()
+#endif
+
+/// \macro RCC_NO_SANITIZE
+/// Disable a particular sanitizer for a function.
+#if __has_attribute(no_sanitize)
+#define RCC_NO_SANITIZE(KIND) __attribute__ ((no_sanitize (KIND)))
+#else
+#define RCC_NO_SANITIZE(KIND)
+#endif
+
+/// Mark debug helper function definitions like dump() that should not be
+/// stripped from debug builds.
+/// Note that you should also surround dump() functions with
+/// `#if !defined(NDEBUG) || defined(RCC_ENABLE_DUMP)` so they do always
+/// get stripped in release builds.
+// FIXME: Move this to a private config.h as it's not usable in public headers.
+#if !defined(NDEBUG) || defined(RCC_ENABLE_DUMP)
+#define RCC_DUMP_METHOD \
+ RCC_ATTRIBUTE_NOINLINE RCC_ATTRIBUTE_USED RCC_ATTRIBUTE_RETAIN
+#else
+#define RCC_DUMP_METHOD RCC_ATTRIBUTE_NOINLINE
+#endif
+
+/// \macro RCC_PRETTY_FUNCTION
+/// Gets a user-friendly looking function signature for the current scope
+/// using the best available method on each platform. The exact format of the
+/// resulting string is implementation specific and non-portable, so this should
+/// only be used, for example, for logging or diagnostics.
+#if defined(_MSC_VER)
+#define RCC_PRETTY_FUNCTION __FUNCSIG__
+#elif defined(__GNUC__) || defined(__clang__)
+#define RCC_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#else
+#define RCC_PRETTY_FUNCTION __func__
+#endif
+
+/// \macro RCC_THREAD_LOCAL
+/// A thread-local storage specifier which can be used with globals,
+/// extern globals, and static globals.
+///
+/// This is essentially an extremely restricted analog to C++11's thread_local
+/// support. It uses thread_local if available, falling back on gcc __thread
+/// if not. __thread doesn't support many of the C++11 thread_local's
+/// features. You should only use this for PODs that you can statically
+/// initialize to some constant value. In almost all circumstances this is most
+/// appropriate for use with a pointer, integer, or small aggregation of
+/// pointers and integers.
+#if RCC_ENABLE_THREADS
+#if __has_feature(cxx_thread_local) || defined(_MSC_VER)
+#define RCC_THREAD_LOCAL thread_local
+#else
+// Clang, GCC, and other compatible compilers used __thread prior to C++11 and
+// we only need the restricted functionality that provides.
+#define RCC_THREAD_LOCAL __thread
+#endif
+#else // !RCC_ENABLE_THREADS
+// If threading is disabled entirely, this compiles to nothing and you get
+// a normal global variable.
+#define RCC_THREAD_LOCAL
+#endif
+
+/// \macro RCC_ENABLE_EXCEPTIONS
+/// Whether RCC is built with exception support.
+#if __has_feature(cxx_exceptions)
+#define RCC_ENABLE_EXCEPTIONS 1
+#elif defined(__GNUC__) && defined(__EXCEPTIONS)
+#define RCC_ENABLE_EXCEPTIONS 1
+#elif defined(_MSC_VER) && defined(_CPPUNWIND)
+#define RCC_ENABLE_EXCEPTIONS 1
+#endif
+
+/// \macro RCC_NO_PROFILE_INSTRUMENT_FUNCTION
+/// Disable the profile instrument for a function.
+#if __has_attribute(no_profile_instrument_function)
+#define RCC_NO_PROFILE_INSTRUMENT_FUNCTION \
+ __attribute__ ((no_profile_instrument_function))
+#else
+#define RCC_NO_PROFILE_INSTRUMENT_FUNCTION
+#endif
+
+/// \macro RCC_PREFERRED_TYPE
+/// Adjust type of bit-field in debug info.
+#if __has_attribute(preferred_type)
+#define RCC_PREFERRED_TYPE(T) __attribute__ ((preferred_type (T)))
+#else
+#define RCC_PREFERRED_TYPE(T)
+#endif
+
+#if RCC_HAS_CPP_ATTRIBUTE(clang::ptrauth_vtable_pointer) && \
+ (defined(__PTRAUTH__) || __has_feature(ptrauth_calls))
+#define RCC_MOVABLE_POLYMORPHIC_TYPE \
+ [[clang::ptrauth_vtable_pointer (default_key, no_address_discrimination, \
+ default_extra_discrimination)]]
+#else
+#define RCC_MOVABLE_POLYMORPHIC_TYPE
+#endif
+
+/// \macro RCC_VIRTUAL_ANCHOR_FUNCTION
+/// This macro is used to adhere to RCC's policy that each class with a vtable
+/// must have at least one out-of-line virtual function. This macro allows us
+/// to declare such a function in `final` classes without triggering a warning.
+// clang-format off
+// Autoformatting makes this look awful.
+#if defined(__clang__)
+ // Make sure this is only parsed if __clang__ is defined
+ #if __has_warning("-Wunnecessary-virtual-specifier")
+ #define RCC_DECLARE_VIRTUAL_ANCHOR_FUNCTION() \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Wunnecessary-virtual-specifier\"") \
+ virtual void anchor() \
+ _Pragma("clang diagnostic pop")
+ #else // __has_warning
+ #define RCC_DECLARE_VIRTUAL_ANCHOR_FUNCTION() \
+ virtual void anchor()
+ #endif
+#else // defined(__clang__)
+ #define RCC_DECLARE_VIRTUAL_ANCHOR_FUNCTION() \
+ virtual void anchor()
+#endif
+// clang-format on
+
+/// \macro RCC_IS_X86
+/// Whether the target architecture is x86 / x86-64.
+#if defined(__x86_64__) || defined(__i386__)
+#define RCC_IS_X86 1
+#else
+#define RCC_IS_X86 0
+#endif
+
+/// \macro RCC_TARGET_SSE42
+/// Function attribute to compile a function with SSE4.2 enabled.
+#if defined(__has_attribute) && __has_attribute(target)
+#define RCC_TARGET_SSE42 __attribute__ ((target ("sse4.2")))
+#else
+#define RCC_TARGET_SSE42
+#endif
+
+#if __has_builtin(__builtin_cpu_supports) && \
+ (defined(__linux__) || defined(__APPLE__))
+#define RCC_CPU_SUPPORTS(feature) __builtin_cpu_supports (feature)
+#else
+#define RCC_CPU_SUPPORTS(feature) 0
+#endif
+
+/// \macro RCC_CPU_SUPPORTS_SSE42
+/// Expands to true if the runtime cpu supports SSE4.2, or if compiled with
+/// SSE4.2 enabled.
+#if defined(__SSE4_2__)
+#define RCC_CPU_SUPPORTS_SSE42 1
+#else
+#define RCC_CPU_SUPPORTS_SSE42 RCC_CPU_SUPPORTS ("sse4.2")
+#endif
+
+#endif
diff --git a/libsupport/include/CoreLib/Error/ErrorHandling.h b/libsupport/include/CoreLib/Error/ErrorHandling.h
new file mode 100644
index 0000000..5ab5a9e
--- /dev/null
+++ b/libsupport/include/CoreLib/Error/ErrorHandling.h
@@ -0,0 +1,217 @@
+/*
+ RCC-Project
+
+ Copyright (C) 2026 Richard Qin
+
+ This file is part of RCC-Project.
+
+ RCC-Project is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option) any
+ later version.
+
+ RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ RCC-Project; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>.
+ */
+
+//===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an API used to indicate fatal error conditions. Non-fatal
+// errors (most of them) should be handled through LLVMContext.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef RCC_SUPPORT_ERRORHANDLING_H
+#define RCC_SUPPORT_ERRORHANDLING_H
+
+#include "CoreLib/Compiler/Compiler.h"
+
+namespace rcc
+{
+class StringRef;
+class Twine;
+
+/// An error handler callback.
+using fatal_error_handler_t = void (*) (void *user_data, const char *reason,
+ bool gen_crash_diag);
+
+/// install_fatal_error_handler - Installs a new error handler to be used
+/// whenever a serious (non-recoverable) error is encountered by LLVM.
+///
+/// If no error handler is installed the default is to print the error message
+/// to stderr, and call exit(1). If an error handler is installed then it is
+/// the handler's responsibility to log the message, it will no longer be
+/// printed to stderr. If the error handler returns, then exit(1) will be
+/// called.
+///
+/// It is dangerous to naively use an error handler which throws an exception.
+/// Even though some applications desire to gracefully recover from arbitrary
+/// faults, blindly throwing exceptions through unfamiliar code isn't a way to
+/// achieve this.
+///
+/// \param user_data - An argument which will be passed to the install error
+/// handler.
+RCC_ABI void
+install_fatal_error_handler (fatal_error_handler_t handler,
+ void *user_data = nullptr);
+
+/// Restores default error handling behaviour.
+RCC_ABI void
+remove_fatal_error_handler ();
+
+/// ScopedFatalErrorHandler - This is a simple helper class which just
+/// calls install_fatal_error_handler in its constructor and
+/// remove_fatal_error_handler in its destructor.
+struct ScopedFatalErrorHandler
+{
+ explicit ScopedFatalErrorHandler (fatal_error_handler_t handler,
+ void *user_data = nullptr)
+ {
+ install_fatal_error_handler (handler, user_data);
+ }
+
+ ~ScopedFatalErrorHandler ()
+ {
+ remove_fatal_error_handler ();
+ }
+};
+
+/// @deprecated Use reportFatalInternalError() or reportFatalUsageError()
+/// instead.
+[[noreturn]] RCC_ABI void
+report_fatal_error (const char *reason, bool gen_crash_diag = true);
+[[noreturn]] RCC_ABI void
+report_fatal_error (StringRef reason, bool gen_crash_diag = true);
+[[noreturn]] RCC_ABI void
+report_fatal_error (const Twine &reason, bool gen_crash_diag = true);
+
+/// Report a fatal error that likely indicates a bug in LLVM. It serves a
+/// similar purpose as an assertion, but is always enabled, regardless of the
+/// value of NDEBUG.
+///
+/// This will call installed error handlers (or print the message by default)
+/// and then abort. This will produce a crash trace and *will* ask users to
+/// report an LLVM bug.
+[[noreturn]] RCC_ABI void
+reportFatalInternalError (const char *reason);
+[[noreturn]] RCC_ABI void
+reportFatalInternalError (StringRef reason);
+[[noreturn]] RCC_ABI void
+reportFatalInternalError (const Twine &reason);
+
+/// Report a fatal error that does not indicate a bug in LLVM.
+///
+/// This can be used in contexts where a proper error reporting mechanism
+/// (such as Error/Expected or DiagnosticInfo) is currently not supported, and
+/// would be too involved to introduce at the moment.
+///
+/// Examples where this function should be used instead of
+/// reportFatalInternalError() include invalid inputs or options, but also
+/// environment error conditions outside LLVM's control. It should also be used
+/// for known unsupported/unimplemented functionality.
+///
+/// This will call installed error handlers (or print the message by default)
+/// and then exit with code 1. It will not produce a crash trace and will
+/// *not* ask users to report an LLVM bug.
+[[noreturn]] RCC_ABI void
+reportFatalUsageError (const char *reason);
+[[noreturn]] RCC_ABI void
+reportFatalUsageError (StringRef reason);
+[[noreturn]] RCC_ABI void
+reportFatalUsageError (const Twine &reason);
+
+/// Installs a new bad alloc error handler that should be used whenever a
+/// bad alloc error, e.g. failing malloc/calloc, is encountered by LLVM.
+///
+/// The user can install a bad alloc handler, in order to define the behavior
+/// in case of failing allocations, e.g. throwing an exception. Note that this
+/// handler must not trigger any additional allocations itself.
+///
+/// If no error handler is installed the default is to print the error message
+/// to stderr, and call exit(1). If an error handler is installed then it is
+/// the handler's responsibility to log the message, it will no longer be
+/// printed to stderr. If the error handler returns, then exit(1) will be
+/// called.
+///
+///
+/// \param user_data - An argument which will be passed to the installed error
+/// handler.
+RCC_ABI void
+install_bad_alloc_error_handler (fatal_error_handler_t handler,
+ void *user_data = nullptr);
+
+/// Restores default bad alloc error handling behavior.
+RCC_ABI void
+remove_bad_alloc_error_handler ();
+
+RCC_ABI void
+install_out_of_memory_new_handler ();
+
+/// Reports a bad alloc error, calling any user defined bad alloc
+/// error handler. In contrast to the generic 'report_fatal_error'
+/// functions, this function might not terminate, e.g. the user
+/// defined error handler throws an exception, but it won't return.
+///
+/// Note: When throwing an exception in the bad alloc handler, make sure that
+/// the following unwind succeeds, e.g. do not trigger additional allocations
+/// in the unwind chain.
+///
+/// If no error handler is installed (default), throws a bad_alloc exception
+/// if LLVM is compiled with exception support. Otherwise prints the error
+/// to standard error and calls abort().
+[[noreturn]] RCC_ABI void
+report_bad_alloc_error (const char *Reason, bool GenCrashDiag = true);
+
+/// This function calls abort(), and prints the optional message to stderr.
+/// Use the llvm_unreachable macro (that adds location info), instead of
+/// calling this function directly.
+[[noreturn]] RCC_ABI void
+rcc_unreachable_internal (const char *msg = nullptr, const char *file = nullptr,
+ unsigned line = 0);
+} // namespace rcc
+
+/// Marks that the current location is not supposed to be reachable.
+/// In !NDEBUG builds, prints the message and location info to stderr.
+/// In NDEBUG builds, if the platform does not support a builtin unreachable
+/// then we call an internal LLVM runtime function. Otherwise the behavior is
+/// controlled by the CMake flag
+/// -DLLVM_UNREACHABLE_OPTIMIZE
+/// * When "ON" (default) llvm_unreachable() becomes an optimizer hint
+/// that the current location is not supposed to be reachable: the hint
+/// turns such code path into undefined behavior. On compilers that don't
+/// support such hints, prints a reduced message instead and aborts the
+/// program.
+/// * When "OFF", a builtin_trap is emitted instead of an
+// optimizer hint or printing a reduced message.
+///
+/// Use this instead of assert(0). It conveys intent more clearly, suppresses
+/// diagnostics for unreachable code paths, and allows compilers to omit
+/// unnecessary code.
+#ifndef NDEBUG
+#define rcc_unreachable(msg) \
+ ::rcc::rcc_unreachable_internal (msg, __FILE__, __LINE__)
+#elif !defined(RCC_BUILTIN_UNREACHABLE)
+#define rcc_unreachable(msg) ::rcc::rcc_unreachable_internal ()
+#elif RCC_UNREACHABLE_OPTIMIZE
+#define rcc_unreachable(msg) RCC_BUILTIN_UNREACHABLE
+#else
+#define rcc_unreachable(msg) \
+ do \
+ { \
+ RCC_BUILTIN_TRAP; \
+ RCC_BUILTIN_UNREACHABLE; \
+ } while (false)
+#endif
+
+#endif
diff --git a/libsupport/include/CoreLib/Error/ErrorOr.h b/libsupport/include/CoreLib/Error/ErrorOr.h
new file mode 100644
index 0000000..0e17822
--- /dev/null
+++ b/libsupport/include/CoreLib/Error/ErrorOr.h
@@ -0,0 +1,378 @@
+/*
+ RCC-Project
+
+ Copyright (C) 2026 Richard Qin
+
+ This file is part of RCC-Project.
+
+ RCC-Project is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option) any
+ later version.
+
+ RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ RCC-Project; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>.
+*/
+
+//===- llvm/Support/ErrorOr.h - Error Smart Pointer -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Provides ErrorOr<T> smart pointer.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef RCC_SUPPORT_ERROROR_H
+#define RCC_SUPPORT_ERROROR_H
+
+#include <cassert>
+#include <functional> // for std::reference_wrapper
+#include <system_error>
+#include <type_traits>
+#include <utility>
+
+namespace rcc
+{
+
+/// Represents either an error or a value T.
+///
+/// ErrorOr<T> is a pointer-like class that represents the result of an
+/// operation. The result is either an error, or a value of type T. This is
+/// designed to emulate the usage of returning a pointer where nullptr indicates
+/// failure. However instead of just knowing that the operation failed, we also
+/// have an error_code that describes why it failed.
+///
+/// It is used like the following.
+/// \code
+/// ErrorOr<Buffer> getBuffer();
+///
+/// auto buffer = getBuffer();
+/// if (error_code ec = buffer.getError())
+/// return ec;
+/// buffer->write("adena");
+/// \endcode
+///
+///
+/// Implicit conversion to bool returns true if there is a usable value. The
+/// unary * and -> operators provide pointer like access to the value. Accessing
+/// the value when there is an error has undefined behavior.
+///
+/// When T is a reference type the behavior is slightly different. The reference
+/// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and
+/// there is special handling to make operator -> work as if T was not a
+/// reference.
+///
+/// T cannot be a rvalue reference.
+template <class T> class ErrorOr
+{
+ template <class OtherT> friend class ErrorOr;
+
+ static constexpr bool isRef = std::is_reference_v<T>;
+
+ using wrap = std::reference_wrapper<std::remove_reference_t<T>>;
+
+public:
+ using storage_type = std::conditional_t<isRef, wrap, T>;
+
+private:
+ using reference = std::remove_reference_t<T> &;
+ using const_reference = const std::remove_reference_t<T> &;
+ using pointer = std::remove_reference_t<T> *;
+ using const_pointer = const std::remove_reference_t<T> *;
+
+public:
+ template <class E>
+ ErrorOr (E ErrorCode,
+ std::enable_if_t<std::is_error_code_enum<E>::value ||
+ std::is_error_condition_enum<E>::value,
+ void *> = nullptr)
+ : HasError (true)
+ {
+ new (getErrorStorage ()) std::error_code (make_error_code (ErrorCode));
+ }
+
+ ErrorOr (std::error_code EC) : HasError (true)
+ {
+ new (getErrorStorage ()) std::error_code (EC);
+ }
+
+ template <class OtherT>
+ ErrorOr (OtherT &&Val,
+ std::enable_if_t<std::is_convertible_v<OtherT, T>> * = nullptr)
+ : HasError (false)
+ {
+ new (getStorage ()) storage_type (std::forward<OtherT> (Val));
+ }
+
+ ErrorOr (const ErrorOr &Other)
+ {
+ copyConstruct (Other);
+ }
+
+ template <class OtherT>
+ ErrorOr (const ErrorOr<OtherT> &Other,
+ std::enable_if_t<std::is_convertible_v<OtherT, T>> * = nullptr)
+ {
+ copyConstruct (Other);
+ }
+
+ template <class OtherT>
+ explicit ErrorOr (
+ const ErrorOr<OtherT> &Other,
+ std::enable_if_t<!std::is_convertible_v<OtherT, const T &>> * = nullptr)
+ {
+ copyConstruct (Other);
+ }
+
+ ErrorOr (ErrorOr &&Other)
+ {
+ moveConstruct (std::move (Other));
+ }
+
+ template <class OtherT>
+ ErrorOr (ErrorOr<OtherT> &&Other,
+ std::enable_if_t<std::is_convertible_v<OtherT, T>> * = nullptr)
+ {
+ moveConstruct (std::move (Other));
+ }
+
+ // This might eventually need SFINAE but it's more complex than is_convertible
+ // & I'm too lazy to write it right now.
+ template <class OtherT>
+ explicit ErrorOr (
+ ErrorOr<OtherT> &&Other,
+ std::enable_if_t<!std::is_convertible_v<OtherT, T>> * = nullptr)
+ {
+ moveConstruct (std::move (Other));
+ }
+
+ ErrorOr &
+ operator= (const ErrorOr &Other)
+ {
+ copyAssign (Other);
+ return *this;
+ }
+
+ ErrorOr &
+ operator= (ErrorOr &&Other)
+ {
+ moveAssign (std::move (Other));
+ return *this;
+ }
+
+ ~ErrorOr ()
+ {
+ if (!HasError)
+ {
+ getStorage ()->~storage_type ();
+ }
+ }
+
+ /// Return false if there is an error.
+ explicit
+ operator bool () const
+ {
+ return !HasError;
+ }
+
+ reference
+ get ()
+ {
+ return *getStorage ();
+ }
+ const_reference
+ get () const
+ {
+ return const_cast<ErrorOr<T> *> (this)->get ();
+ }
+
+ std::error_code
+ getError () const
+ {
+ return HasError ? *getErrorStorage () : std::error_code ();
+ }
+
+ pointer
+ operator->()
+ {
+ return toPointer (getStorage ());
+ }
+
+ const_pointer
+ operator->() const
+ {
+ return toPointer (getStorage ());
+ }
+
+ reference
+ operator* ()
+ {
+ return *getStorage ();
+ }
+
+ const_reference
+ operator* () const
+ {
+ return *getStorage ();
+ }
+
+private:
+ template <class OtherT>
+ void
+ copyConstruct (const ErrorOr<OtherT> &Other)
+ {
+ if (!Other.HasError)
+ {
+ // Get the other value.
+ HasError = false;
+ new (getStorage ()) storage_type (*Other.getStorage ());
+ }
+ else
+ {
+ // Get other's error.
+ HasError = true;
+ new (getErrorStorage ()) std::error_code (Other.getError ());
+ }
+ }
+
+ template <class T1>
+ static bool
+ compareThisIfSameType (const T1 &a, const T1 &b)
+ {
+ return &a == &b;
+ }
+
+ template <class T1, class T2>
+ static bool
+ compareThisIfSameType (const T1 &, const T2 &)
+ {
+ return false;
+ }
+
+ template <class OtherT>
+ void
+ copyAssign (const ErrorOr<OtherT> &Other)
+ {
+ if (compareThisIfSameType (*this, Other))
+ {
+ return;
+ }
+
+ this->~ErrorOr ();
+ new (this) ErrorOr (Other);
+ }
+
+ template <class OtherT>
+ void
+ moveConstruct (ErrorOr<OtherT> &&Other)
+ {
+ if (!Other.HasError)
+ {
+ // Get the other value.
+ HasError = false;
+ new (getStorage ()) storage_type (std::move (*Other.getStorage ()));
+ }
+ else
+ {
+ // Get other's error.
+ HasError = true;
+ new (getErrorStorage ()) std::error_code (Other.getError ());
+ }
+ }
+
+ template <class OtherT>
+ void
+ moveAssign (ErrorOr<OtherT> &&Other)
+ {
+ if (compareThisIfSameType (*this, Other))
+ {
+ return;
+ }
+
+ this->~ErrorOr ();
+ new (this) ErrorOr (std::move (Other));
+ }
+
+ pointer
+ toPointer (pointer Val)
+ {
+ return Val;
+ }
+
+ const_pointer
+ toPointer (const_pointer Val) const
+ {
+ return Val;
+ }
+
+ pointer
+ toPointer (wrap *Val)
+ {
+ return &Val->get ();
+ }
+
+ const_pointer
+ toPointer (const wrap *Val) const
+ {
+ return &Val->get ();
+ }
+
+ storage_type *
+ getStorage ()
+ {
+ assert (!HasError && "Cannot get value when an error exists!");
+ return &TStorage;
+ }
+
+ const storage_type *
+ getStorage () const
+ {
+ assert (!HasError && "Cannot get value when an error exists!");
+ return &TStorage;
+ }
+
+ std::error_code *
+ getErrorStorage ()
+ {
+ assert (HasError && "Cannot get error when a value exists!");
+ return &ErrorStorage;
+ }
+
+ const std::error_code *
+ getErrorStorage () const
+ {
+ assert (HasError && "Cannot get error when a value exists!");
+ return &ErrorStorage;
+ }
+
+ union
+ {
+ storage_type TStorage;
+ std::error_code ErrorStorage;
+ };
+ bool HasError : 1;
+};
+
+template <class T, class E>
+std::enable_if_t<std::is_error_code_enum<E>::value ||
+ std::is_error_condition_enum<E>::value,
+ bool>
+operator== (const ErrorOr<T> &Err, E Code)
+{
+ return Err.getError () == Code;
+}
+
+} // end namespace rcc
+
+#endif // RCC_SUPPORT_ERROROR_H
diff --git a/libsupport/include/CoreLib/Math/MathExtras.h b/libsupport/include/CoreLib/Math/MathExtras.h
new file mode 100644
index 0000000..a9c954d
--- /dev/null
+++ b/libsupport/include/CoreLib/Math/MathExtras.h
@@ -0,0 +1,1050 @@
+/*
+ RCC-Project
+
+ Copyright (C) 2026 Richard Qin
+
+ This file is part of RCC-Project.
+
+ RCC-Project is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option) any
+ later version.
+
+ RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ RCC-Project; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>.
+*/
+
+//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains some functions that are useful for math stuff.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef RCC_SUPPORT_MATHEXTRAS_H
+#define RCC_SUPPORT_MATHEXTRAS_H
+
+#include "CoreLib/Compiler/Compiler.h"
+#include <bit>
+#include <cassert>
+#include <climits>
+#include <cstdint>
+#include <cstring>
+#include <limits>
+#include <numbers>
+#include <type_traits>
+#include <utility>
+
+namespace rcc
+{
+/// Some template parameter helpers to optimize for bitwidth, for functions that
+/// take multiple arguments.
+
+// We can't verify signedness, since callers rely on implicit coercions to
+// signed/unsigned.
+template <typename T, typename U>
+using enableif_int =
+ std::enable_if_t<std::is_integral_v<T> && std::is_integral_v<U>>;
+
+// Use std::common_type_t to widen only up to the widest argument.
+template <typename T, typename U, typename = enableif_int<T, U>>
+using common_uint =
+ std::common_type_t<std::make_unsigned_t<T>, std::make_unsigned_t<U>>;
+template <typename T, typename U, typename = enableif_int<T, U>>
+using common_sint =
+ std::common_type_t<std::make_signed_t<T>, std::make_signed_t<U>>;
+
+/// Mathematical constants.
+namespace numbers
+{
+// clang-format off
+inline constexpr float ef = std::numbers::e_v<float>;
+inline constexpr float egammaf = std::numbers::egamma_v<float>;
+inline constexpr float ln2f = std::numbers::ln2_v<float>;
+inline constexpr float ln10f = std::numbers::ln10_v<float>;
+inline constexpr float log2ef = std::numbers::log2e_v<float>;
+inline constexpr float log10ef = std::numbers::log10e_v<float>;
+inline constexpr float pif = std::numbers::pi_v<float>;
+inline constexpr float inv_pif = std::numbers::inv_pi_v<float>;
+inline constexpr float inv_sqrtpif = std::numbers::inv_sqrtpi_v<float>;
+inline constexpr float sqrt2f = std::numbers::sqrt2_v<float>;
+inline constexpr float inv_sqrt2f = 1.0f / std::numbers::sqrt2_v<float>;
+inline constexpr float sqrt3f = std::numbers::sqrt3_v<float>;
+inline constexpr float inv_sqrt3f = std::numbers::inv_sqrt3_v<float>;
+inline constexpr float phif = std::numbers::phi_v<float>;
+
+// sqrtpi is not in C++20 std::numbers.
+template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
+inline constexpr T sqrtpi_v = T(0x1.c5bf891b4ef6bP+0); // (1.7724538509055160273) https://oeis.org/A002161
+inline constexpr double sqrtpi = sqrtpi_v<double>;
+inline constexpr float sqrtpif = sqrtpi_v<float>;
+
+// These string literals are taken from below:
+// https://github.com/bminor/glibc/blob/8543577b04ded6d979ffcc5a818930e4d74d0645/math/math.h#L1215-L1229
+constexpr const char *pis = "3.141592653589793238462643383279502884",
+ *inv_pis = "0.318309886183790671537767526745028724";
+// clang-format on
+} // namespace numbers
+
+/// Create a bitmask with the N right-most bits set to 1, and all other
+/// bits set to 0. Only unsigned types are allowed.
+template <typename T>
+constexpr T
+maskTrailingOnes (unsigned N)
+{
+ static_assert (std::is_unsigned_v<T>, "Invalid type!");
+ const unsigned Bits = CHAR_BIT * sizeof (T);
+ assert (N <= Bits && "Invalid bit index");
+ if (N == 0)
+ {
+ return 0;
+ }
+ return T (-1) >> (Bits - N);
+}
+
+/// Create a bitmask with the N left-most bits set to 1, and all other
+/// bits set to 0. Only unsigned types are allowed.
+template <typename T>
+constexpr T
+maskLeadingOnes (unsigned N)
+{
+ return ~maskTrailingOnes<T> (CHAR_BIT * sizeof (T) - N);
+}
+
+/// Create a bitmask with the N right-most bits set to 0, and all other
+/// bits set to 1. Only unsigned types are allowed.
+template <typename T>
+constexpr T
+maskTrailingZeros (unsigned N)
+{
+ return maskLeadingOnes<T> (CHAR_BIT * sizeof (T) - N);
+}
+
+/// Create a bitmask with the N left-most bits set to 0, and all other
+/// bits set to 1. Only unsigned types are allowed.
+template <typename T>
+constexpr T
+maskLeadingZeros (unsigned N)
+{
+ return maskTrailingOnes<T> (CHAR_BIT * sizeof (T) - N);
+}
+
+/// Macro compressed bit reversal table for 256 bits.
+///
+/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable
+static const unsigned char BitReverseTable256[256] = {
+#define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64
+#define R4(n) R2 (n), R2 (n + 2 * 16), R2 (n + 1 * 16), R2 (n + 3 * 16)
+#define R6(n) R4 (n), R4 (n + 2 * 4), R4 (n + 1 * 4), R4 (n + 3 * 4)
+ R6 (0), R6 (2), R6 (1), R6 (3)
+#undef R2
+#undef R4
+#undef R6
+};
+
+/// Reverse the bits in \p Val.
+template <typename T>
+constexpr T
+reverseBits (T Val)
+{
+#if __has_builtin(__builtin_bitreverse8)
+ if constexpr (std::is_same_v<T, uint8_t>)
+ {
+ return __builtin_bitreverse8 (Val);
+ }
+#endif
+#if __has_builtin(__builtin_bitreverse16)
+ if constexpr (std::is_same_v<T, uint16_t>)
+ {
+ return __builtin_bitreverse16 (Val);
+ }
+#endif
+#if __has_builtin(__builtin_bitreverse32)
+ if constexpr (std::is_same_v<T, uint32_t>)
+ {
+ return __builtin_bitreverse32 (Val);
+ }
+#endif
+#if __has_builtin(__builtin_bitreverse64)
+ if constexpr (std::is_same_v<T, uint64_t>)
+ {
+ return __builtin_bitreverse64 (Val);
+ }
+#endif
+
+ unsigned char in[sizeof (Val)];
+ unsigned char out[sizeof (Val)];
+ std::memcpy (in, &Val, sizeof (Val));
+ for (unsigned i = 0; i < sizeof (Val); ++i)
+ {
+ out[(sizeof (Val) - i) - 1] = BitReverseTable256[in[i]];
+ }
+ std::memcpy (&Val, out, sizeof (Val));
+ return Val;
+}
+
+// NOTE: The following support functions use the _32/_64 extensions instead of
+// type overloading so that signed and unsigned integers can be used without
+// ambiguity.
+
+/// Return the high 32 bits of a 64 bit value.
+constexpr uint32_t
+Hi_32 (uint64_t Value)
+{
+ return static_cast<uint32_t> (Value >> 32);
+}
+
+/// Return the low 32 bits of a 64 bit value.
+constexpr uint32_t
+Lo_32 (uint64_t Value)
+{
+ return static_cast<uint32_t> (Value);
+}
+
+/// Make a 64-bit integer from a high / low pair of 32-bit integers.
+constexpr uint64_t
+Make_64 (uint32_t High, uint32_t Low)
+{
+ return ((uint64_t)High << 32) | (uint64_t)Low;
+}
+
+/// Checks if an integer fits into the given bit width.
+template <unsigned N>
+constexpr bool
+isInt (int64_t x)
+{
+ if constexpr (N == 0)
+ {
+ return 0 == x;
+ }
+ if constexpr (N == 8)
+ {
+ return static_cast<int8_t> (x) == x;
+ }
+ if constexpr (N == 16)
+ {
+ return static_cast<int16_t> (x) == x;
+ }
+ if constexpr (N == 32)
+ {
+ return static_cast<int32_t> (x) == x;
+ }
+ if constexpr (N < 64)
+ {
+ return -(INT64_C (1) << (N - 1)) <= x && x < (INT64_C (1) << (N - 1));
+ }
+ (void)x; // MSVC v19.25 warns that x is unused.
+ return true;
+}
+
+/// Checks if a signed integer is an N bit number shifted left by S.
+template <unsigned N, unsigned S>
+constexpr bool
+isShiftedInt (int64_t x)
+{
+ static_assert (S < 64, "isShiftedInt<N, S> with S >= 64 is too much.");
+ static_assert (N + S <= 64,
+ "isShiftedInt<N, S> with N + S > 64 is too wide.");
+ return isInt<N + S> (x) && (x % (UINT64_C (1) << S) == 0);
+}
+
+/// Checks if an unsigned integer fits into the given bit width.
+template <unsigned N>
+constexpr bool
+isUInt (uint64_t x)
+{
+ if constexpr (N < 64)
+ {
+ return (x >> N) == 0;
+ }
+ (void)x; // MSVC v19.25 warns that x is unused.
+ return true;
+}
+
+/// Checks if a unsigned integer is an N bit number shifted left by S.
+template <unsigned N, unsigned S>
+constexpr bool
+isShiftedUInt (uint64_t x)
+{
+ static_assert (S < 64, "isShiftedUInt<N, S> with S >= 64 is too much.");
+ static_assert (N + S <= 64,
+ "isShiftedUInt<N, S> with N + S > 64 is too wide.");
+ // S must be strictly less than 64. So 1 << S is not undefined behavior.
+ return isUInt<N + S> (x) && (x % (UINT64_C (1) << S) == 0);
+}
+
+/// Gets the maximum value for a N-bit unsigned integer.
+inline constexpr uint64_t
+maxUIntN (uint64_t N)
+{
+ assert (N <= 64 && "integer width out of range");
+
+ // uint64_t(1) << 64 is undefined behavior, so we can't do
+ // (uint64_t(1) << N) - 1
+ // without checking first that N != 64. But this works and doesn't have a
+ // branch for N != 0.
+ // Unfortunately, shifting a uint64_t right by 64 bit is undefined
+ // behavior, so the condition on N == 0 is necessary. Fortunately, most
+ // optimizers do not emit branches for this check.
+ if (N == 0)
+ {
+ return 0;
+ }
+ return UINT64_MAX >> (64 - N);
+}
+
+/// Gets the minimum value for a N-bit signed integer.
+inline constexpr int64_t
+minIntN (int64_t N)
+{
+ assert (N <= 64 && "integer width out of range");
+
+ if (N == 0)
+ {
+ return 0;
+ }
+ return UINT64_MAX << (N - 1);
+}
+
+/// Gets the maximum value for a N-bit signed integer.
+inline constexpr int64_t
+maxIntN (int64_t N)
+{
+ assert (N <= 64 && "integer width out of range");
+
+ // This relies on two's complement wraparound when N == 64, so we convert to
+ // int64_t only at the very end to avoid UB.
+ if (N == 0)
+ {
+ return 0;
+ }
+ return (UINT64_C (1) << (N - 1)) - 1;
+}
+
+/// Checks if an unsigned integer fits into the given (dynamic) bit width.
+inline constexpr bool
+isUIntN (unsigned N, uint64_t x)
+{
+ return N >= 64 || (x >> N) == 0;
+}
+
+/// Checks if an signed integer fits into the given (dynamic) bit width.
+inline constexpr bool
+isIntN (unsigned N, int64_t x)
+{
+ return N >= 64 || (minIntN (N) <= x && x <= maxIntN (N));
+}
+
+/// Return true if the argument is a non-empty sequence of ones starting at the
+/// least significant bit with the remainder zero (32 bit version).
+/// Ex. isMask_32(0x0000FFFFU) == true.
+constexpr bool
+isMask_32 (uint32_t Value)
+{
+ return Value && ((Value + 1) & Value) == 0;
+}
+
+/// Return true if the argument is a non-empty sequence of ones starting at the
+/// least significant bit with the remainder zero (64 bit version).
+constexpr bool
+isMask_64 (uint64_t Value)
+{
+ return Value && ((Value + 1) & Value) == 0;
+}
+
+/// Return true if the argument contains a non-empty sequence of ones with the
+/// remainder zero (32 bit version.) Ex. isShiftedMask_32(0x0000FF00U) == true.
+constexpr bool
+isShiftedMask_32 (uint32_t Value)
+{
+ return Value && isMask_32 ((Value - 1) | Value);
+}
+
+/// Return true if the argument contains a non-empty sequence of ones with the
+/// remainder zero (64 bit version.)
+constexpr bool
+isShiftedMask_64 (uint64_t Value)
+{
+ return Value && isMask_64 ((Value - 1) | Value);
+}
+
+/// Return true if the argument is a power of two > 0.
+/// Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.)
+constexpr bool
+isPowerOf2_32 (uint32_t Value)
+{
+ return std::has_single_bit (Value);
+}
+
+/// Return true if the argument is a power of two > 0 (64 bit edition.)
+constexpr bool
+isPowerOf2_64 (uint64_t Value)
+{
+ return std::has_single_bit (Value);
+}
+
+/// Return true if the argument contains a non-empty sequence of ones with the
+/// remainder zero (32 bit version.) Ex. isShiftedMask_32(0x0000FF00U) == true.
+/// If true, \p MaskIdx will specify the index of the lowest set bit and \p
+/// MaskLen is updated to specify the length of the mask, else neither are
+/// updated.
+inline bool
+isShiftedMask_32 (uint32_t Value, unsigned &MaskIdx, unsigned &MaskLen)
+{
+ if (!isShiftedMask_32 (Value))
+ {
+ return false;
+ }
+ MaskIdx = std::countr_zero (Value);
+ MaskLen = std::popcount (Value);
+ return true;
+}
+
+/// Return true if the argument contains a non-empty sequence of ones with the
+/// remainder zero (64 bit version.) If true, \p MaskIdx will specify the index
+/// of the lowest set bit and \p MaskLen is updated to specify the length of the
+/// mask, else neither are updated.
+inline bool
+isShiftedMask_64 (uint64_t Value, unsigned &MaskIdx, unsigned &MaskLen)
+{
+ if (!isShiftedMask_64 (Value))
+ {
+ return false;
+ }
+ MaskIdx = std::countr_zero (Value);
+ MaskLen = std::popcount (Value);
+ return true;
+}
+
+/// Compile time Log2.
+/// Valid only for positive powers of two.
+template <size_t kValue>
+constexpr size_t
+ConstantLog2 ()
+{
+ static_assert (rcc::isPowerOf2_64 (kValue),
+ "Value is not a valid power of 2");
+ return std::countr_zero (kValue);
+}
+
+/// Return the floor log base 2 of the specified value, -1 if the value is zero.
+/// (32 bit edition.)
+/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2
+inline unsigned
+Log2_32 (uint32_t Value)
+{
+ return 31 - std::countl_zero (Value);
+}
+
+/// Return the floor log base 2 of the specified value, -1 if the value is zero.
+/// (64 bit edition.)
+inline unsigned
+Log2_64 (uint64_t Value)
+{
+ return 63 - std::countl_zero (Value);
+}
+
+/// Return the ceil log base 2 of the specified value, 32 if the value is zero.
+/// (32 bit edition).
+/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3
+inline unsigned
+Log2_32_Ceil (uint32_t Value)
+{
+ return 32 - std::countl_zero (Value - 1);
+}
+
+/// Return the ceil log base 2 of the specified value, 64 if the value is zero.
+/// (64 bit edition.)
+inline unsigned
+Log2_64_Ceil (uint64_t Value)
+{
+ return 64 - std::countl_zero (Value - 1);
+}
+
+/// A and B are either alignments or offsets. Return the minimum alignment that
+/// may be assumed after adding the two together.
+template <typename U, typename V, typename T = common_uint<U, V>>
+constexpr T
+MinAlign (U A, V B)
+{
+ // The largest power of 2 that divides both A and B.
+ //
+ // Replace "-Value" by "1+~Value" in the following commented code to avoid
+ // MSVC warning C4146
+ // return (A | B) & -(A | B);
+ return (A | B) & (1 + ~(A | B));
+}
+
+/// Fallback when arguments aren't integral.
+constexpr uint64_t
+MinAlign (uint64_t A, uint64_t B)
+{
+ return (A | B) & (1 + ~(A | B));
+}
+
+/// Returns the next power of two (in 64-bits) that is strictly greater than A.
+/// Returns zero on overflow.
+constexpr uint64_t
+NextPowerOf2 (uint64_t A)
+{
+ A |= (A >> 1);
+ A |= (A >> 2);
+ A |= (A >> 4);
+ A |= (A >> 8);
+ A |= (A >> 16);
+ A |= (A >> 32);
+ return A + 1;
+}
+
+/// Returns the power of two which is greater than or equal to the given value.
+/// Essentially, it is a ceil operation across the domain of powers of two.
+inline uint64_t
+PowerOf2Ceil (uint64_t A)
+{
+ if (!A || A > UINT64_MAX / 2)
+ {
+ return 0;
+ }
+ return UINT64_C (1) << Log2_64_Ceil (A);
+}
+
+/// Returns the integer ceil(Numerator / Denominator). Unsigned version.
+/// Guaranteed to never overflow.
+template <typename U, typename V, typename T = common_uint<U, V>>
+constexpr T
+divideCeil (U Numerator, V Denominator)
+{
+ assert (Denominator && "Division by zero");
+ T Bias = (Numerator != 0);
+ return (Numerator - Bias) / Denominator + Bias;
+}
+
+/// Fallback when arguments aren't integral.
+constexpr uint64_t
+divideCeil (uint64_t Numerator, uint64_t Denominator)
+{
+ assert (Denominator && "Division by zero");
+ uint64_t Bias = (Numerator != 0);
+ return (Numerator - Bias) / Denominator + Bias;
+}
+
+// Check whether divideCeilSigned or divideFloorSigned would overflow. This
+// happens only when Numerator = INT_MIN and Denominator = -1.
+template <typename U, typename V>
+constexpr bool
+divideSignedWouldOverflow (U Numerator, V Denominator)
+{
+ return Numerator == std::numeric_limits<U>::min () && Denominator == -1;
+}
+
+/// Returns the integer ceil(Numerator / Denominator). Signed version.
+/// Overflow is explicitly forbidden with an assert.
+template <typename U, typename V, typename T = common_sint<U, V>>
+constexpr T
+divideCeilSigned (U Numerator, V Denominator)
+{
+ assert (Denominator && "Division by zero");
+ assert (!divideSignedWouldOverflow (Numerator, Denominator) &&
+ "Divide would overflow");
+ if (!Numerator)
+ {
+ return 0;
+ }
+ // C's integer division rounds towards 0.
+ T Bias = Denominator >= 0 ? 1 : -1;
+ bool SameSign = (Numerator >= 0) == (Denominator >= 0);
+ return SameSign ? (Numerator - Bias) / Denominator + 1
+ : Numerator / Denominator;
+}
+
+/// Returns the integer floor(Numerator / Denominator). Signed version.
+/// Overflow is explicitly forbidden with an assert.
+template <typename U, typename V, typename T = common_sint<U, V>>
+constexpr T
+divideFloorSigned (U Numerator, V Denominator)
+{
+ assert (Denominator && "Division by zero");
+ assert (!divideSignedWouldOverflow (Numerator, Denominator) &&
+ "Divide would overflow");
+ if (!Numerator)
+ {
+ return 0;
+ }
+ // C's integer division rounds towards 0.
+ T Bias = Denominator >= 0 ? -1 : 1;
+ bool SameSign = (Numerator >= 0) == (Denominator >= 0);
+ return SameSign ? Numerator / Denominator
+ : (Numerator - Bias) / Denominator - 1;
+}
+
+/// Returns the remainder of the Euclidean division of LHS by RHS. Result is
+/// always non-negative.
+template <typename U, typename V, typename T = common_sint<U, V>>
+constexpr T
+mod (U Numerator, V Denominator)
+{
+ assert (Denominator >= 1 && "Mod by non-positive number");
+ T Mod = Numerator % Denominator;
+ return Mod < 0 ? Mod + Denominator : Mod;
+}
+
+/// Returns (Numerator / Denominator) rounded by round-half-up. Guaranteed to
+/// never overflow.
+template <typename U, typename V, typename T = common_uint<U, V>>
+constexpr T
+divideNearest (U Numerator, V Denominator)
+{
+ assert (Denominator && "Division by zero");
+ T Mod = Numerator % Denominator;
+ return (Numerator / Denominator) +
+ (Mod > (static_cast<T> (Denominator) - 1) / 2);
+}
+
+/// Returns the next integer (mod 2**nbits) that is greater than or equal to
+/// \p Value and is a multiple of \p Align. \p Align must be non-zero.
+///
+/// Examples:
+/// \code
+/// alignTo(5, 8) = 8
+/// alignTo(17, 8) = 24
+/// alignTo(~0LL, 8) = 0
+/// alignTo(321, 255) = 510
+/// \endcode
+///
+/// Will overflow only if result is not representable in T.
+template <typename U, typename V, typename T = common_uint<U, V>>
+constexpr T
+alignTo (U Value, V Align)
+{
+ assert (Align != 0u && "Align can't be 0.");
+ T CeilDiv = divideCeil (Value, Align);
+ return CeilDiv * Align;
+}
+
+/// Fallback when arguments aren't integral.
+constexpr uint64_t
+alignTo (uint64_t Value, uint64_t Align)
+{
+ assert (Align != 0u && "Align can't be 0.");
+ uint64_t CeilDiv = divideCeil (Value, Align);
+ return CeilDiv * Align;
+}
+
+/// Will overflow only if result is not representable in T.
+template <typename U, typename V, typename T = common_uint<U, V>>
+constexpr T
+alignToPowerOf2 (U Value, V Align)
+{
+ assert (Align != 0 && (Align & (Align - 1)) == 0 &&
+ "Align must be a power of 2");
+ T NegAlign = static_cast<T> (0) - Align;
+ return (Value + (Align - 1)) & NegAlign;
+}
+
+/// Fallback when arguments aren't integral.
+constexpr uint64_t
+alignToPowerOf2 (uint64_t Value, uint64_t Align)
+{
+ assert (Align != 0 && (Align & (Align - 1)) == 0 &&
+ "Align must be a power of 2");
+ uint64_t NegAlign = 0 - Align;
+ return (Value + (Align - 1)) & NegAlign;
+}
+
+/// If non-zero \p Skew is specified, the return value will be a minimal integer
+/// that is greater than or equal to \p Size and equal to \p A * N + \p Skew for
+/// some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p
+/// Skew mod \p A'. \p Align must be non-zero.
+///
+/// Examples:
+/// \code
+/// alignTo(5, 8, 7) = 7
+/// alignTo(17, 8, 1) = 17
+/// alignTo(~0LL, 8, 3) = 3
+/// alignTo(321, 255, 42) = 552
+/// \endcode
+///
+/// May overflow.
+template <typename U, typename V, typename W,
+ typename T = common_uint<common_uint<U, V>, W>>
+constexpr T
+alignTo (U Value, V Align, W Skew)
+{
+ assert (Align != 0u && "Align can't be 0.");
+ Skew %= Align;
+ return alignTo (Value - Skew, Align) + Skew;
+}
+
+/// Returns the next integer (mod 2**nbits) that is greater than or equal to
+/// \p Value and is a multiple of \c Align. \c Align must be non-zero.
+///
+/// Will overflow only if result is not representable in T.
+template <auto Align, typename V, typename T = common_uint<decltype (Align), V>>
+constexpr T
+alignTo (V Value)
+{
+ static_assert (Align != 0u, "Align must be non-zero");
+ T CeilDiv = divideCeil (Value, Align);
+ return CeilDiv * Align;
+}
+
+/// Returns the largest unsigned integer less than or equal to \p Value and is
+/// \p Skew mod \p Align. \p Align must be non-zero. Guaranteed to never
+/// overflow.
+template <typename U, typename V, typename W = uint8_t,
+ typename T = common_uint<common_uint<U, V>, W>>
+constexpr T
+alignDown (U Value, V Align, W Skew = 0)
+{
+ assert (Align != 0u && "Align can't be 0.");
+ Skew %= Align;
+ return (Value - Skew) / Align * Align + Skew;
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
+/// Requires B <= 32.
+template <unsigned B>
+constexpr int32_t
+SignExtend32 (uint32_t X)
+{
+ static_assert (B <= 32, "Bit width out of range.");
+ if constexpr (B == 0)
+ {
+ return 0;
+ }
+ return int32_t (X << (32 - B)) >> (32 - B);
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
+/// Requires B <= 32.
+inline int32_t
+SignExtend32 (uint32_t X, unsigned B)
+{
+ assert (B <= 32 && "Bit width out of range.");
+ if (B == 0)
+ {
+ return 0;
+ }
+ return int32_t (X << (32 - B)) >> (32 - B);
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
+/// Requires B <= 64.
+template <unsigned B>
+constexpr int64_t
+SignExtend64 (uint64_t x)
+{
+ static_assert (B <= 64, "Bit width out of range.");
+ if constexpr (B == 0)
+ {
+ return 0;
+ }
+ return int64_t (x << (64 - B)) >> (64 - B);
+}
+
+/// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
+/// Requires B <= 64.
+inline int64_t
+SignExtend64 (uint64_t X, unsigned B)
+{
+ assert (B <= 64 && "Bit width out of range.");
+ if (B == 0)
+ {
+ return 0;
+ }
+ return int64_t (X << (64 - B)) >> (64 - B);
+}
+
+/// Return the absolute value of a signed integer, converted to the
+/// corresponding unsigned integer type. Avoids undefined behavior in std::abs
+/// when you pass it INT_MIN or similar.
+template <typename T, typename U = std::make_unsigned_t<T>>
+constexpr U
+AbsoluteValue (T X)
+{
+ // If X is negative, cast it to the unsigned type _before_ negating it.
+ return X < 0 ? -static_cast<U> (X) : X;
+}
+
+/// Subtract two unsigned integers, X and Y, of type T and return the absolute
+/// value of the result.
+template <typename U, typename V, typename T = common_uint<U, V>>
+constexpr T
+AbsoluteDifference (U X, V Y)
+{
+ return X > Y ? (X - Y) : (Y - X);
+}
+
+/// Add two unsigned integers, X and Y, of type T. Clamp the result to the
+/// maximum representable value of T on overflow. ResultOverflowed indicates if
+/// the result is larger than the maximum representable value of type T.
+template <typename T>
+std::enable_if_t<std::is_unsigned_v<T>, T>
+SaturatingAdd (T X, T Y, bool *ResultOverflowed = nullptr)
+{
+ bool Dummy;
+ bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
+ // Hacker's Delight, p. 29
+ T Z = X + Y;
+ Overflowed = (Z < X || Z < Y);
+ if (Overflowed)
+ {
+ return std::numeric_limits<T>::max ();
+ }
+ else
+ {
+ return Z;
+ }
+}
+
+/// Add multiple unsigned integers of type T. Clamp the result to the
+/// maximum representable value of T on overflow.
+template <class T, class... Ts>
+std::enable_if_t<std::is_unsigned_v<T>, T>
+SaturatingAdd (T X, T Y, T Z, Ts... Args)
+{
+ bool Overflowed = false;
+ T XY = SaturatingAdd (X, Y, &Overflowed);
+ if (Overflowed)
+ {
+ return SaturatingAdd (std::numeric_limits<T>::max (), T (1), Args...);
+ }
+ return SaturatingAdd (XY, Z, Args...);
+}
+
+/// Multiply two unsigned integers, X and Y, of type T. Clamp the result to the
+/// maximum representable value of T on overflow. ResultOverflowed indicates if
+/// the result is larger than the maximum representable value of type T.
+template <typename T>
+std::enable_if_t<std::is_unsigned_v<T>, T>
+SaturatingMultiply (T X, T Y, bool *ResultOverflowed = nullptr)
+{
+ bool Dummy;
+ bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
+
+ // Hacker's Delight, p. 30 has a different algorithm, but we don't use that
+ // because it fails for uint16_t (where multiplication can have undefined
+ // behavior due to promotion to int), and requires a division in addition
+ // to the multiplication.
+
+ Overflowed = false;
+
+ // Log2(Z) would be either Log2Z or Log2Z + 1.
+ // Special case: if X or Y is 0, Log2_64 gives -1, and Log2Z
+ // will necessarily be less than Log2Max as desired.
+ int Log2Z = Log2_64 (X) + Log2_64 (Y);
+ const T Max = std::numeric_limits<T>::max ();
+ int Log2Max = Log2_64 (Max);
+ if (Log2Z < Log2Max)
+ {
+ return X * Y;
+ }
+ if (Log2Z > Log2Max)
+ {
+ Overflowed = true;
+ return Max;
+ }
+
+ // We're going to use the top bit, and maybe overflow one
+ // bit past it. Multiply all but the bottom bit then add
+ // that on at the end.
+ T Z = (X >> 1) * Y;
+ if (Z & ~(Max >> 1))
+ {
+ Overflowed = true;
+ return Max;
+ }
+ Z <<= 1;
+ if (X & 1)
+ {
+ return SaturatingAdd (Z, Y, ResultOverflowed);
+ }
+
+ return Z;
+}
+
+/// Multiply two unsigned integers, X and Y, and add the unsigned integer, A to
+/// the product. Clamp the result to the maximum representable value of T on
+/// overflow. ResultOverflowed indicates if the result is larger than the
+/// maximum representable value of type T.
+template <typename T>
+std::enable_if_t<std::is_unsigned_v<T>, T>
+SaturatingMultiplyAdd (T X, T Y, T A, bool *ResultOverflowed = nullptr)
+{
+ bool Dummy;
+ bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
+
+ T Product = SaturatingMultiply (X, Y, &Overflowed);
+ if (Overflowed)
+ {
+ return Product;
+ }
+
+ return SaturatingAdd (A, Product, &Overflowed);
+}
+
+/// Use this rather than HUGE_VALF; the latter causes warnings on MSVC.
+RCC_ABI extern const float huge_valf;
+
+/// Add two signed integers, computing the two's complement truncated result,
+/// returning a pair {result, overflow}, where "overflow" is a boolean value
+/// indicating whether an overflow occurred.
+template <typename T>
+constexpr std::enable_if_t<std::is_signed_v<T>, std::pair<T, bool>>
+AddOverflow (T X, T Y)
+{
+ // Perform the unsigned addition.
+ using U = std::make_unsigned_t<T>;
+ const U UX = static_cast<U> (X);
+ const U UY = static_cast<U> (Y);
+ const U UResult = UX + UY;
+
+ // Convert to signed.
+ auto Result = static_cast<T> (UResult);
+
+ // Adding two positive numbers should result in a positive number.
+ if (X > 0 && Y > 0)
+ {
+ return {Result, Result <= 0};
+ }
+ // Adding two negatives should result in a negative number.
+ if (X < 0 && Y < 0)
+ {
+ return {Result, Result >= 0};
+ }
+ return {Result, false};
+}
+
+/// Add two signed integers, computing the two's complement truncated result,
+/// returning true if overflow occurred.
+template <typename T>
+std::enable_if_t<std::is_signed_v<T>, bool>
+AddOverflow (T X, T Y, T &Result)
+{
+#if __has_builtin(__builtin_add_overflow)
+ return __builtin_add_overflow (X, Y, &Result);
+#else
+ auto [Res, Ovf] = AddOverflow (X, Y);
+ Result = Res;
+ return Ovf;
+#endif
+}
+
+/// Subtract two signed integers, computing the two's complement truncated
+/// result, returning a pair {result, overflow}, where "overflow" is a
+/// boolean value indicating whether an overflow occurred.
+template <typename T>
+constexpr std::enable_if_t<std::is_signed_v<T>, std::pair<T, bool>>
+SubOverflow (T X, T Y)
+{
+ // Perform the unsigned addition.
+ using U = std::make_unsigned_t<T>;
+ const U UX = static_cast<U> (X);
+ const U UY = static_cast<U> (Y);
+ const U UResult = UX - UY;
+
+ // Convert to signed.
+ auto Result = static_cast<T> (UResult);
+
+ // Subtracting a positive number from a negative results in a negative number.
+ if (X <= 0 && Y > 0)
+ {
+ return {Result, Result >= 0};
+ }
+ // Subtracting a negative number from a positive results in a positive number.
+ if (X >= 0 && Y < 0)
+ {
+ return {Result, Result <= 0};
+ }
+ return {Result, false};
+}
+
+/// Subtract two signed integers, computing the two's complement truncated
+/// result, returning true if an overflow occurred.
+template <typename T>
+std::enable_if_t<std::is_signed_v<T>, bool>
+SubOverflow (T X, T Y, T &Result)
+{
+#if __has_builtin(__builtin_sub_overflow)
+ return __builtin_sub_overflow (X, Y, &Result);
+#else
+ auto [Res, Ovf] = SubOverflow (X, Y);
+ Result = Res;
+ return Ovf;
+#endif
+}
+
+/// Multiply two signed integers, computing the two's complement truncated
+/// result, returning a pair {result, overflow}, where "overflow" is a
+/// boolean value indicating whether an overflow occurred.
+template <typename T>
+constexpr std::enable_if_t<std::is_signed_v<T>, std::pair<T, bool>>
+MulOverflow (T X, T Y)
+{
+ // Perform the unsigned multiplication on absolute values.
+ using U = std::make_unsigned_t<T>;
+ const U UX = X < 0 ? (0 - static_cast<U> (X)) : static_cast<U> (X);
+ const U UY = Y < 0 ? (0 - static_cast<U> (Y)) : static_cast<U> (Y);
+ const U UResult = UX * UY;
+
+ // Convert to signed.
+ const bool IsNegative = (X < 0) ^ (Y < 0);
+ auto Result = IsNegative ? (0 - UResult) : UResult;
+
+ // If any of the args was 0, result is 0 and no overflow occurs.
+ if (UX == 0 || UY == 0)
+ {
+ return {Result, false};
+ }
+
+ // UX and UY are in [1, 2^n], where n is the number of digits.
+ // Check how the max allowed absolute value (2^n for negative, 2^(n-1) for
+ // positive) divided by an argument compares to the other.
+ bool Overflow =
+ IsNegative
+ ? UX > (static_cast<U> (std::numeric_limits<T>::max ()) + U (1)) / UY
+ : UX > (static_cast<U> (std::numeric_limits<T>::max ())) / UY;
+
+ return {Result, Overflow};
+}
+
+/// Multiply two signed integers, computing the two's complement truncated
+/// result, returning true if an overflow occurred.
+template <typename T>
+std::enable_if_t<std::is_signed_v<T>, bool>
+MulOverflow (T X, T Y, T &Result)
+{
+#if __has_builtin(__builtin_mul_overflow)
+ return __builtin_mul_overflow (X, Y, &Result);
+#else
+ auto [Res, Ovf] = MulOverflow (X, Y);
+ Result = Res;
+ return Ovf;
+#endif
+}
+
+/// Type to force float point values onto the stack, so that x86 doesn't add
+/// hidden precision, avoiding rounding differences on various platforms.
+#if defined(__i386__) || defined(_M_IX86)
+using stack_float_t = volatile float;
+#else
+using stack_float_t = float;
+#endif
+
+/// Returns the number of digits in the given integer.
+RCC_ABI int
+NumDigitsBase10 (uint64_t X);
+
+} // namespace rcc
+
+#endif
diff --git a/libsupport/include/CoreLib/Memory/MemAlloc.h b/libsupport/include/CoreLib/Memory/MemAlloc.h
new file mode 100644
index 0000000..b7183c0
--- /dev/null
+++ b/libsupport/include/CoreLib/Memory/MemAlloc.h
@@ -0,0 +1,124 @@
+/*
+ RCC-Project
+
+ Copyright (C) 2026 Richard Qin
+
+ This file is part of RCC-Project.
+
+ RCC-Project is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option) any
+ later version.
+
+ RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ RCC-Project; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>.
+ */
+
+//===- MemAlloc.h - Memory allocation functions -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines counterparts of C library allocation functions defined in
+/// the namespace 'std'. The new allocation functions crash on allocation
+/// failure instead of returning null pointer.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef RCC_SUPPORT_MEMALLOC_H
+#define RCC_SUPPORT_MEMALLOC_H
+
+#include "CoreLib/Compiler/Compiler.h"
+#include "CoreLib/Error/ErrorHandling.h"
+#include <cstdlib>
+
+namespace rcc
+{
+
+RCC_ATTRIBUTE_RETURNS_NONNULL inline void *
+safe_malloc (size_t Sz)
+{
+ void *Result = std::malloc (Sz);
+ if (Result == nullptr)
+ {
+ // It is implementation-defined whether allocation occurs if the space
+ // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+ // non-zero, if the space requested was zero.
+ if (Sz == 0)
+ {
+ return safe_malloc (1);
+ }
+ report_bad_alloc_error ("Allocation failed");
+ }
+ return Result;
+}
+
+RCC_ATTRIBUTE_RETURNS_NONNULL inline void *
+safe_calloc (size_t Count, size_t Sz)
+{
+ void *Result = std::calloc (Count, Sz);
+ if (Result == nullptr)
+ {
+ // It is implementation-defined whether allocation occurs if the space
+ // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+ // non-zero, if the space requested was zero.
+ if (Count == 0 || Sz == 0)
+ {
+ return safe_malloc (1);
+ }
+ report_bad_alloc_error ("Allocation failed");
+ }
+ return Result;
+}
+
+RCC_ATTRIBUTE_RETURNS_NONNULL inline void *
+safe_realloc (void *Ptr, size_t Sz)
+{
+ void *Result = std::realloc (Ptr, Sz);
+ if (Result == nullptr)
+ {
+ // It is implementation-defined whether allocation occurs if the space
+ // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+ // non-zero, if the space requested was zero.
+ if (Sz == 0)
+ {
+ return safe_malloc (1);
+ }
+ report_bad_alloc_error ("Allocation failed");
+ }
+ return Result;
+}
+
+/// Allocate a buffer of memory with the given size and alignment.
+///
+/// When the compiler supports aligned operator new, this will use it to
+/// handle even over-aligned allocations.
+///
+/// However, this doesn't make any attempt to leverage the fancier techniques
+/// like posix_memalign due to portability. It is mostly intended to allow
+/// compatibility with platforms that, after aligned allocation was added, use
+/// reduced default alignment.
+RCC_ABI RCC_ATTRIBUTE_RETURNS_NONNULL RCC_ATTRIBUTE_RETURNS_NOALIAS void *
+allocate_buffer (size_t Size, size_t Alignment);
+
+/// Deallocate a buffer of memory with the given size and alignment.
+///
+/// If supported, this will used the sized delete operator. Also if supported,
+/// this will pass the alignment to the delete operator.
+///
+/// The pointer must have been allocated with the corresponding new operator,
+/// most likely using the above helper.
+RCC_ABI void
+deallocate_buffer (void *Ptr, size_t Size, size_t Alignment);
+
+} // namespace rcc
+#endif
diff --git a/libsupport/include/CoreLib/System/Errno.h b/libsupport/include/CoreLib/System/Errno.h
new file mode 100644
index 0000000..2626ad9
--- /dev/null
+++ b/libsupport/include/CoreLib/System/Errno.h
@@ -0,0 +1,64 @@
+/*
+ RCC-Project
+
+ Copyright (C) 2026 Richard Qin
+
+ This file is part of RCC-Project.
+
+ RCC-Project is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option) any
+ later version.
+
+ RCC-Project is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ RCC-Project; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>.
+*/
+
+// This implementation is based on llvm/include/llvm/Support/Errno.h.
+
+#ifndef RCC_SUPPORT_ERRNO_H
+#define RCC_SUPPORT_ERRNO_H
+
+#include "CoreLib/Compiler/Compiler.h"
+
+#include <cerrno>
+#include <string>
+
+namespace rcc
+{
+namespace sys
+{
+
+/// Returns a string representation of the errno value, using whatever
+/// thread-safe variant of strerror() is available. Be sure to call this
+/// immediately after the function that set errno, or errno may have been
+/// overwritten by an intervening call.
+RCC_ABI std::string
+StrError ();
+
+/// Like the no-argument version above, but uses \p errnum instead of errno.
+RCC_ABI std::string
+StrError (int errnum);
+
+template <typename FailT, typename Fun, typename... Args>
+inline decltype (auto)
+RetryAfterSignal (const FailT &Fail, const Fun &F, const Args &...As)
+{
+ decltype (F (As...)) Res;
+ do
+ {
+ errno = 0;
+ Res = F (As...);
+ } while (Res == Fail && errno == EINTR);
+ return Res;
+}
+
+} // namespace sys
+} // namespace rcc
+
+#endif // RCC_SUPPORT_ERRNO_H