From 3c659b956accc288f9332049d5313d0406dc48c4 Mon Sep 17 00:00:00 2001
From: barracuda156 <vital.had@gmail.com>
Date: Tue, 14 Nov 2023 21:46:08 +0800
Subject: [PATCH] Add coroutine header

From: https://github.com/iains/llvm-project/commit/0ec37d1e98f07379443c420569f282b12482595f
---
 libcxx/include/CMakeLists.txt         |   1 +
 libcxx/include/__config               |   5 +-
 libcxx/include/coroutine              | 409 ++++++++++++++++++++++++++
 libcxx/include/experimental/coroutine |   7 +
 4 files changed, 421 insertions(+), 1 deletion(-)
 create mode 100644 libcxx/include/coroutine

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index d9def18d725..dc3cf73770a 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -44,6 +44,7 @@ set(files
   complex
   complex.h
   condition_variable
+  coroutine
   csetjmp
   csignal
   cstdarg
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 738d891e303..1bd724722c5 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1244,7 +1244,10 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
 #define _LIBCPP_HAS_NO_IS_AGGREGATE
 #endif
 
-#if !defined(__cpp_coroutines) || __cpp_coroutines < 201703L
+#if defined(__clang__) && (!defined(__cpp_coroutine) || \
+                           __cpp_coroutine < 201703L)
+#define _LIBCPP_HAS_NO_COROUTINES
+#elif !defined(__cpp_impl_coroutine) || __cpp_impl_coroutine < 201703L
 #define _LIBCPP_HAS_NO_COROUTINES
 #endif
 
diff --git a/libcxx/include/coroutine b/libcxx/include/coroutine
new file mode 100644
index 00000000000..0b3eac1f021
--- /dev/null
+++ b/libcxx/include/coroutine
@@ -0,0 +1,409 @@
+// -*- C++ -*-
+//===----------------------------- coroutine -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_COROUTINE
+#define _LIBCPP_COROUTINE
+
+/**
+    experimental/coroutine synopsis
+
+// C++next
+
+namespace std {
+inline namespace __coro20 {
+
+  // 18.11.1 coroutine traits
+template <typename R, typename... ArgTypes>
+class coroutine_traits;
+// 18.11.2 coroutine handle
+template <typename Promise = void>
+class coroutine_handle;
+// 18.11.2.7 comparison operators:
+bool operator==(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT;
+bool operator!=(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT;
+bool operator<(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT;
+bool operator<=(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT;
+bool operator>=(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT;
+bool operator>(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT;
+// 18.11.3 trivial awaitables
+struct suspend_never;
+struct suspend_always;
+// 18.11.2.8 hash support:
+template <class T> struct hash;
+template <class P> struct hash<coroutine_handle<P>>;
+
+} // namespace __coro20
+} // namespace std
+
+ */
+
+#include <__config>
+
+#if defined(_LIBCPP_COMPILER_GCC)
+
+#include <new>
+#include <type_traits>
+#include <functional>
+#include <memory> // for hash<T*>
+#include <cstddef>
+#include <__debug>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+#ifdef _LIBCPP_HAS_NO_COROUTINES
+# if defined(_LIBCPP_WARNING)
+    _LIBCPP_WARNING("<experimental/coroutine> cannot be used with this compiler")
+# else
+#   warning <experimental/coroutine> cannot be used with this compiler
+# endif
+#endif
+
+#ifndef _LIBCPP_HAS_NO_COROUTINES
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+inline namespace __coro20 {
+
+template <class _Tp, class = void>
+struct __coroutine_traits_sfinae {};
+
+template <class _Tp>
+struct __coroutine_traits_sfinae<
+    _Tp, typename __void_t<typename _Tp::promise_type>::type>
+{
+  using promise_type = typename _Tp::promise_type;
+};
+
+template <typename _Ret, typename... _Args>
+struct coroutine_traits
+    : public __coroutine_traits_sfinae<_Ret>
+{
+};
+
+template <typename _Promise = void>
+class _LIBCPP_TEMPLATE_VIS coroutine_handle;
+
+template <>
+class _LIBCPP_TEMPLATE_VIS coroutine_handle<void> {
+public:
+    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR coroutine_handle() _NOEXCEPT : __handle_(nullptr) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR coroutine_handle(nullptr_t) _NOEXCEPT : __handle_(nullptr) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    coroutine_handle& operator=(nullptr_t) _NOEXCEPT {
+        __handle_ = nullptr;
+        return *this;
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR void* address() const _NOEXCEPT { return __handle_; }
+
+    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR explicit operator bool() const _NOEXCEPT { return __handle_; }
+
+    _LIBCPP_INLINE_VISIBILITY
+    void operator()() { resume(); }
+
+    _LIBCPP_INLINE_VISIBILITY
+    void resume() {
+      _LIBCPP_ASSERT(__is_suspended(),
+                     "resume() can only be called on suspended coroutines");
+      _LIBCPP_ASSERT(!done(),
+                "resume() has undefined behavior when the coroutine is done");
+      __builtin_coro_resume(__handle_);
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    void destroy() {
+      _LIBCPP_ASSERT(__is_suspended(),
+                     "destroy() can only be called on suspended coroutines");
+      __builtin_coro_destroy(__handle_);
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    bool done() const {
+      _LIBCPP_ASSERT(__is_suspended(),
+                     "done() can only be called on suspended coroutines");
+      return __builtin_coro_done(__handle_);
+    }
+
+public:
+    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR
+    static coroutine_handle from_address(void* __addr) _NOEXCEPT {
+        coroutine_handle __tmp;
+        __tmp.__handle_ = __addr;
+        return __tmp;
+    }
+
+    // FIXME: Should from_address(nullptr) be allowed?
+    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR
+    static coroutine_handle from_address(nullptr_t) _NOEXCEPT {
+      return coroutine_handle(nullptr);
+    }
+
+    template <class _Tp, bool _CallIsValid = false>
+    static coroutine_handle from_address(_Tp*) {
+      static_assert(_CallIsValid,
+       "coroutine_handle<void>::from_address cannot be called with "
+        "non-void pointers");
+    }
+
+private:
+  bool __is_suspended() const _NOEXCEPT  {
+    // FIXME actually implement a check for if the coro is suspended.
+    return __handle_;
+  }
+
+  template <class _PromiseT> friend class coroutine_handle;
+  void* __handle_;
+};
+
+// 18.11.2.7 comparison operators:
+inline _LIBCPP_INLINE_VISIBILITY
+bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
+    return __x.address() == __y.address();
+}
+inline _LIBCPP_INLINE_VISIBILITY
+bool operator!=(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
+    return !(__x == __y);
+}
+inline _LIBCPP_INLINE_VISIBILITY
+bool operator<(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
+    return less<void*>()(__x.address(), __y.address());
+}
+inline _LIBCPP_INLINE_VISIBILITY
+bool operator>(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
+    return __y < __x;
+}
+inline _LIBCPP_INLINE_VISIBILITY
+bool operator<=(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
+    return !(__x > __y);
+}
+inline _LIBCPP_INLINE_VISIBILITY
+bool operator>=(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
+    return !(__x < __y);
+}
+
+template <typename _Promise>
+class _LIBCPP_TEMPLATE_VIS coroutine_handle : public coroutine_handle<> {
+    using _Base = coroutine_handle<>;
+public:
+#ifndef _LIBCPP_CXX03_LANG
+    // 18.11.2.1 construct/reset
+    using coroutine_handle<>::coroutine_handle;
+#else
+    _LIBCPP_INLINE_VISIBILITY coroutine_handle() _NOEXCEPT : _Base() {}
+    _LIBCPP_INLINE_VISIBILITY coroutine_handle(nullptr_t) _NOEXCEPT : _Base(nullptr) {}
+#endif
+    _LIBCPP_INLINE_VISIBILITY
+    coroutine_handle& operator=(nullptr_t) _NOEXCEPT {
+        _Base::operator=(nullptr);
+        return *this;
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    _Promise& promise() const {
+        return *static_cast<_Promise*>(
+            __builtin_coro_promise(this->__handle_, _LIBCPP_ALIGNOF(_Promise), false));
+    }
+
+public:
+    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR
+    static coroutine_handle from_address(void* __addr) _NOEXCEPT {
+        coroutine_handle __tmp;
+        __tmp.__handle_ = __addr;
+        return __tmp;
+    }
+
+    // NOTE: this overload isn't required by the standard but is needed so
+    // the deleted _Promise* overload doesn't make from_address(nullptr)
+    // ambiguous.
+    // FIXME: should from_address work with nullptr?
+    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_CONSTEXPR
+    static coroutine_handle from_address(nullptr_t) _NOEXCEPT {
+      return coroutine_handle(nullptr);
+    }
+
+    template <class _Tp, bool _CallIsValid = false>
+    static coroutine_handle from_address(_Tp*) {
+      static_assert(_CallIsValid,
+       "coroutine_handle<promise_type>::from_address cannot be called with "
+        "non-void pointers");
+    }
+
+    template <bool _CallIsValid = false>
+    static coroutine_handle from_address(_Promise*) {
+      static_assert(_CallIsValid,
+       "coroutine_handle<promise_type>::from_address cannot be used with "
+        "pointers to the coroutine's promise type; use 'from_promise' instead");
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    static coroutine_handle from_promise(_Promise& __promise) _NOEXCEPT {
+        typedef typename remove_cv<_Promise>::type _RawPromise;
+        coroutine_handle __tmp;
+        __tmp.__handle_ = __builtin_coro_promise(
+            _VSTD::addressof(const_cast<_RawPromise&>(__promise)),
+             _LIBCPP_ALIGNOF(_Promise), true);
+        return __tmp;
+    }
+};
+
+#if __has_builtin(__builtin_coro_noop)
+struct noop_coroutine_promise {};
+
+template <>
+class _LIBCPP_TEMPLATE_VIS coroutine_handle<noop_coroutine_promise>
+    : public coroutine_handle<> {
+  using _Base = coroutine_handle<>;
+  using _Promise = noop_coroutine_promise;
+public:
+
+  _LIBCPP_INLINE_VISIBILITY
+  _Promise& promise() const {
+    return *static_cast<_Promise*>(
+      __builtin_coro_promise(this->__handle_, _LIBCPP_ALIGNOF(_Promise), false));
+  }
+
+  _LIBCPP_CONSTEXPR explicit operator bool() const _NOEXCEPT { return true; }
+  _LIBCPP_CONSTEXPR bool done() const _NOEXCEPT { return false; }
+
+  _LIBCPP_CONSTEXPR_AFTER_CXX17 void operator()() const _NOEXCEPT {}
+  _LIBCPP_CONSTEXPR_AFTER_CXX17 void resume() const _NOEXCEPT {}
+  _LIBCPP_CONSTEXPR_AFTER_CXX17 void destroy() const _NOEXCEPT {}
+
+private:
+  _LIBCPP_INLINE_VISIBILITY
+  friend coroutine_handle<noop_coroutine_promise> noop_coroutine() _NOEXCEPT;
+
+  _LIBCPP_INLINE_VISIBILITY coroutine_handle() _NOEXCEPT {
+    this->__handle_ = __builtin_coro_noop();
+  }
+};
+
+using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
+
+inline _LIBCPP_INLINE_VISIBILITY
+noop_coroutine_handle noop_coroutine() _NOEXCEPT {
+  return noop_coroutine_handle();
+}
+#else
+  /// [coroutine.noop]
+  struct noop_coroutine_promise
+  {
+  };
+
+  // 17.12.4.1 Class noop_coroutine_promise
+  /// [coroutine.promise.noop]
+  template <>
+    struct coroutine_handle<noop_coroutine_promise>
+    {
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 3460. Unimplementable noop_coroutine_handle guarantees
+      // [coroutine.handle.noop.conv], conversion
+      _LIBCPP_CONSTEXPR operator coroutine_handle<>() const _NOEXCEPT
+      { return coroutine_handle<>::from_address(address()); }
+
+      // [coroutine.handle.noop.observers], observers
+      _LIBCPP_CONSTEXPR explicit operator bool() const _NOEXCEPT { return true; }
+
+      _LIBCPP_CONSTEXPR bool done() const _NOEXCEPT { return false; }
+
+      // [coroutine.handle.noop.resumption], resumption
+      void operator()() const _NOEXCEPT {}
+
+      void resume() const noexcept {}
+
+      void destroy() const noexcept {}
+
+      // [coroutine.handle.noop.promise], promise access
+      noop_coroutine_promise& promise() const noexcept
+      { return _S_fr.__p; }
+
+      // [coroutine.handle.noop.address], address
+      _LIBCPP_CONSTEXPR void* address() const noexcept { return _M_fr_ptr; }
+
+    private:
+      friend coroutine_handle noop_coroutine() _NOEXCEPT;
+
+      struct __frame
+      {
+	static void __dummy_resume_destroy() { }
+
+	void (*__r)() = __dummy_resume_destroy;
+	void (*__d)() = __dummy_resume_destroy;
+	struct noop_coroutine_promise __p;
+      };
+
+      static __frame _S_fr;
+
+      explicit coroutine_handle() noexcept = default;
+
+      void* _M_fr_ptr = &_S_fr;
+    };
+
+  using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
+
+  inline noop_coroutine_handle::__frame
+  noop_coroutine_handle::_S_fr{};
+
+  inline noop_coroutine_handle noop_coroutine() _NOEXCEPT
+  {
+    return noop_coroutine_handle();
+  }
+
+#endif // __has_builtin(__builtin_coro_noop)
+
+struct suspend_never {
+  _LIBCPP_INLINE_VISIBILITY
+  bool await_ready() const _NOEXCEPT { return true; }
+  _LIBCPP_INLINE_VISIBILITY
+  void await_suspend(coroutine_handle<>) const _NOEXCEPT {}
+  _LIBCPP_INLINE_VISIBILITY
+  void await_resume() const _NOEXCEPT {}
+};
+
+struct suspend_always {
+  _LIBCPP_INLINE_VISIBILITY
+  bool await_ready() const _NOEXCEPT { return false; }
+  _LIBCPP_INLINE_VISIBILITY
+  void await_suspend(coroutine_handle<>) const _NOEXCEPT {}
+  _LIBCPP_INLINE_VISIBILITY
+  void await_resume() const _NOEXCEPT {}
+};
+
+} // __coro20
+
+template <class _Tp>
+struct hash<_VSTD::__coro20::coroutine_handle<_Tp> > {
+    using __arg_type = _VSTD::__coro20::coroutine_handle<_Tp>;
+    _LIBCPP_INLINE_VISIBILITY
+    size_t operator()(__arg_type const& __v) const _NOEXCEPT
+    {return hash<void*>()(__v.address());}
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // !defined(_LIBCPP_HAS_NO_COROUTINES)
+
+#else // the compiler doesn't support this header.
+
+#error this compiler should use <experimental/coroutine>
+
+#endif
+
+#endif /* _LIBCPP_COROUTINE */
diff --git a/libcxx/include/experimental/coroutine b/libcxx/include/experimental/coroutine
index 1eb224a535a..f43440bd522 100644
--- a/libcxx/include/experimental/coroutine
+++ b/libcxx/include/experimental/coroutine
@@ -47,6 +47,11 @@ template <class P> struct hash<coroutine_handle<P>>;
  */
 
 #include <experimental/__config>
+
+#if defined(_LIBCPP_COMPILER_GCC)
+# error GCC should include <coroutine> not <experimental/coroutine>
+#else
+
 #include <new>
 #include <type_traits>
 #include <functional>
@@ -333,4 +338,6 @@ _LIBCPP_END_NAMESPACE_STD
 
 #endif // !defined(_LIBCPP_HAS_NO_COROUTINES)
 
+#endif // check for which compiler.
+
 #endif /* _LIBCPP_EXPERIMENTAL_COROUTINE */
