[libc-commits] [libc] 5bf8efd - [libc] Fix more inline definitions

Roland McGrath via libc-commits libc-commits at lists.llvm.org
Fri Jun 30 14:46:46 PDT 2023


Author: Roland McGrath
Date: 2023-06-30T14:46:25-07:00
New Revision: 5bf8efd269f8b75b5be40f087f231d71f744885c

URL: https://github.com/llvm/llvm-project/commit/5bf8efd269f8b75b5be40f087f231d71f744885c
DIFF: https://github.com/llvm/llvm-project/commit/5bf8efd269f8b75b5be40f087f231d71f744885c.diff

LOG: [libc] Fix more inline definitions

Fix a bunch more instances of incorrect use of the `static`
keyword and missing use of LIBC_INLINE and LIBC_INLINE_VAR
macros. Note that even forward declarations and generic template
declarations must follow the prescribed patterns for libc code so
that they match every definition, all template specializations.

Reviewed By: Caslyn

Differential Revision: https://reviews.llvm.org/D154260

Added: 
    

Modified: 
    libc/src/__support/CPP/optional.h
    libc/src/__support/CPP/span.h
    libc/src/__support/CPP/string_view.h
    libc/src/__support/CPP/type_traits.h
    libc/src/__support/StringUtil/tables/linux_extension_signals.h
    libc/src/__support/StringUtil/tables/linux_platform_errors.h
    libc/src/__support/StringUtil/tables/linux_platform_signals.h
    libc/src/__support/StringUtil/tables/minimal_platform_errors.h
    libc/src/__support/StringUtil/tables/minimal_platform_signals.h
    libc/src/__support/StringUtil/tables/posix_errors.h
    libc/src/__support/StringUtil/tables/posix_signals.h
    libc/src/__support/StringUtil/tables/signal_table.h
    libc/src/__support/StringUtil/tables/stdc_errors.h
    libc/src/__support/StringUtil/tables/stdc_signals.h
    libc/src/__support/UInt.h
    libc/src/__support/threads/linux/thread.cpp
    libc/src/stdio/printf_core/write_int_converter.h
    libc/src/string/memory_utils/op_aarch64.h
    libc/src/string/memory_utils/op_generic.h
    libc/src/string/memory_utils/op_x86.h
    libc/src/string/memory_utils/strcmp_implementations.h
    libc/src/string/memory_utils/strstr_implementations.h
    libc/src/string/memory_utils/utils.h
    libc/src/string/string_utils.h

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/CPP/optional.h b/libc/src/__support/CPP/optional.h
index 40ba858f5eaf16..8b3959514108d4 100644
--- a/libc/src/__support/CPP/optional.h
+++ b/libc/src/__support/CPP/optional.h
@@ -18,19 +18,19 @@ namespace cpp {
 
 // Trivial in_place_t struct.
 struct in_place_t {
-  LIBC_INLINE explicit in_place_t() = default;
+  LIBC_INLINE_VAR explicit in_place_t() = default;
 };
 
 // Trivial nullopt_t struct.
 struct nullopt_t {
-  LIBC_INLINE explicit nullopt_t() = default;
+  LIBC_INLINE_VAR explicit nullopt_t() = default;
 };
 
 // nullopt that can be used and returned.
-inline constexpr nullopt_t nullopt{};
+LIBC_INLINE_VAR constexpr nullopt_t nullopt{};
 
 // in_place that can be used in the constructor.
-inline constexpr in_place_t in_place{};
+LIBC_INLINE_VAR constexpr in_place_t in_place{};
 
 // This is very simple implementation of the std::optional class. It makes
 // several assumptions that the underlying type is trivially constructable,

diff  --git a/libc/src/__support/CPP/span.h b/libc/src/__support/CPP/span.h
index dc3960e75f61f0..bc64d0d7b36d94 100644
--- a/libc/src/__support/CPP/span.h
+++ b/libc/src/__support/CPP/span.h
@@ -13,6 +13,8 @@
 #include "array.h"       // For array
 #include "type_traits.h" // For remove_cv_t, enable_if_t, is_same_v, is_const_v
 
+#include "src/__support/macros/attributes.h"
+
 namespace __llvm_libc::cpp {
 
 // A trimmed down implementation of std::span.
@@ -25,12 +27,12 @@ namespace __llvm_libc::cpp {
 // - No reverse iterators
 template <typename T> class span {
   template <typename U>
-  inline static constexpr bool is_const_view_v =
+  LIBC_INLINE_VAR static constexpr bool is_const_view_v =
       !cpp::is_const_v<U> && cpp::is_const_v<T> &&
       cpp::is_same_v<U, remove_cv_t<T>>;
 
   template <typename U>
-  inline static constexpr bool is_compatible_v =
+  LIBC_INLINE_VAR static constexpr bool is_compatible_v =
       cpp::is_same_v<U, T> || is_const_view_v<U>;
 
 public:
@@ -46,61 +48,67 @@ template <typename T> class span {
 
   static constexpr size_type dynamic_extent = -1;
 
-  constexpr span() : span_data(nullptr), span_size(0) {}
+  LIBC_INLINE constexpr span() : span_data(nullptr), span_size(0) {}
 
-  constexpr span(pointer first, size_type count)
+  LIBC_INLINE constexpr span(pointer first, size_type count)
       : span_data(first), span_size(count) {}
 
-  constexpr span(pointer first, pointer end)
+  LIBC_INLINE constexpr span(pointer first, pointer end)
       : span_data(first), span_size(end - first) {}
 
   template <typename U, size_t N,
             cpp::enable_if_t<is_compatible_v<U>, bool> = true>
-  constexpr span(U (&arr)[N]) : span_data(arr), span_size(N) {}
+  LIBC_INLINE constexpr span(U (&arr)[N]) : span_data(arr), span_size(N) {}
 
   template <typename U, size_t N,
             cpp::enable_if_t<is_compatible_v<U>, bool> = true>
-  constexpr span(array<U, N> &arr)
+  LIBC_INLINE constexpr span(array<U, N> &arr)
       : span_data(arr.data()), span_size(arr.size()) {}
 
   template <typename U, cpp::enable_if_t<is_compatible_v<U>, bool> = true>
-  constexpr span(span<U> &s) : span_data(s.data()), span_size(s.size()) {}
+  LIBC_INLINE constexpr span(span<U> &s)
+      : span_data(s.data()), span_size(s.size()) {}
 
   template <typename U, cpp::enable_if_t<is_compatible_v<U>, bool> = true>
-  constexpr span &operator=(span<U> &s) {
+  LIBC_INLINE constexpr span &operator=(span<U> &s) {
     span_data = s.data();
     span_size = s.size();
     return *this;
   }
 
-  ~span() = default;
-  constexpr reference operator[](size_type index) const {
+  LIBC_INLINE ~span() = default;
+
+  LIBC_INLINE constexpr reference operator[](size_type index) const {
     return data()[index];
   }
-  constexpr iterator begin() const { return data(); }
-  constexpr iterator end() const { return data() + size(); }
-  constexpr reference front() const { return (*this)[0]; }
-  constexpr reference back() const { return (*this)[size() - 1]; }
-  constexpr pointer data() const { return span_data; }
-  constexpr size_type size() const { return span_size; }
-  constexpr size_type size_bytes() const { return sizeof(T) * size(); }
-  constexpr bool empty() const { return size() == 0; }
-
-  constexpr span<element_type> subspan(size_type offset,
-                                       size_type count = dynamic_extent) const {
+
+  LIBC_INLINE constexpr iterator begin() const { return data(); }
+  LIBC_INLINE constexpr iterator end() const { return data() + size(); }
+  LIBC_INLINE constexpr reference front() const { return (*this)[0]; }
+  LIBC_INLINE constexpr reference back() const { return (*this)[size() - 1]; }
+  LIBC_INLINE constexpr pointer data() const { return span_data; }
+  LIBC_INLINE constexpr size_type size() const { return span_size; }
+  LIBC_INLINE constexpr size_type size_bytes() const {
+    return sizeof(T) * size();
+  }
+  LIBC_INLINE constexpr bool empty() const { return size() == 0; }
+
+  LIBC_INLINE constexpr span<element_type>
+  subspan(size_type offset, size_type count = dynamic_extent) const {
     return span<element_type>(data() + offset, count_to_size(offset, count));
   }
 
-  constexpr span<element_type> first(size_type count) const {
+  LIBC_INLINE constexpr span<element_type> first(size_type count) const {
     return subspan(0, count);
   }
 
-  constexpr span<element_type> last(size_type count) const {
+  LIBC_INLINE constexpr span<element_type> last(size_type count) const {
     return span<element_type>(data() + (size() - count), count);
   }
 
 private:
-  constexpr size_type count_to_size(size_type offset, size_type count) const {
+  LIBC_INLINE constexpr size_type count_to_size(size_type offset,
+                                                size_type count) const {
     if (count == dynamic_extent) {
       return size() - offset;
     }

diff  --git a/libc/src/__support/CPP/string_view.h b/libc/src/__support/CPP/string_view.h
index aa31f15d97c66e..e4e3f89f933541 100644
--- a/libc/src/__support/CPP/string_view.h
+++ b/libc/src/__support/CPP/string_view.h
@@ -60,7 +60,7 @@ class string_view {
 
   // special value equal to the maximum value representable by the type
   // size_type.
-  inline static constexpr size_t npos = -1;
+  LIBC_INLINE_VAR static constexpr size_t npos = -1;
 
   LIBC_INLINE constexpr string_view() : Data(nullptr), Len(0) {}
 

diff  --git a/libc/src/__support/CPP/type_traits.h b/libc/src/__support/CPP/type_traits.h
index 63ff10c58135bf..5808e92f6816a5 100644
--- a/libc/src/__support/CPP/type_traits.h
+++ b/libc/src/__support/CPP/type_traits.h
@@ -9,6 +9,8 @@
 #ifndef LLVM_LIBC_SRC_SUPPORT_CPP_TYPETRAITS_H
 #define LLVM_LIBC_SRC_SUPPORT_CPP_TYPETRAITS_H
 
+#include "src/__support/macros/attributes.h"
+
 namespace __llvm_libc {
 namespace cpp {
 
@@ -23,7 +25,7 @@ using enable_if_t = typename enable_if<B, T>::type;
 
 template <typename T, T v> struct integral_constant {
   using value_type = T;
-  static constexpr T value = v;
+  LIBC_INLINE_VAR static constexpr T value = v;
 };
 using true_type = cpp::integral_constant<bool, true>;
 using false_type = cpp::integral_constant<bool, false>;
@@ -39,11 +41,12 @@ struct is_trivially_constructible
 template <typename T, typename U> struct is_same : cpp::false_type {};
 template <typename T> struct is_same<T, T> : cpp::true_type {};
 template <typename T, typename U>
-inline constexpr bool is_same_v = is_same<T, U>::value;
+LIBC_INLINE_VAR constexpr bool is_same_v = is_same<T, U>::value;
 
 template <class T> struct is_const : cpp::false_type {};
 template <class T> struct is_const<const T> : cpp::true_type {};
-template <class T> inline constexpr bool is_const_v = is_const<T>::value;
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_const_v = is_const<T>::value;
 
 template <typename T> struct remove_cv : type_identity<T> {};
 template <typename T> struct remove_cv<const T> : type_identity<T> {};
@@ -71,7 +74,7 @@ template <typename T, typename... Args> constexpr bool is_unqualified_any_of() {
 } // namespace details
 
 template <typename T> struct is_integral {
-  static constexpr bool value = details::is_unqualified_any_of<
+  LIBC_INLINE_VAR static constexpr bool value = details::is_unqualified_any_of<
       T,
 #ifdef __SIZEOF_INT128__
       __int128_t, __uint128_t,
@@ -80,33 +83,36 @@ template <typename T> struct is_integral {
       unsigned int, long, unsigned long, long long, unsigned long long, bool>();
 };
 template <typename T>
-inline constexpr bool is_integral_v = is_integral<T>::value;
+LIBC_INLINE_VAR constexpr bool is_integral_v = is_integral<T>::value;
 
 template <typename T> struct is_enum {
-  static constexpr bool value = __is_enum(T);
+  LIBC_INLINE_VAR static constexpr bool value = __is_enum(T);
 };
-template <typename T> inline constexpr bool is_enum_v = is_enum<T>::value;
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_enum_v = is_enum<T>::value;
 
 template <typename T> struct is_pointer : cpp::false_type {};
 template <typename T> struct is_pointer<T *> : cpp::true_type {};
 template <typename T> struct is_pointer<T *const> : cpp::true_type {};
 template <typename T> struct is_pointer<T *volatile> : cpp::true_type {};
 template <typename T> struct is_pointer<T *const volatile> : cpp::true_type {};
-template <typename T> inline constexpr bool is_pointer_v = is_pointer<T>::value;
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_pointer_v = is_pointer<T>::value;
 
 template <typename T> struct is_floating_point {
-  static constexpr bool value =
+  LIBC_INLINE_VAR static constexpr bool value =
       details::is_unqualified_any_of<T, float, double, long double>();
 };
 template <typename T>
-inline constexpr bool is_floating_point_v = is_floating_point<T>::value;
+LIBC_INLINE_VAR constexpr bool is_floating_point_v =
+    is_floating_point<T>::value;
 
 template <typename T> struct is_arithmetic {
-  static constexpr bool value =
+  LIBC_INLINE_VAR static constexpr bool value =
       is_integral<T>::value || is_floating_point<T>::value;
 };
 template <typename T>
-inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
+LIBC_INLINE_VAR constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
 
 namespace details {
 template <typename T, bool = is_arithmetic<T>::value>
@@ -119,19 +125,20 @@ template <typename T> struct is_unsigned<T, false> : false_type {};
 } // namespace details
 
 template <typename T> struct is_signed {
-  static constexpr bool value = details::is_signed<T>::value;
-  constexpr operator bool() const { return value; }
-  constexpr bool operator()() const { return value; }
+  LIBC_INLINE_VAR static constexpr bool value = details::is_signed<T>::value;
+  LIBC_INLINE constexpr operator bool() const { return value; }
+  LIBC_INLINE constexpr bool operator()() const { return value; }
 };
-template <typename T> inline constexpr bool is_signed_v = is_signed<T>::value;
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_signed_v = is_signed<T>::value;
 
 template <typename T> struct is_unsigned {
-  static constexpr bool value = details::is_unsigned<T>::value;
-  constexpr operator bool() const { return value; }
-  constexpr bool operator()() const { return value; }
+  LIBC_INLINE_VAR static constexpr bool value = details::is_unsigned<T>::value;
+  LIBC_INLINE constexpr operator bool() const { return value; }
+  LIBC_INLINE constexpr bool operator()() const { return value; }
 };
 template <typename T>
-inline constexpr bool is_unsigned_v = is_unsigned<T>::value;
+LIBC_INLINE_VAR constexpr bool is_unsigned_v = is_unsigned<T>::value;
 
 template <typename T> struct make_unsigned;
 template <> struct make_unsigned<char> : type_identity<unsigned char> {};
@@ -166,7 +173,8 @@ using conditional_t = typename conditional<B, T, F>::type;
 
 template <typename T>
 struct is_void : is_same<void, typename remove_cv<T>::type> {};
-template <typename T> inline constexpr bool is_void_v = is_void<T>::value;
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_void_v = is_void<T>::value;
 template <class T> T declval();
 
 // Compile time checks on implicit conversions.
@@ -176,10 +184,12 @@ template <typename T> void convertible_to_helper(T);
 } // namespace details
 
 template <typename F, typename T, typename = void>
-inline constexpr bool is_convertible_v = false;
+LIBC_INLINE_VAR constexpr bool is_convertible_v = false;
 
+// FIXME: This should use LIBC_INLINE_VAR, but clang buggily complains about
+// this when LIBC_INLINE_VAR uses [[clang::internal_linkage]].
 template <typename F, typename T>
-inline constexpr bool
+constexpr bool
     is_convertible_v<F, T,
                      details::void_t<decltype(details::convertible_to_helper<T>(
                          declval<F>()))>> = true;

diff  --git a/libc/src/__support/StringUtil/tables/linux_extension_signals.h b/libc/src/__support/StringUtil/tables/linux_extension_signals.h
index 7e310096086876..8da3731e398722 100644
--- a/libc/src/__support/StringUtil/tables/linux_extension_signals.h
+++ b/libc/src/__support/StringUtil/tables/linux_extension_signals.h
@@ -18,7 +18,7 @@ namespace __llvm_libc {
 // The array being larger than necessary isn't a problem. The MsgMappings will
 // be set to their default state which maps 0 to an empty string. This will get
 // filtered out in the MessageMapper building stage.
-inline constexpr const MsgTable<3> LINUX_SIGNALS = {
+LIBC_INLINE_VAR constexpr const MsgTable<3> LINUX_SIGNALS = {
 #ifdef SIGSTKFLT
     MsgMapping(SIGSTKFLT, "Stack fault"), // unused
 #endif

diff  --git a/libc/src/__support/StringUtil/tables/linux_platform_errors.h b/libc/src/__support/StringUtil/tables/linux_platform_errors.h
index e6d20106f25268..49e4b1bd2a4286 100644
--- a/libc/src/__support/StringUtil/tables/linux_platform_errors.h
+++ b/libc/src/__support/StringUtil/tables/linux_platform_errors.h
@@ -15,7 +15,7 @@
 
 namespace __llvm_libc {
 
-inline constexpr auto PLATFORM_ERRORS =
+LIBC_INLINE_VAR constexpr auto PLATFORM_ERRORS =
     STDC_ERRORS + POSIX_ERRORS + LINUX_ERRORS;
 
 } // namespace __llvm_libc

diff  --git a/libc/src/__support/StringUtil/tables/linux_platform_signals.h b/libc/src/__support/StringUtil/tables/linux_platform_signals.h
index 7f98a241f9c40c..b21b0ccf89aef0 100644
--- a/libc/src/__support/StringUtil/tables/linux_platform_signals.h
+++ b/libc/src/__support/StringUtil/tables/linux_platform_signals.h
@@ -15,7 +15,7 @@
 
 namespace __llvm_libc {
 
-inline constexpr auto PLATFORM_SIGNALS =
+LIBC_INLINE_VAR constexpr auto PLATFORM_SIGNALS =
     STDC_SIGNALS + POSIX_SIGNALS + LINUX_SIGNALS;
 
 } // namespace __llvm_libc

diff  --git a/libc/src/__support/StringUtil/tables/minimal_platform_errors.h b/libc/src/__support/StringUtil/tables/minimal_platform_errors.h
index 9fa75d5c9a76ad..950b84be204994 100644
--- a/libc/src/__support/StringUtil/tables/minimal_platform_errors.h
+++ b/libc/src/__support/StringUtil/tables/minimal_platform_errors.h
@@ -13,7 +13,7 @@
 
 namespace __llvm_libc {
 
-inline constexpr auto PLATFORM_ERRORS = STDC_ERRORS;
+LIBC_INLINE_VAR constexpr auto PLATFORM_ERRORS = STDC_ERRORS;
 
 } // namespace __llvm_libc
 

diff  --git a/libc/src/__support/StringUtil/tables/minimal_platform_signals.h b/libc/src/__support/StringUtil/tables/minimal_platform_signals.h
index 758dfc8263da2b..e1a77803895f1a 100644
--- a/libc/src/__support/StringUtil/tables/minimal_platform_signals.h
+++ b/libc/src/__support/StringUtil/tables/minimal_platform_signals.h
@@ -13,7 +13,7 @@
 
 namespace __llvm_libc {
 
-inline constexpr auto PLATFORM_SIGNALS = STDC_SIGNALS;
+LIBC_INLINE_VAR constexpr auto PLATFORM_SIGNALS = STDC_SIGNALS;
 
 } // namespace __llvm_libc
 

diff  --git a/libc/src/__support/StringUtil/tables/posix_errors.h b/libc/src/__support/StringUtil/tables/posix_errors.h
index 43b1d9dec562e9..01a0f223d6679a 100644
--- a/libc/src/__support/StringUtil/tables/posix_errors.h
+++ b/libc/src/__support/StringUtil/tables/posix_errors.h
@@ -15,7 +15,7 @@
 
 namespace __llvm_libc {
 
-inline constexpr MsgTable<76> POSIX_ERRORS = {
+LIBC_INLINE_VAR constexpr MsgTable<76> POSIX_ERRORS = {
     MsgMapping(EPERM, "Operation not permitted"),
     MsgMapping(ENOENT, "No such file or directory"),
     MsgMapping(ESRCH, "No such process"),

diff  --git a/libc/src/__support/StringUtil/tables/posix_signals.h b/libc/src/__support/StringUtil/tables/posix_signals.h
index b34035d367e88d..a7e681b92449c3 100644
--- a/libc/src/__support/StringUtil/tables/posix_signals.h
+++ b/libc/src/__support/StringUtil/tables/posix_signals.h
@@ -16,7 +16,7 @@
 
 namespace __llvm_libc {
 
-inline constexpr MsgTable<22> POSIX_SIGNALS = {
+LIBC_INLINE_VAR constexpr MsgTable<22> POSIX_SIGNALS = {
     MsgMapping(SIGHUP, "Hangup"),
     MsgMapping(SIGQUIT, "Quit"),
     MsgMapping(SIGTRAP, "Trace/breakpoint trap"),

diff  --git a/libc/src/__support/StringUtil/tables/signal_table.h b/libc/src/__support/StringUtil/tables/signal_table.h
index c2b1b36df659c0..6e198a60c9b32e 100644
--- a/libc/src/__support/StringUtil/tables/signal_table.h
+++ b/libc/src/__support/StringUtil/tables/signal_table.h
@@ -26,7 +26,7 @@
 
 namespace __llvm_libc::internal {
 
-inline constexpr auto PLATFORM_SIGNALS = []() {
+LIBC_INLINE_VAR constexpr auto PLATFORM_SIGNALS = []() {
   if constexpr (USE_LINUX_PLATFORM_SIGNALS) {
     return STDC_SIGNALS + POSIX_SIGNALS + LINUX_SIGNALS;
   } else {

diff  --git a/libc/src/__support/StringUtil/tables/stdc_errors.h b/libc/src/__support/StringUtil/tables/stdc_errors.h
index 42b934f1ba9c3d..42d370583d7536 100644
--- a/libc/src/__support/StringUtil/tables/stdc_errors.h
+++ b/libc/src/__support/StringUtil/tables/stdc_errors.h
@@ -15,7 +15,7 @@
 
 namespace __llvm_libc {
 
-inline constexpr const MsgTable<4> STDC_ERRORS = {
+LIBC_INLINE_VAR constexpr const MsgTable<4> STDC_ERRORS = {
     MsgMapping(0, "Success"),
     MsgMapping(EDOM, "Numerical argument out of domain"),
     MsgMapping(ERANGE, "Numerical result out of range"),

diff  --git a/libc/src/__support/StringUtil/tables/stdc_signals.h b/libc/src/__support/StringUtil/tables/stdc_signals.h
index 3de4318ed8f6f0..13b1aeda124bd7 100644
--- a/libc/src/__support/StringUtil/tables/stdc_signals.h
+++ b/libc/src/__support/StringUtil/tables/stdc_signals.h
@@ -15,7 +15,7 @@
 
 namespace __llvm_libc {
 
-inline constexpr const MsgTable<6> STDC_SIGNALS = {
+LIBC_INLINE_VAR constexpr const MsgTable<6> STDC_SIGNALS = {
     MsgMapping(SIGINT, "Interrupt"),
     MsgMapping(SIGILL, "Illegal instruction"),
     MsgMapping(SIGABRT, "Aborted"),

diff  --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h
index 74b72b59e1ddd9..a748d47cd06cc8 100644
--- a/libc/src/__support/UInt.h
+++ b/libc/src/__support/UInt.h
@@ -27,20 +27,20 @@ template <size_t Bits, bool Signed> struct BigInt {
 
   static_assert(Bits > 0 && Bits % 64 == 0,
                 "Number of bits in BigInt should be a multiple of 64.");
-  static constexpr size_t WORDCOUNT = Bits / 64;
+  static LIBC_INLINE_VAR constexpr size_t WORDCOUNT = Bits / 64;
   uint64_t val[WORDCOUNT]{};
 
-  static constexpr uint64_t MASK32 = 0xFFFFFFFFu;
+  static LIBC_INLINE_VAR constexpr uint64_t MASK32 = 0xFFFFFFFFu;
 
-  static constexpr uint64_t low(uint64_t v) { return v & MASK32; }
-  static constexpr uint64_t high(uint64_t v) { return (v >> 32) & MASK32; }
+  static LIBC_INLINE constexpr uint64_t low(uint64_t v) { return v & MASK32; }
+  static LIBC_INLINE constexpr uint64_t high(uint64_t v) { return (v >> 32) & MASK32; }
 
-  constexpr BigInt() = default;
+  LIBC_INLINE constexpr BigInt() = default;
 
-  constexpr BigInt(const BigInt<Bits, Signed> &other) = default;
+  LIBC_INLINE constexpr BigInt(const BigInt<Bits, Signed> &other) = default;
 
   template <size_t OtherBits, bool OtherSigned>
-  constexpr BigInt(const BigInt<OtherBits, OtherSigned> &other) {
+  LIBC_INLINE constexpr BigInt(const BigInt<OtherBits, OtherSigned> &other) {
     if (OtherBits >= Bits) {
       for (size_t i = 0; i < WORDCOUNT; ++i)
         val[i] = other[i];
@@ -60,7 +60,7 @@ template <size_t Bits, bool Signed> struct BigInt {
 
   // Construct a BigInt from a C array.
   template <size_t N, enable_if_t<N <= WORDCOUNT, int> = 0>
-  constexpr BigInt(const uint64_t (&nums)[N]) {
+  LIBC_INLINE constexpr BigInt(const uint64_t (&nums)[N]) {
     size_t min_wordcount = N < WORDCOUNT ? N : WORDCOUNT;
     size_t i = 0;
     for (; i < min_wordcount; ++i)
@@ -74,7 +74,7 @@ template <size_t Bits, bool Signed> struct BigInt {
   // Initialize the first word to |v| and the rest to 0.
   template <typename T,
             typename = cpp::enable_if_t<is_integral_v<T> && sizeof(T) <= 16>>
-  constexpr BigInt(T v) {
+  LIBC_INLINE constexpr BigInt(T v) {
     val[0] = static_cast<uint64_t>(v);
 
     if constexpr (Bits == 64)
@@ -93,7 +93,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     }
   }
 
-  constexpr explicit BigInt(const cpp::array<uint64_t, WORDCOUNT> &words) {
+  LIBC_INLINE constexpr explicit BigInt(const cpp::array<uint64_t, WORDCOUNT> &words) {
     for (size_t i = 0; i < WORDCOUNT; ++i)
       val[i] = words[i];
   }
@@ -101,7 +101,7 @@ template <size_t Bits, bool Signed> struct BigInt {
   template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T> &&
                                                     sizeof(T) <= 16 &&
                                                     !cpp::is_same_v<T, bool>>>
-  constexpr explicit operator T() const {
+  LIBC_INLINE constexpr explicit operator T() const {
     if constexpr (sizeof(T) <= 8)
       return static_cast<T>(val[0]);
 
@@ -120,11 +120,11 @@ template <size_t Bits, bool Signed> struct BigInt {
     }
   }
 
-  constexpr explicit operator bool() const { return !is_zero(); }
+  LIBC_INLINE constexpr explicit operator bool() const { return !is_zero(); }
 
   BigInt<Bits, Signed> &operator=(const BigInt<Bits, Signed> &other) = default;
 
-  constexpr bool is_zero() const {
+  LIBC_INLINE constexpr bool is_zero() const {
     for (size_t i = 0; i < WORDCOUNT; ++i) {
       if (val[i] != 0)
         return false;
@@ -134,7 +134,7 @@ template <size_t Bits, bool Signed> struct BigInt {
 
   // Add x to this number and store the result in this number.
   // Returns the carry value produced by the addition operation.
-  constexpr uint64_t add(const BigInt<Bits, Signed> &x) {
+  LIBC_INLINE constexpr uint64_t add(const BigInt<Bits, Signed> &x) {
     SumCarry<uint64_t> s{0, 0};
     for (size_t i = 0; i < WORDCOUNT; ++i) {
       s = add_with_carry_const(val[i], x.val[i], s.carry);
@@ -143,7 +143,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return s.carry;
   }
 
-  BigInt<Bits, Signed> operator+(const BigInt<Bits, Signed> &other) const {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> operator+(const BigInt<Bits, Signed> &other) const {
     BigInt<Bits, Signed> result;
     SumCarry<uint64_t> s{0, 0};
     for (size_t i = 0; i < WORDCOUNT; ++i) {
@@ -155,7 +155,7 @@ template <size_t Bits, bool Signed> struct BigInt {
 
   // This will only apply when initializing a variable from constant values, so
   // it will always use the constexpr version of add_with_carry.
-  constexpr BigInt<Bits, Signed> operator+(BigInt<Bits, Signed> &&other) const {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> operator+(BigInt<Bits, Signed> &&other) const {
     BigInt<Bits, Signed> result;
     SumCarry<uint64_t> s{0, 0};
     for (size_t i = 0; i < WORDCOUNT; ++i) {
@@ -165,7 +165,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return result;
   }
 
-  constexpr BigInt<Bits, Signed> &
+  LIBC_INLINE constexpr BigInt<Bits, Signed> &
   operator+=(const BigInt<Bits, Signed> &other) {
     add(other); // Returned carry value is ignored.
     return *this;
@@ -173,7 +173,7 @@ template <size_t Bits, bool Signed> struct BigInt {
 
   // Subtract x to this number and store the result in this number.
   // Returns the carry value produced by the subtraction operation.
-  constexpr uint64_t sub(const BigInt<Bits, Signed> &x) {
+  LIBC_INLINE constexpr uint64_t sub(const BigInt<Bits, Signed> &x) {
     DiffBorrow<uint64_t> d{0, 0};
     for (size_t i = 0; i < WORDCOUNT; ++i) {
       d = sub_with_borrow_const(val[i], x.val[i], d.borrow);
@@ -182,7 +182,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return d.borrow;
   }
 
-  BigInt<Bits, Signed> operator-(const BigInt<Bits, Signed> &other) const {
+  LIBC_INLINE BigInt<Bits, Signed> operator-(const BigInt<Bits, Signed> &other) const {
     BigInt<Bits, Signed> result;
     DiffBorrow<uint64_t> d{0, 0};
     for (size_t i = 0; i < WORDCOUNT; ++i) {
@@ -192,7 +192,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return result;
   }
 
-  constexpr BigInt<Bits, Signed> operator-(BigInt<Bits, Signed> &&other) const {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> operator-(BigInt<Bits, Signed> &&other) const {
     BigInt<Bits, Signed> result;
     DiffBorrow<uint64_t> d{0, 0};
     for (size_t i = 0; i < WORDCOUNT; ++i) {
@@ -202,7 +202,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return result;
   }
 
-  constexpr BigInt<Bits, Signed> &
+  LIBC_INLINE constexpr BigInt<Bits, Signed> &
   operator-=(const BigInt<Bits, Signed> &other) {
     // TODO(lntue): Set overflow flag / errno when carry is true.
     sub(other);
@@ -215,7 +215,7 @@ template <size_t Bits, bool Signed> struct BigInt {
   // the operations using 64-bit numbers. This ensures that we don't lose the
   // carry bits.
   // Returns the carry value produced by the multiplication operation.
-  constexpr uint64_t mul(uint64_t x) {
+  LIBC_INLINE constexpr uint64_t mul(uint64_t x) {
     BigInt<128, Signed> partial_sum(0);
     uint64_t carry = 0;
     for (size_t i = 0; i < WORDCOUNT; ++i) {
@@ -230,7 +230,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return partial_sum.val[1];
   }
 
-  constexpr BigInt<Bits, Signed>
+  LIBC_INLINE constexpr BigInt<Bits, Signed>
   operator*(const BigInt<Bits, Signed> &other) const {
     if constexpr (Signed) {
       BigInt<Bits, false> a(*this);
@@ -271,7 +271,7 @@ template <size_t Bits, bool Signed> struct BigInt {
 
   // Return the full product, only unsigned for now.
   template <size_t OtherBits>
-  constexpr BigInt<Bits + OtherBits, Signed>
+  LIBC_INLINE constexpr BigInt<Bits + OtherBits, Signed>
   ful_mul(const BigInt<OtherBits, Signed> &other) const {
     BigInt<Bits + OtherBits, Signed> result(0);
     BigInt<128, Signed> partial_sum(0);
@@ -317,7 +317,7 @@ template <size_t Bits, bool Signed> struct BigInt {
   //    256      4        16          10            3
   //    512      8        64          36            7
   constexpr BigInt<Bits, Signed>
-  quick_mul_hi(const BigInt<Bits, Signed> &other) const {
+  LIBC_INLINE quick_mul_hi(const BigInt<Bits, Signed> &other) const {
     BigInt<Bits, Signed> result(0);
     BigInt<128, Signed> partial_sum(0);
     uint64_t carry = 0;
@@ -346,7 +346,7 @@ template <size_t Bits, bool Signed> struct BigInt {
 
   // pow takes a power and sets this to its starting value to that power. Zero
   // to the zeroth power returns 1.
-  constexpr void pow_n(uint64_t power) {
+  LIBC_INLINE constexpr void pow_n(uint64_t power) {
     BigInt<Bits, Signed> result = 1;
     BigInt<Bits, Signed> cur_power = *this;
 
@@ -364,7 +364,7 @@ template <size_t Bits, bool Signed> struct BigInt {
 
   // div takes another BigInt of the same size and divides this by it. The value
   // of this will be set to the quotient, and the return value is the remainder.
-  constexpr optional<BigInt<Bits, Signed>>
+  LIBC_INLINE constexpr optional<BigInt<Bits, Signed>>
   div(const BigInt<Bits, Signed> &other) {
     BigInt<Bits, Signed> remainder(0);
     if (*this < other) {
@@ -407,7 +407,7 @@ template <size_t Bits, bool Signed> struct BigInt {
   //   Since the remainder of each division step < x < 2^32, the computation of
   // each step is now properly contained within uint64_t.
   //   And finally we perform some extra alignment steps for the remaining bits.
-  constexpr optional<BigInt<Bits, Signed>> div_uint32_times_pow_2(uint32_t x,
+  LIBC_INLINE constexpr optional<BigInt<Bits, Signed>> div_uint32_times_pow_2(uint32_t x,
                                                                   size_t e) {
     BigInt<Bits, Signed> remainder(0);
 
@@ -515,32 +515,32 @@ template <size_t Bits, bool Signed> struct BigInt {
     return remainder;
   }
 
-  constexpr BigInt<Bits, Signed>
+  LIBC_INLINE constexpr BigInt<Bits, Signed>
   operator/(const BigInt<Bits, Signed> &other) const {
     BigInt<Bits, Signed> result(*this);
     result.div(other);
     return result;
   }
 
-  constexpr BigInt<Bits, Signed> &
+  LIBC_INLINE constexpr BigInt<Bits, Signed> &
   operator/=(const BigInt<Bits, Signed> &other) {
     div(other);
     return *this;
   }
 
-  constexpr BigInt<Bits, Signed>
+  LIBC_INLINE constexpr BigInt<Bits, Signed>
   operator%(const BigInt<Bits, Signed> &other) const {
     BigInt<Bits, Signed> result(*this);
     return *result.div(other);
   }
 
-  constexpr BigInt<Bits, Signed> &
+  LIBC_INLINE constexpr BigInt<Bits, Signed> &
   operator*=(const BigInt<Bits, Signed> &other) {
     *this = *this * other;
     return *this;
   }
 
-  constexpr uint64_t clz() {
+  LIBC_INLINE constexpr uint64_t clz() {
     uint64_t leading_zeroes = 0;
     for (size_t i = WORDCOUNT; i > 0; --i) {
       if (val[i - 1] == 0) {
@@ -553,7 +553,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return leading_zeroes;
   }
 
-  constexpr void shift_left(size_t s) {
+  LIBC_INLINE constexpr void shift_left(size_t s) {
 #ifdef __SIZEOF_INT128__
     if constexpr (Bits == 128) {
       // Use builtin 128 bits if available;
@@ -596,18 +596,18 @@ template <size_t Bits, bool Signed> struct BigInt {
     }
   }
 
-  constexpr BigInt<Bits, Signed> operator<<(size_t s) const {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> operator<<(size_t s) const {
     BigInt<Bits, Signed> result(*this);
     result.shift_left(s);
     return result;
   }
 
-  constexpr BigInt<Bits, Signed> &operator<<=(size_t s) {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> &operator<<=(size_t s) {
     shift_left(s);
     return *this;
   }
 
-  constexpr void shift_right(size_t s) {
+  LIBC_INLINE constexpr void shift_right(size_t s) {
 #ifdef __SIZEOF_INT128__
     if constexpr (Bits == 128) {
       // Use builtin 128 bits if available;
@@ -660,18 +660,18 @@ template <size_t Bits, bool Signed> struct BigInt {
     }
   }
 
-  constexpr BigInt<Bits, Signed> operator>>(size_t s) const {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> operator>>(size_t s) const {
     BigInt<Bits, Signed> result(*this);
     result.shift_right(s);
     return result;
   }
 
-  constexpr BigInt<Bits, Signed> &operator>>=(size_t s) {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> &operator>>=(size_t s) {
     shift_right(s);
     return *this;
   }
 
-  constexpr BigInt<Bits, Signed>
+  LIBC_INLINE constexpr BigInt<Bits, Signed>
   operator&(const BigInt<Bits, Signed> &other) const {
     BigInt<Bits, Signed> result;
     for (size_t i = 0; i < WORDCOUNT; ++i)
@@ -679,14 +679,14 @@ template <size_t Bits, bool Signed> struct BigInt {
     return result;
   }
 
-  constexpr BigInt<Bits, Signed> &
+  LIBC_INLINE constexpr BigInt<Bits, Signed> &
   operator&=(const BigInt<Bits, Signed> &other) {
     for (size_t i = 0; i < WORDCOUNT; ++i)
       val[i] &= other.val[i];
     return *this;
   }
 
-  constexpr BigInt<Bits, Signed>
+  LIBC_INLINE constexpr BigInt<Bits, Signed>
   operator|(const BigInt<Bits, Signed> &other) const {
     BigInt<Bits, Signed> result;
     for (size_t i = 0; i < WORDCOUNT; ++i)
@@ -694,14 +694,14 @@ template <size_t Bits, bool Signed> struct BigInt {
     return result;
   }
 
-  constexpr BigInt<Bits, Signed> &
+  LIBC_INLINE constexpr BigInt<Bits, Signed> &
   operator|=(const BigInt<Bits, Signed> &other) {
     for (size_t i = 0; i < WORDCOUNT; ++i)
       val[i] |= other.val[i];
     return *this;
   }
 
-  constexpr BigInt<Bits, Signed>
+  LIBC_INLINE constexpr BigInt<Bits, Signed>
   operator^(const BigInt<Bits, Signed> &other) const {
     BigInt<Bits, Signed> result;
     for (size_t i = 0; i < WORDCOUNT; ++i)
@@ -709,27 +709,27 @@ template <size_t Bits, bool Signed> struct BigInt {
     return result;
   }
 
-  constexpr BigInt<Bits, Signed> &
+  LIBC_INLINE constexpr BigInt<Bits, Signed> &
   operator^=(const BigInt<Bits, Signed> &other) {
     for (size_t i = 0; i < WORDCOUNT; ++i)
       val[i] ^= other.val[i];
     return *this;
   }
 
-  constexpr BigInt<Bits, Signed> operator~() const {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> operator~() const {
     BigInt<Bits, Signed> result;
     for (size_t i = 0; i < WORDCOUNT; ++i)
       result.val[i] = ~val[i];
     return result;
   }
 
-  constexpr BigInt<Bits, Signed> operator-() const {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> operator-() const {
     BigInt<Bits, Signed> result = ~(*this);
     result.add(BigInt<Bits, Signed>(1));
     return result;
   }
 
-  constexpr bool operator==(const BigInt<Bits, Signed> &other) const {
+  LIBC_INLINE constexpr bool operator==(const BigInt<Bits, Signed> &other) const {
     for (size_t i = 0; i < WORDCOUNT; ++i) {
       if (val[i] != other.val[i])
         return false;
@@ -737,7 +737,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return true;
   }
 
-  constexpr bool operator!=(const BigInt<Bits, Signed> &other) const {
+  LIBC_INLINE constexpr bool operator!=(const BigInt<Bits, Signed> &other) const {
     for (size_t i = 0; i < WORDCOUNT; ++i) {
       if (val[i] != other.val[i])
         return true;
@@ -745,7 +745,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return false;
   }
 
-  constexpr bool operator>(const BigInt<Bits, Signed> &other) const {
+  LIBC_INLINE constexpr bool operator>(const BigInt<Bits, Signed> &other) const {
     if constexpr (Signed) {
       // Check for 
diff erent signs;
       bool a_sign = val[WORDCOUNT - 1] >> 63;
@@ -766,7 +766,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return false;
   }
 
-  constexpr bool operator>=(const BigInt<Bits, Signed> &other) const {
+  LIBC_INLINE constexpr bool operator>=(const BigInt<Bits, Signed> &other) const {
     if constexpr (Signed) {
       // Check for 
diff erent signs;
       bool a_sign = val[WORDCOUNT - 1] >> 63;
@@ -787,7 +787,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return true;
   }
 
-  constexpr bool operator<(const BigInt<Bits, Signed> &other) const {
+  LIBC_INLINE constexpr bool operator<(const BigInt<Bits, Signed> &other) const {
     if constexpr (Signed) {
       // Check for 
diff erent signs;
       bool a_sign = val[WORDCOUNT - 1] >> 63;
@@ -809,7 +809,7 @@ template <size_t Bits, bool Signed> struct BigInt {
     return false;
   }
 
-  constexpr bool operator<=(const BigInt<Bits, Signed> &other) const {
+  LIBC_INLINE constexpr bool operator<=(const BigInt<Bits, Signed> &other) const {
     if constexpr (Signed) {
       // Check for 
diff erent signs;
       bool a_sign = val[WORDCOUNT - 1] >> 63;
@@ -830,26 +830,26 @@ template <size_t Bits, bool Signed> struct BigInt {
     return true;
   }
 
-  constexpr BigInt<Bits, Signed> &operator++() {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> &operator++() {
     BigInt<Bits, Signed> one(1);
     add(one);
     return *this;
   }
 
-  constexpr BigInt<Bits, Signed> operator++(int) {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> operator++(int) {
     BigInt<Bits, Signed> oldval(*this);
     BigInt<Bits, Signed> one(1);
     add(one);
     return oldval;
   }
 
-  constexpr BigInt<Bits, Signed> &operator--() {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> &operator--() {
     BigInt<Bits, Signed> one(1);
     sub(one);
     return *this;
   }
 
-  constexpr BigInt<Bits, Signed> operator--(int) {
+  LIBC_INLINE constexpr BigInt<Bits, Signed> operator--(int) {
     BigInt<Bits, Signed> oldval(*this);
     BigInt<Bits, Signed> one(1);
     sub(one);
@@ -857,14 +857,14 @@ template <size_t Bits, bool Signed> struct BigInt {
   }
 
   // Return the i-th 64-bit word of the number.
-  constexpr const uint64_t &operator[](size_t i) const { return val[i]; }
+  LIBC_INLINE constexpr const uint64_t &operator[](size_t i) const { return val[i]; }
 
   // Return the i-th 64-bit word of the number.
-  constexpr uint64_t &operator[](size_t i) { return val[i]; }
+  LIBC_INLINE constexpr uint64_t &operator[](size_t i) { return val[i]; }
 
-  uint64_t *data() { return val; }
+  LIBC_INLINE uint64_t *data() { return val; }
 
-  const uint64_t *data() const { return val; }
+  LIBC_INLINE const uint64_t *data() const { return val; }
 };
 
 template <size_t Bits> using UInt = BigInt<Bits, false>;
@@ -874,7 +874,7 @@ template <size_t Bits> using Int = BigInt<Bits, true>;
 // Provides limits of U/Int<128>.
 template <> class numeric_limits<UInt<128>> {
 public:
-  static constexpr UInt<128> max() {
+  LIBC_INLINE static constexpr UInt<128> max() {
     return UInt<128>({0xffff'ffff'ffff'ffff, 0xffff'ffff'ffff'ffff});
   }
   static constexpr UInt<128> min() { return UInt<128>(0); }
@@ -882,10 +882,10 @@ template <> class numeric_limits<UInt<128>> {
 
 template <> class numeric_limits<Int<128>> {
 public:
-  static constexpr Int<128> max() {
+  LIBC_INLINE static constexpr Int<128> max() {
     return Int<128>({0xffff'ffff'ffff'ffff, 0x7fff'ffff'ffff'ffff});
   }
-  static constexpr Int<128> min() {
+  LIBC_INLINE static constexpr Int<128> min() {
     return Int<128>({0, 0x8000'0000'0000'0000});
   }
 };

diff  --git a/libc/src/__support/threads/linux/thread.cpp b/libc/src/__support/threads/linux/thread.cpp
index 60baff5e8998bf..994057aa949ab5 100644
--- a/libc/src/__support/threads/linux/thread.cpp
+++ b/libc/src/__support/threads/linux/thread.cpp
@@ -120,7 +120,7 @@ LIBC_INLINE ErrorOr<void *> alloc_stack(size_t stacksize, size_t guardsize) {
 // This must always be inlined as we may be freeing the calling threads stack in
 // which case a normal return from the top the stack would cause an invalid
 // memory read.
-static __attribute__((always_inline)) inline void
+[[gnu::always_inline]] LIBC_INLINE void
 free_stack(void *stack, size_t stacksize, size_t guardsize) {
   uintptr_t stackaddr = reinterpret_cast<uintptr_t>(stack);
   stackaddr -= guardsize;
@@ -144,7 +144,7 @@ struct alignas(STACK_ALIGNMENT) StartArgs {
 // This must always be inlined as we may be freeing the calling threads stack in
 // which case a normal return from the top the stack would cause an invalid
 // memory read.
-static __attribute__((always_inline)) inline void
+[[gnu::always_inline]] LIBC_INLINE void
 cleanup_thread_resources(ThreadAttributes *attrib) {
   // Cleanup the TLS before the stack as the TLS information is stored on
   // the stack.
@@ -153,7 +153,7 @@ cleanup_thread_resources(ThreadAttributes *attrib) {
     free_stack(attrib->stack, attrib->stacksize, attrib->guardsize);
 }
 
-__attribute__((always_inline)) inline uintptr_t get_start_args_addr() {
+[[gnu::always_inline]] LIBC_INLINE uintptr_t get_start_args_addr() {
 // NOTE: For __builtin_frame_address to work reliably across compilers,
 // architectures and various optimization levels, the TU including this file
 // should be compiled with -fno-omit-frame-pointer.
@@ -176,7 +176,7 @@ __attribute__((always_inline)) inline uintptr_t get_start_args_addr() {
 #endif
 }
 
-__attribute__((noinline)) static void start_thread() {
+[[gnu::noinline]] LIBC_INLINE void start_thread() {
   auto *start_args = reinterpret_cast<StartArgs *>(get_start_args_addr());
   auto *attrib = start_args->thread_attrib;
   self.attrib = attrib;

diff  --git a/libc/src/stdio/printf_core/write_int_converter.h b/libc/src/stdio/printf_core/write_int_converter.h
index b270127afbd5db..a88665c517ab5e 100644
--- a/libc/src/stdio/printf_core/write_int_converter.h
+++ b/libc/src/stdio/printf_core/write_int_converter.h
@@ -19,7 +19,8 @@
 namespace __llvm_libc {
 namespace printf_core {
 
-int inline convert_write_int(Writer *writer, const FormatSection &to_conv) {
+LIBC_INLINE int convert_write_int(Writer *writer,
+                                  const FormatSection &to_conv) {
 
   // This is an additional check added by LLVM-libc. The reason it returns -3 is
   // because printf uses negative return values for errors, and -1 and -2 are

diff  --git a/libc/src/string/memory_utils/op_aarch64.h b/libc/src/string/memory_utils/op_aarch64.h
index afe2b7302c3597..29d3b822a4e2a5 100644
--- a/libc/src/string/memory_utils/op_aarch64.h
+++ b/libc/src/string/memory_utils/op_aarch64.h
@@ -26,7 +26,7 @@
 
 namespace __llvm_libc::aarch64 {
 
-static inline constexpr bool kNeon = LLVM_LIBC_IS_DEFINED(__ARM_NEON);
+LIBC_INLINE_VAR constexpr bool kNeon = LLVM_LIBC_IS_DEFINED(__ARM_NEON);
 
 namespace neon {
 
@@ -52,7 +52,7 @@ struct BzeroCacheLine {
   }
 };
 
-LIBC_INLINE static bool hasZva() {
+LIBC_INLINE bool hasZva() {
   uint64_t zva_val;
   asm("mrs %[zva_val], dczid_el0" : [zva_val] "=r"(zva_val));
   // DC ZVA is permitted if DZP, bit [4] is zero.

diff  --git a/libc/src/string/memory_utils/op_generic.h b/libc/src/string/memory_utils/op_generic.h
index b2c8fa2c599a9b..999b7a6b541678 100644
--- a/libc/src/string/memory_utils/op_generic.h
+++ b/libc/src/string/memory_utils/op_generic.h
@@ -318,24 +318,24 @@ template <typename T> struct Memmove {
 // Same as load above but with an offset to the pointer.
 // Making the offset explicit hints the compiler to use relevant addressing mode
 // consistently.
-template <typename T> LIBC_INLINE static T load(CPtr ptr, size_t offset) {
+template <typename T> LIBC_INLINE T load(CPtr ptr, size_t offset) {
   return ::__llvm_libc::load<T>(ptr + offset);
 }
 
 // Same as above but also makes sure the loaded value is in big endian format.
 // This is useful when implementing lexicograhic comparisons as big endian
 // scalar comparison directly maps to lexicographic byte comparisons.
-template <typename T> LIBC_INLINE static T load_be(CPtr ptr, size_t offset) {
+template <typename T> LIBC_INLINE T load_be(CPtr ptr, size_t offset) {
   return Endian::to_big_endian(load<T>(ptr, offset));
 }
 
 // Equality: returns true iff values at locations (p1 + offset) and (p2 +
 // offset) compare equal.
-template <typename T> static bool eq(CPtr p1, CPtr p2, size_t offset);
+template <typename T> LIBC_INLINE bool eq(CPtr p1, CPtr p2, size_t offset);
 
 // Not equals: returns non-zero iff values at locations (p1 + offset) and (p2 +
 // offset) 
diff er.
-template <typename T> static uint32_t neq(CPtr p1, CPtr p2, size_t offset);
+template <typename T> LIBC_INLINE uint32_t neq(CPtr p1, CPtr p2, size_t offset);
 
 // Lexicographic comparison:
 // - returns 0 iff values at locations (p1 + offset) and (p2 + offset) compare
@@ -345,7 +345,7 @@ template <typename T> static uint32_t neq(CPtr p1, CPtr p2, size_t offset);
 // - returns a positive value if value at location (p1 + offset) is
 //   lexicographically greater than value at (p2 + offset).
 template <typename T>
-static MemcmpReturnType cmp(CPtr p1, CPtr p2, size_t offset);
+LIBC_INLINE MemcmpReturnType cmp(CPtr p1, CPtr p2, size_t offset);
 
 // Lexicographic comparison of non-equal values:
 // - returns a negative value if value at location (p1 + offset) is
@@ -353,7 +353,7 @@ static MemcmpReturnType cmp(CPtr p1, CPtr p2, size_t offset);
 // - returns a positive value if value at location (p1 + offset) is
 //   lexicographically greater than value at (p2 + offset).
 template <typename T>
-static MemcmpReturnType cmp_neq(CPtr p1, CPtr p2, size_t offset);
+LIBC_INLINE MemcmpReturnType cmp_neq(CPtr p1, CPtr p2, size_t offset);
 
 ///////////////////////////////////////////////////////////////////////////////
 // Memcmp implementation
@@ -563,6 +563,7 @@ LIBC_INLINE MemcmpReturnType cmp<uint8_t>(CPtr p1, CPtr p2, size_t offset) {
 }
 template <>
 LIBC_INLINE MemcmpReturnType cmp_neq<uint8_t>(CPtr p1, CPtr p2, size_t offset);
+
 } // namespace __llvm_libc::generic
 
 #endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_GENERIC_H

diff  --git a/libc/src/string/memory_utils/op_x86.h b/libc/src/string/memory_utils/op_x86.h
index 87585419770e76..4c526dabf42ac7 100644
--- a/libc/src/string/memory_utils/op_x86.h
+++ b/libc/src/string/memory_utils/op_x86.h
@@ -50,7 +50,7 @@ LIBC_INLINE_VAR constexpr bool kAvx512BW = LLVM_LIBC_IS_DEFINED(__AVX512BW__);
 ///////////////////////////////////////////////////////////////////////////////
 // Memcpy repmovsb implementation
 struct Memcpy {
-  static void repmovsb(void *dst, const void *src, size_t count) {
+  LIBC_INLINE static void repmovsb(void *dst, const void *src, size_t count) {
     asm volatile("rep movsb" : "+D"(dst), "+S"(src), "+c"(count) : : "memory");
   }
 };

diff  --git a/libc/src/string/memory_utils/strcmp_implementations.h b/libc/src/string/memory_utils/strcmp_implementations.h
index 3a7caeef545bfe..1fc08fcd095daf 100644
--- a/libc/src/string/memory_utils/strcmp_implementations.h
+++ b/libc/src/string/memory_utils/strcmp_implementations.h
@@ -14,8 +14,8 @@
 namespace __llvm_libc {
 
 template <typename Comp>
-constexpr static int strcmp_implementation(const char *left, const char *right,
-                                           Comp &&comp) {
+LIBC_INLINE constexpr int
+strcmp_implementation(const char *left, const char *right, Comp &&comp) {
   // TODO: Look at benefits for comparing words at a time.
   for (; *left && !comp(*left, *right); ++left, ++right)
     ;
@@ -24,8 +24,9 @@ constexpr static int strcmp_implementation(const char *left, const char *right,
 }
 
 template <typename Comp>
-constexpr static int strncmp_implementation(const char *left, const char *right,
-                                            size_t n, Comp &&comp) {
+LIBC_INLINE constexpr int strncmp_implementation(const char *left,
+                                                 const char *right, size_t n,
+                                                 Comp &&comp) {
   if (n == 0)
     return 0;
 

diff  --git a/libc/src/string/memory_utils/strstr_implementations.h b/libc/src/string/memory_utils/strstr_implementations.h
index d24aedd58cdbc3..3cf1a84ef415dd 100644
--- a/libc/src/string/memory_utils/strstr_implementations.h
+++ b/libc/src/string/memory_utils/strstr_implementations.h
@@ -16,8 +16,8 @@
 namespace __llvm_libc {
 
 template <typename Comp>
-constexpr static char *strstr_implementation(const char *haystack,
-                                             const char *needle, Comp &&comp) {
+LIBC_INLINE constexpr char *
+strstr_implementation(const char *haystack, const char *needle, Comp &&comp) {
   void *result = memmem_implementation(
       static_cast<const void *>(haystack), internal::string_length(haystack),
       static_cast<const void *>(needle), internal::string_length(needle), comp);

diff  --git a/libc/src/string/memory_utils/utils.h b/libc/src/string/memory_utils/utils.h
index 93cbf15a83e71c..4356a98bda658f 100644
--- a/libc/src/string/memory_utils/utils.h
+++ b/libc/src/string/memory_utils/utils.h
@@ -24,48 +24,50 @@ namespace __llvm_libc {
 
 // Allows compile time error reporting in `if constexpr` branches.
 template <bool flag = false>
-static void deferred_static_assert(const char *msg) {
+LIBC_INLINE void deferred_static_assert(const char *msg) {
   static_assert(flag, "compilation error");
   (void)msg;
 }
 
 // Return whether `value` is zero or a power of two.
-static constexpr bool is_power2_or_zero(size_t value) {
+LIBC_INLINE constexpr bool is_power2_or_zero(size_t value) {
   return (value & (value - 1U)) == 0;
 }
 
 // Return whether `value` is a power of two.
-static constexpr bool is_power2(size_t value) {
+LIBC_INLINE constexpr bool is_power2(size_t value) {
   return value && is_power2_or_zero(value);
 }
 
 // Compile time version of log2 that handles 0.
-static constexpr size_t log2s(size_t value) {
+LIBC_INLINE constexpr size_t log2s(size_t value) {
   return (value == 0 || value == 1) ? 0 : 1 + log2s(value / 2);
 }
 
 // Returns the first power of two preceding value or value if it is already a
 // power of two (or 0 when value is 0).
-static constexpr size_t le_power2(size_t value) {
+LIBC_INLINE constexpr size_t le_power2(size_t value) {
   return value == 0 ? value : 1ULL << log2s(value);
 }
 
 // Returns the first power of two following value or value if it is already a
 // power of two (or 0 when value is 0).
-static constexpr size_t ge_power2(size_t value) {
+LIBC_INLINE constexpr size_t ge_power2(size_t value) {
   return is_power2_or_zero(value) ? value : 1ULL << (log2s(value) + 1);
 }
 
 // Returns the number of bytes to substract from ptr to get to the previous
 // multiple of alignment. If ptr is already aligned returns 0.
-template <size_t alignment> uintptr_t distance_to_align_down(const void *ptr) {
+template <size_t alignment>
+LIBC_INLINE uintptr_t distance_to_align_down(const void *ptr) {
   static_assert(is_power2(alignment), "alignment must be a power of 2");
   return reinterpret_cast<uintptr_t>(ptr) & (alignment - 1U);
 }
 
 // Returns the number of bytes to add to ptr to get to the next multiple of
 // alignment. If ptr is already aligned returns 0.
-template <size_t alignment> uintptr_t distance_to_align_up(const void *ptr) {
+template <size_t alignment>
+LIBC_INLINE uintptr_t distance_to_align_up(const void *ptr) {
   static_assert(is_power2(alignment), "alignment must be a power of 2");
   // The logic is not straightforward and involves unsigned modulo arithmetic
   // but the generated code is as fast as it can be.
@@ -75,12 +77,13 @@ template <size_t alignment> uintptr_t distance_to_align_up(const void *ptr) {
 // Returns the number of bytes to add to ptr to get to the next multiple of
 // alignment. If ptr is already aligned returns alignment.
 template <size_t alignment>
-uintptr_t distance_to_next_aligned(const void *ptr) {
+LIBC_INLINE uintptr_t distance_to_next_aligned(const void *ptr) {
   return alignment - distance_to_align_down<alignment>(ptr);
 }
 
 // Returns the same pointer but notifies the compiler that it is aligned.
-template <size_t alignment, typename T> static T *assume_aligned(T *ptr) {
+template <size_t alignment, typename T>
+LIBC_INLINE T *assume_aligned(T *ptr) {
   return reinterpret_cast<T *>(__builtin_assume_aligned(ptr, alignment));
 }
 

diff  --git a/libc/src/string/string_utils.h b/libc/src/string/string_utils.h
index 572d47d639565f..da4bcb955ab473 100644
--- a/libc/src/string/string_utils.h
+++ b/libc/src/string/string_utils.h
@@ -225,7 +225,8 @@ LIBC_INLINE size_t strlcpy(char *__restrict dst, const char *__restrict src,
 }
 
 template <bool ReturnNull = true>
-constexpr static char *strchr_implementation(const char *src, int c) {
+LIBC_INLINE constexpr static char *strchr_implementation(const char *src,
+                                                         int c) {
   char ch = static_cast<char>(c);
   for (; *src && *src != ch; ++src)
     ;
@@ -233,7 +234,8 @@ constexpr static char *strchr_implementation(const char *src, int c) {
   return *src == ch ? const_cast<char *>(src) : ret;
 }
 
-constexpr static char *strrchr_implementation(const char *src, int c) {
+LIBC_INLINE constexpr static char *strrchr_implementation(const char *src,
+                                                          int c) {
   char ch = static_cast<char>(c);
   char *last_occurrence = nullptr;
   for (; *src; ++src) {


        


More information about the libc-commits mailing list