public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jason Merrill <jason@redhat.com>
To: Iain Sandoe <iain@sandoe.co.uk>, GCC Patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH v2] coroutines: Accept 'extern "C"' coroutines.
Date: Mon, 19 Dec 2022 10:54:20 -0500	[thread overview]
Message-ID: <bf9402ed-f142-10ac-dc59-d99500b0937e@redhat.com> (raw)
In-Reply-To: <0FD0D3D2-EB28-41DD-9F08-BD8BB267F238@sandoe.co.uk>

On 12/17/22 08:40, Iain Sandoe wrote:
> Hi.
> 
> It seems that everyone agrees that extern C coroutines should be permitted,
> although I have yet to see a useful testcase.
> 
> This patch has been revised to append the suffices for such functions in
> mangle.cc rather than as part of the outlined function decl production.
> 
> tested on x86_64-darwin21.
> OK for trunk?
> Iain

OK, thanks.

> 
> — 8< —
> 
> 'extern "C"' coroutines are permitted by the standard and expected to work
> (although constructing useful cases could be challenging). In order to
> permit this we need to arrange for the outlined helper functions to be
> named properly, even when no mangling is required.  To do this, we append
> the actor and destroy suffixes in all cases.
> 
> Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
> 
> gcc/cp/ChangeLog:
> 
> 	* mangle.cc (write_mangled_name): Append the helper function
> 	suffixes here...
> 	(write_encoding): ... rather than here.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/coroutines/torture/extern-c-coroutine.C: New test.
> ---
>   gcc/cp/mangle.cc                              | 23 ++---
>   .../coroutines/torture/extern-c-coroutine.C   | 89 +++++++++++++++++++
>   2 files changed, 101 insertions(+), 11 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/coroutines/torture/extern-c-coroutine.C
> 
> diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
> index 074cf27ec7a..5789adcf680 100644
> --- a/gcc/cp/mangle.cc
> +++ b/gcc/cp/mangle.cc
> @@ -805,6 +805,18 @@ write_mangled_name (const tree decl, bool top_level)
>       write_string (".pre");
>     else if (DECL_IS_POST_FN_P (decl))
>       write_string (".post");
> +
> +  /* If this is a coroutine helper, then append an appropriate string to
> +     identify which.  */
> +  if (tree ramp = DECL_RAMP_FN (decl))
> +    {
> +      if (DECL_ACTOR_FN (ramp) == decl)
> +	write_string (JOIN_STR "actor");
> +      else if (DECL_DESTROY_FN (ramp) == decl)
> +	write_string (JOIN_STR "destroy");
> +      else
> +	gcc_unreachable ();
> +    }
>   }
>   
>   /* Returns true if the return type of DECL is part of its signature, and
> @@ -863,17 +875,6 @@ write_encoding (const tree decl)
>   				mangle_return_type_p (decl),
>   				d);
>   
> -      /* If this is a coroutine helper, then append an appropriate string to
> -	 identify which.  */
> -      if (tree ramp = DECL_RAMP_FN (decl))
> -	{
> -	  if (DECL_ACTOR_FN (ramp) == decl)
> -	    write_string (JOIN_STR "actor");
> -	  else if (DECL_DESTROY_FN (ramp) == decl)
> -	    write_string (JOIN_STR "destroy");
> -	  else
> -	    gcc_unreachable ();
> -	}
>       }
>   }
>   
> diff --git a/gcc/testsuite/g++.dg/coroutines/torture/extern-c-coroutine.C b/gcc/testsuite/g++.dg/coroutines/torture/extern-c-coroutine.C
> new file mode 100644
> index 00000000000..c178a80ee4b
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/coroutines/torture/extern-c-coroutine.C
> @@ -0,0 +1,89 @@
> +#include <coroutine>
> +#include <cstdio>
> +
> +#ifndef OUTPUT
> +#  define PRINT(X)
> +#  define PRINTF(X,...)
> +#else
> +#  define PRINT(X) puts(X)
> +#  define PRINTF printf
> +#endif
> +
> +struct future {
> +  struct promise_type;
> +  using handle_type = std::coroutine_handle<future::promise_type>;
> +  handle_type handle;
> +  future () : handle(0) {}
> +  future (handle_type _handle)
> +    : handle(_handle) {
> +        PRINT("Created future object from handle");
> +  }
> +  future (const future &) = delete; // no copying
> +  future (future &&s) : handle(s.handle) {
> +	s.handle = nullptr;
> +	PRINT("future mv ctor ");
> +  }
> +  future &operator = (future &&s) {
> +	handle = s.handle;
> +	s.handle = nullptr;
> +	PRINT("future op=  ");
> +	return *this;
> +  }
> +  ~future() {
> +        PRINT("Destroyed future");
> +        if ( handle )
> +          handle.destroy();
> +  }
> +
> +  struct promise_type {
> +    void return_value (int v) {
> +      PRINTF ("return_value (%d)\n", v);
> +      vv = v;
> +    }
> +
> +    std::suspend_always initial_suspend() noexcept { return {}; }
> +    std::suspend_always final_suspend() noexcept { return {}; }
> +    void unhandled_exception() {}
> +    auto get_return_object() {return handle_type::from_promise (*this);}
> +
> +    int get_value () { return vv; }
> +  private:
> +    int vv;
> +  };
> +  bool await_ready() { return false; }
> +  void await_suspend(std::coroutine_handle<>) {}
> +  void await_resume() {}
> +};
> +
> +extern "C" future
> +test () {
> +  co_return 22;
> +}
> +
> +extern "C" future
> +f () noexcept
> +{
> +  PRINT ("future: about to return");
> +  co_return 42;
> +}
> +
> +int main ()
> +{
> +  PRINT ("main: create future");
> +  future x = f ();
> +  PRINT ("main: got future - resuming");
> +  if (x.handle.done())
> +    __builtin_abort ();
> +  x.handle.resume();
> +  PRINT ("main: after resume");
> +  int y = x.handle.promise().get_value();
> +  if ( y != 42 )
> +    __builtin_abort ();
> +  if (!x.handle.done())
> +    {
> +      PRINT ("main: apparently not done...");
> +      __builtin_abort ();
> +    }
> +  PRINT ("main: returning");
> +  return 0;
> +}


      reply	other threads:[~2022-12-19 15:54 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-10 11:37 [PATCH] " Iain Sandoe
2022-12-17 13:40 ` [PATCH v2] " Iain Sandoe
2022-12-19 15:54   ` Jason Merrill [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bf9402ed-f142-10ac-dc59-d99500b0937e@redhat.com \
    --to=jason@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=iain@sandoe.co.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).