[CIR][NFC] Reorganize coroutine tests (#211152)
Move the coroutine tests into a dedicated CodeGenCoroutines directory. This is a test only reorganization in preparation for upcoming coroutine-related changes.
This commit is contained in:
parent
7bbaa66b88
commit
39eb2a11a2
3 changed files with 154 additions and 163 deletions
152
clang/test/CIR/CodeGenCoroutines/Inputs/coroutine.h
Normal file
152
clang/test/CIR/CodeGenCoroutines/Inputs/coroutine.h
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
|
||||
namespace std {
|
||||
|
||||
template<typename T> struct remove_reference { typedef T type; };
|
||||
template<typename T> struct remove_reference<T &> { typedef T type; };
|
||||
template<typename T> struct remove_reference<T &&> { typedef T type; };
|
||||
|
||||
template<typename T>
|
||||
typename remove_reference<T>::type &&move(T &&t) noexcept;
|
||||
|
||||
template <class Ret, typename... T>
|
||||
struct coroutine_traits { using promise_type = typename Ret::promise_type; };
|
||||
|
||||
template <class Promise = void>
|
||||
struct coroutine_handle {
|
||||
static coroutine_handle from_address(void *) noexcept;
|
||||
};
|
||||
template <>
|
||||
struct coroutine_handle<void> {
|
||||
template <class PromiseType>
|
||||
coroutine_handle(coroutine_handle<PromiseType>) noexcept;
|
||||
static coroutine_handle from_address(void *);
|
||||
};
|
||||
|
||||
struct suspend_always {
|
||||
bool await_ready() noexcept { return false; }
|
||||
void await_suspend(coroutine_handle<>) noexcept {}
|
||||
void await_resume() noexcept {}
|
||||
};
|
||||
|
||||
struct suspend_never {
|
||||
bool await_ready() noexcept { return true; }
|
||||
void await_suspend(coroutine_handle<>) noexcept {}
|
||||
void await_resume() noexcept {}
|
||||
};
|
||||
|
||||
// Awaitable whose await_resume CAN throw.
|
||||
struct suspend_maybe_throw {
|
||||
bool await_ready() noexcept;
|
||||
void await_suspend(coroutine_handle<>) noexcept;
|
||||
void await_resume(); // not noexcept
|
||||
};
|
||||
|
||||
// Awaitable whose await_resume is noexcept.
|
||||
struct suspend_nothrow {
|
||||
bool await_ready() noexcept;
|
||||
void await_suspend(coroutine_handle<>) noexcept;
|
||||
void await_resume() noexcept;
|
||||
};
|
||||
|
||||
struct string {
|
||||
int size() const;
|
||||
string();
|
||||
string(char const *s);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct optional {
|
||||
optional();
|
||||
optional(const T&);
|
||||
T &operator*() &;
|
||||
T &&operator*() &&;
|
||||
T &value() &;
|
||||
T &&value() &&;
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
namespace folly {
|
||||
namespace coro {
|
||||
|
||||
using std::suspend_always;
|
||||
using std::suspend_never;
|
||||
using std::coroutine_handle;
|
||||
|
||||
using SemiFuture = int;
|
||||
|
||||
template<class T>
|
||||
struct Task {
|
||||
struct promise_type {
|
||||
Task<T> get_return_object() noexcept;
|
||||
suspend_always initial_suspend() noexcept;
|
||||
suspend_always final_suspend() noexcept;
|
||||
void return_value(T);
|
||||
void unhandled_exception();
|
||||
auto yield_value(Task<T>) noexcept { return final_suspend(); }
|
||||
};
|
||||
bool await_ready() noexcept { return false; }
|
||||
void await_suspend(coroutine_handle<>) noexcept {}
|
||||
T await_resume();
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Task<void> {
|
||||
struct promise_type {
|
||||
Task<void> get_return_object() noexcept;
|
||||
suspend_always initial_suspend() noexcept;
|
||||
suspend_always final_suspend() noexcept;
|
||||
void return_void() noexcept;
|
||||
void unhandled_exception() noexcept;
|
||||
auto yield_value(Task<void>) noexcept { return final_suspend(); }
|
||||
};
|
||||
bool await_ready() noexcept { return false; }
|
||||
void await_suspend(coroutine_handle<>) noexcept {}
|
||||
void await_resume() noexcept {}
|
||||
SemiFuture semi();
|
||||
};
|
||||
|
||||
// FIXME: add CIRGen support here.
|
||||
// struct blocking_wait_fn {
|
||||
// template <typename T>
|
||||
// T operator()(Task<T>&& awaitable) const {
|
||||
// return T();
|
||||
// }
|
||||
// };
|
||||
|
||||
// inline constexpr blocking_wait_fn blocking_wait{};
|
||||
// static constexpr blocking_wait_fn const& blockingWait = blocking_wait;
|
||||
template <typename T>
|
||||
T blockingWait(Task<T>&& awaitable) {
|
||||
return T();
|
||||
}
|
||||
|
||||
struct co_invoke_fn {
|
||||
template <typename F, typename... A>
|
||||
Task<void> operator()(F&& f, A&&... a) const {
|
||||
return Task<void>();
|
||||
}
|
||||
};
|
||||
|
||||
co_invoke_fn co_invoke;
|
||||
|
||||
}} // namespace folly::coro
|
||||
|
||||
struct TaskWithEH {
|
||||
struct promise_type {
|
||||
TaskWithEH get_return_object();
|
||||
std::suspend_nothrow initial_suspend() noexcept;
|
||||
std::suspend_nothrow final_suspend() noexcept;
|
||||
void return_void();
|
||||
void unhandled_exception();
|
||||
};
|
||||
};
|
||||
|
||||
struct TaskThrowingInit {
|
||||
struct promise_type {
|
||||
TaskThrowingInit get_return_object();
|
||||
std::suspend_maybe_throw initial_suspend() noexcept; // resume CAN throw
|
||||
std::suspend_nothrow final_suspend() noexcept;
|
||||
void return_void();
|
||||
void unhandled_exception();
|
||||
};
|
||||
};
|
||||
|
|
@ -4,42 +4,7 @@
|
|||
// FIXME: we currently don't have flatten-cfg for coroutines or lower to LLVM-IR
|
||||
// implemented correctly, so this tests only the CIR output.
|
||||
|
||||
namespace std {
|
||||
template <class Ret, typename... T>
|
||||
struct coroutine_traits { using promise_type = typename Ret::promise_type; };
|
||||
|
||||
template <class Promise = void> struct coroutine_handle {
|
||||
static coroutine_handle from_address(void *) noexcept;
|
||||
};
|
||||
template <> struct coroutine_handle<void> {
|
||||
template <class P> coroutine_handle(coroutine_handle<P>) noexcept;
|
||||
static coroutine_handle from_address(void *);
|
||||
};
|
||||
|
||||
// Awaitable whose await_resume CAN throw.
|
||||
struct suspend_maybe_throw {
|
||||
bool await_ready() noexcept;
|
||||
void await_suspend(coroutine_handle<>) noexcept;
|
||||
void await_resume(); // not noexcept
|
||||
};
|
||||
|
||||
// Awaitable whose await_resume is noexcept.
|
||||
struct suspend_nothrow {
|
||||
bool await_ready() noexcept;
|
||||
void await_suspend(coroutine_handle<>) noexcept;
|
||||
void await_resume() noexcept;
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
struct TaskWithEH {
|
||||
struct promise_type {
|
||||
TaskWithEH get_return_object();
|
||||
std::suspend_nothrow initial_suspend() noexcept;
|
||||
std::suspend_nothrow final_suspend() noexcept;
|
||||
void return_void();
|
||||
void unhandled_exception();
|
||||
};
|
||||
};
|
||||
#include "Inputs/coroutine.h"
|
||||
|
||||
TaskWithEH simple_eh_body() {
|
||||
co_return;
|
||||
|
|
@ -74,16 +39,6 @@ TaskWithEH simple_eh_body() {
|
|||
// Make sure that 'final' is outside of the above try/catch/etc.
|
||||
// CIR: cir.call @_ZN10TaskWithEH12promise_type13final_suspendEv
|
||||
|
||||
struct TaskThrowingInit {
|
||||
struct promise_type {
|
||||
TaskThrowingInit get_return_object();
|
||||
std::suspend_maybe_throw initial_suspend() noexcept; // resume CAN throw
|
||||
std::suspend_nothrow final_suspend() noexcept;
|
||||
void return_void();
|
||||
void unhandled_exception();
|
||||
};
|
||||
};
|
||||
|
||||
TaskThrowingInit throwing_init_suspend() {
|
||||
co_return;
|
||||
}
|
||||
|
|
@ -3,123 +3,7 @@
|
|||
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm -disable-llvm-passes %s -o %t-cir.ll
|
||||
// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=OGCG
|
||||
|
||||
namespace std {
|
||||
|
||||
template<typename T> struct remove_reference { typedef T type; };
|
||||
template<typename T> struct remove_reference<T &> { typedef T type; };
|
||||
template<typename T> struct remove_reference<T &&> { typedef T type; };
|
||||
|
||||
template<typename T>
|
||||
typename remove_reference<T>::type &&move(T &&t) noexcept;
|
||||
|
||||
template <class Ret, typename... T>
|
||||
struct coroutine_traits { using promise_type = typename Ret::promise_type; };
|
||||
|
||||
template <class Promise = void>
|
||||
struct coroutine_handle {
|
||||
static coroutine_handle from_address(void *) noexcept;
|
||||
};
|
||||
template <>
|
||||
struct coroutine_handle<void> {
|
||||
template <class PromiseType>
|
||||
coroutine_handle(coroutine_handle<PromiseType>) noexcept;
|
||||
static coroutine_handle from_address(void *);
|
||||
};
|
||||
|
||||
struct suspend_always {
|
||||
bool await_ready() noexcept { return false; }
|
||||
void await_suspend(coroutine_handle<>) noexcept {}
|
||||
void await_resume() noexcept {}
|
||||
};
|
||||
|
||||
struct suspend_never {
|
||||
bool await_ready() noexcept { return true; }
|
||||
void await_suspend(coroutine_handle<>) noexcept {}
|
||||
void await_resume() noexcept {}
|
||||
};
|
||||
|
||||
struct string {
|
||||
int size() const;
|
||||
string();
|
||||
string(char const *s);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct optional {
|
||||
optional();
|
||||
optional(const T&);
|
||||
T &operator*() &;
|
||||
T &&operator*() &&;
|
||||
T &value() &;
|
||||
T &&value() &&;
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
namespace folly {
|
||||
namespace coro {
|
||||
|
||||
using std::suspend_always;
|
||||
using std::suspend_never;
|
||||
using std::coroutine_handle;
|
||||
|
||||
using SemiFuture = int;
|
||||
|
||||
template<class T>
|
||||
struct Task {
|
||||
struct promise_type {
|
||||
Task<T> get_return_object() noexcept;
|
||||
suspend_always initial_suspend() noexcept;
|
||||
suspend_always final_suspend() noexcept;
|
||||
void return_value(T);
|
||||
void unhandled_exception();
|
||||
auto yield_value(Task<T>) noexcept { return final_suspend(); }
|
||||
};
|
||||
bool await_ready() noexcept { return false; }
|
||||
void await_suspend(coroutine_handle<>) noexcept {}
|
||||
T await_resume();
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Task<void> {
|
||||
struct promise_type {
|
||||
Task<void> get_return_object() noexcept;
|
||||
suspend_always initial_suspend() noexcept;
|
||||
suspend_always final_suspend() noexcept;
|
||||
void return_void() noexcept;
|
||||
void unhandled_exception() noexcept;
|
||||
auto yield_value(Task<void>) noexcept { return final_suspend(); }
|
||||
};
|
||||
bool await_ready() noexcept { return false; }
|
||||
void await_suspend(coroutine_handle<>) noexcept {}
|
||||
void await_resume() noexcept {}
|
||||
SemiFuture semi();
|
||||
};
|
||||
|
||||
// FIXME: add CIRGen support here.
|
||||
// struct blocking_wait_fn {
|
||||
// template <typename T>
|
||||
// T operator()(Task<T>&& awaitable) const {
|
||||
// return T();
|
||||
// }
|
||||
// };
|
||||
|
||||
// inline constexpr blocking_wait_fn blocking_wait{};
|
||||
// static constexpr blocking_wait_fn const& blockingWait = blocking_wait;
|
||||
template <typename T>
|
||||
T blockingWait(Task<T>&& awaitable) {
|
||||
return T();
|
||||
}
|
||||
|
||||
struct co_invoke_fn {
|
||||
template <typename F, typename... A>
|
||||
Task<void> operator()(F&& f, A&&... a) const {
|
||||
return Task<void>();
|
||||
}
|
||||
};
|
||||
|
||||
co_invoke_fn co_invoke;
|
||||
|
||||
}} // namespace folly::coro
|
||||
#include "Inputs/coroutine.h"
|
||||
|
||||
// CIR-DAG: ![[VoidTask:.*]] = !cir.struct<"folly::coro::Task<void>" padded {!u8i}>
|
||||
// CIR-DAG: ![[IntTask:.*]] = !cir.struct<"folly::coro::Task<int>" padded {!u8i}>
|
||||
Loading…
Reference in a new issue