[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cfe-commits
Subject:    [PATCH] D144680: [Coroutines] Avoid creating conditional cleanup markers in suspend block
From:       Wei Wang via Phabricator via cfe-commits <cfe-commits () lists ! llvm ! org>
Date:       2023-02-28 23:31:47
Message-ID: soeVEOC4QLOe8eRswNBl5A () geopod-ismtpd-11
[Download RAW message or body]

This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGce7eb2e05544: [Coroutines] Avoid creating conditional cl=
eanup markers in suspend block (authored by weiwang).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144680/new/

https://reviews.llvm.org/D144680

Files:
  clang/lib/CodeGen/CGCoroutine.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/test/CodeGenCoroutines/pr59181.cpp


["D144680.501311.patch" (D144680.501311.patch)]

Index: clang/test/CodeGenCoroutines/pr59181.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCoroutines/pr59181.cpp
@@ -0,0 +1,60 @@
+// Test for PR59181. Tests that no conditional cleanup is created around \
await_suspend. +//
+// REQUIRES: x86-registered-target
+//
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - -std=c++20 \
-disable-llvm-passes -fsanitize-address-use-after-scope | FileCheck %s +
+#include "Inputs/coroutine.h"
+
+struct Task {
+  int value_;
+  struct promise_type {
+    Task get_return_object() {
+      return Task{0};
+    }
+
+    std::suspend_never initial_suspend() noexcept {
+      return {};
+    }
+
+    std::suspend_never final_suspend() noexcept {
+      return {};
+    }
+
+    void return_value(Task t) noexcept {}
+    void unhandled_exception() noexcept {}
+
+    auto await_transform(Task t) {
+      struct Suspension {
+        auto await_ready() noexcept { return false;}
+        auto await_suspend(std::coroutine_handle<> coro) {
+          coro.destroy();
+        }
+
+        auto await_resume() noexcept {
+          return 0;
+        }
+      };
+      return Suspension{};
+    }
+  };
+};
+
+Task bar(bool cond) {
+  co_return cond ? Task{ co_await Task{}}: Task{};
+}
+
+void foo() {
+  bar(true);
+}
+
+// CHECK: cleanup.cont:{{.*}}
+// CHECK-NEXT: load i8
+// CHECK-NEXT: trunc
+// CHECK-NEXT: store i1 false
+// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF:%ref.tmp[0-9]+]])
+
+// CHECK: await.suspend:{{.*}}
+// CHECK-NOT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF]])
+// CHECK: call void \
@_ZZN4Task12promise_type15await_transformES_EN10Suspension13await_suspendESt16coroutine_handleIvE
 +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[REF]])
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -333,6 +333,7 @@
   // in this header.
   struct CGCoroInfo {
     std::unique_ptr<CGCoroData> Data;
+    bool InSuspendBlock = false;
     CGCoroInfo();
     ~CGCoroInfo();
   };
@@ -342,6 +343,10 @@
     return CurCoro.Data != nullptr;
   }
 
+  bool inSuspendBlock() const {
+    return isCoroutine() && CurCoro.InSuspendBlock;
+  }
+
   /// CurGD - The GlobalDecl for the current function being compiled.
   GlobalDecl CurGD;
 
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -541,13 +541,17 @@
       // Avoid creating a conditional cleanup just to hold an llvm.lifetime.end
       // marker. Instead, start the lifetime of a conditional temporary earlier
       // so that it's unconditional. Don't do this with sanitizers which need
-      // more precise lifetime marks.
+      // more precise lifetime marks. However when inside an "await.suspend"
+      // block, we should always avoid conditional cleanup because it creates
+      // boolean marker that lives across await_suspend, which can destroy coro
+      // frame.
       ConditionalEvaluation *OldConditional = nullptr;
       CGBuilderTy::InsertPoint OldIP;
       if (isInConditionalBranch() && !E->getType().isDestructedType() &&
-          !SanOpts.has(SanitizerKind::HWAddress) &&
-          !SanOpts.has(SanitizerKind::Memory) &&
-          !CGM.getCodeGenOpts().SanitizeAddressUseAfterScope) {
+          ((!SanOpts.has(SanitizerKind::HWAddress) &&
+            !SanOpts.has(SanitizerKind::Memory) &&
+            !CGM.getCodeGenOpts().SanitizeAddressUseAfterScope) ||
+           inSuspendBlock())) {
         OldConditional = OutermostConditional;
         OutermostConditional = nullptr;
 
Index: clang/lib/CodeGen/CGCoroutine.cpp
===================================================================
--- clang/lib/CodeGen/CGCoroutine.cpp
+++ clang/lib/CodeGen/CGCoroutine.cpp
@@ -198,7 +198,9 @@
   auto *NullPtr = llvm::ConstantPointerNull::get(CGF.CGM.Int8PtrTy);
   auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});
 
+  CGF.CurCoro.InSuspendBlock = true;
   auto *SuspendRet = CGF.EmitScalarExpr(S.getSuspendExpr());
+  CGF.CurCoro.InSuspendBlock = false;
   if (SuspendRet != nullptr && SuspendRet->getType()->isIntegerTy(1)) {
     // Veto suspension if requested by bool returning await_suspend.
     BasicBlock *RealSuspendBlock =


[Attachment #4 (text/plain)]

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic