brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.3 KiB · f36f899 Raw
115 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O1 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s2 3#include "Inputs/coroutine.h"4 5struct Task {6  struct promise_type {7    Task get_return_object() noexcept {8      return Task{std::coroutine_handle<promise_type>::from_promise(*this)};9    }10 11    void return_void() noexcept {}12 13    struct final_awaiter {14      bool await_ready() noexcept { return false; }15      std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> h) noexcept {16        h.destroy();17        return {};18      }19      void await_resume() noexcept {}20    };21 22    void unhandled_exception() noexcept {}23 24    final_awaiter final_suspend() noexcept { return {}; }25 26    std::suspend_always initial_suspend() noexcept { return {}; }27 28    template <typename Awaitable>29    auto await_transform(Awaitable &&awaitable) {30      return awaitable.co_viaIfAsync();31    }32  };33 34  using handle_t = std::coroutine_handle<promise_type>;35 36  class Awaiter {37  public:38    explicit Awaiter(handle_t coro) noexcept;39    Awaiter(Awaiter &&other) noexcept;40    Awaiter(const Awaiter &) = delete;41    ~Awaiter();42 43    bool await_ready() noexcept { return false; }44    handle_t await_suspend(std::coroutine_handle<> continuation) noexcept;45    void await_resume();46 47  private:48    handle_t coro_;49  };50 51  Task(handle_t coro) noexcept : coro_(coro) {}52 53  handle_t coro_;54 55  Task(const Task &t) = delete;56  Task(Task &&t) noexcept;57  ~Task();58  Task &operator=(Task t) noexcept;59 60  Awaiter co_viaIfAsync();61};62 63static Task foo() {64  co_return;65}66 67Task bar() {68  auto mode = 2;69  switch (mode) {70  case 1:71    co_await foo();72    break;73  case 2:74    co_await foo();75    break;76  default:77    break;78  }79}80 81// CHECK-LABEL: define{{.*}} void @_Z3barv82// CHECK:         %[[MODE:.+]] = load i32, ptr %mode83// CHECK-NEXT:    switch i32 %[[MODE]], label %{{.+}} [84// CHECK-NEXT:      i32 1, label %[[CASE1:.+]]85// CHECK-NEXT:      i32 2, label %[[CASE2:.+]]86// CHECK-NEXT:    ]87 88// CHECK:       [[CASE1]]:89// CHECK:         br i1 %{{.+}}, label %[[CASE1_AWAIT_READY:.+]], label %[[CASE1_AWAIT_SUSPEND:.+]]90// CHECK:       [[CASE1_AWAIT_SUSPEND]]:91// CHECK-NEXT:    %{{.+}} = call token @llvm.coro.save(ptr null)92// CHECK-NEXT:    call void @llvm.coro.await.suspend.handle93// CHECK-NEXT:    %{{.+}} = call i8 @llvm.coro.suspend94// CHECK-NEXT:    switch i8 %{{.+}}, label %coro.ret [95// CHECK-NEXT:      i8 0, label %[[CASE1_AWAIT_READY]]96// CHECK-NEXT:      i8 1, label %[[CASE1_AWAIT_CLEANUP:.+]]97// CHECK-NEXT:    ]98// CHECK:       [[CASE1_AWAIT_CLEANUP]]:99// make sure that the awaiter eventually gets cleaned up.100// CHECK:         call void @{{.+Awaiter.+}}101 102// CHECK:       [[CASE2]]:103// CHECK:         br i1 %{{.+}}, label %[[CASE2_AWAIT_READY:.+]], label %[[CASE2_AWAIT_SUSPEND:.+]]104// CHECK:       [[CASE2_AWAIT_SUSPEND]]:105// CHECK-NEXT:    %{{.+}} = call token @llvm.coro.save(ptr null)106// CHECK-NEXT:    call void @llvm.coro.await.suspend.handle107// CHECK-NEXT:    %{{.+}} = call i8 @llvm.coro.suspend108// CHECK-NEXT:    switch i8 %{{.+}}, label %coro.ret [109// CHECK-NEXT:      i8 0, label %[[CASE2_AWAIT_READY]]110// CHECK-NEXT:      i8 1, label %[[CASE2_AWAIT_CLEANUP:.+]]111// CHECK-NEXT:    ]112// CHECK:       [[CASE2_AWAIT_CLEANUP]]:113// make sure that the awaiter eventually gets cleaned up.114// CHECK:         call void @{{.+Awaiter.+}}115