diff --git a/cmake/unifex_env.cmake b/cmake/unifex_env.cmake index b26aed1b..41b527ff 100644 --- a/cmake/unifex_env.cmake +++ b/cmake/unifex_env.cmake @@ -21,7 +21,7 @@ endif() if (UNIFEX_CXX_COMPILER_MSVC) # warning level 3 and all warnings as errors - add_compile_options(/W3 /WX) + add_compile_options(/W3 /WX /bigobj) else() # lots of warnings and all warnings as errors add_compile_options(-Wall -Wextra -pedantic -Werror) diff --git a/examples/fp_delegation.cpp b/examples/fp_delegation.cpp index eb010d0d..f7dc808e 100644 --- a/examples/fp_delegation.cpp +++ b/examples/fp_delegation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License Version 2.0 with LLVM Exceptions * (the "License"); you may not use this file except in compliance with @@ -13,6 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#if defined(_MSC_VER) && !defined(__clang__) +// async stacks break this file when building with MSVC; we can probably fix it +// by switching the implementation to use unifex::variant_sender, but that's a +// post-CppCon problem +# define UNIFEX_NO_ASYNC_STACKS 1 +#endif #include #include @@ -135,7 +141,7 @@ class delegating_sender { auto local_op = [&receiver, context = context_]() mutable { return LC{unifex::connect( unifex::schedule(context->single_thread_context_.get_scheduler()), - (Receiver &&) receiver)}; + (Receiver&&)receiver)}; }; return op{std::move(local_op), context_}; } @@ -143,7 +149,7 @@ class delegating_sender { auto target_op = [&receiver]() mutable { return unifex::connect( unifex::schedule(unifex::get_scheduler(std::as_const(receiver))), - (Receiver &&) receiver); + (Receiver&&)receiver); }; return op{std::move(target_op), context_}; diff --git a/include/unifex/await_transform.hpp b/include/unifex/await_transform.hpp index e0d08ed2..6712f513 100644 --- a/include/unifex/await_transform.hpp +++ b/include/unifex/await_transform.hpp @@ -387,10 +387,9 @@ class _awaitable_wrapper::type final { coro::coroutine_handle<>, _suspend_result_t>; - template(typename Promise) // - (requires same_as>) // - bool await_suspend_impl( - coro::coroutine_handle h, AsyncStackFrame* frame) { + template + bool await_suspend_bool( + coro::coroutine_handle h, AsyncStackFrame* frame) { auto* root = frame->getStackRoot(); auto resumer = resume_with_stack_root(h).handle(); @@ -418,10 +417,9 @@ class _awaitable_wrapper::type final { } } - template(typename Promise) // - (requires(!same_as>)) // - suspend_result_t await_suspend_impl( - coro::coroutine_handle h, AsyncStackFrame* frame) { + template + suspend_result_t await_suspend_impl( + coro::coroutine_handle h, AsyncStackFrame* frame) { auto resumer = resume_with_stack_root(h).handle(); // save for later destruction @@ -437,7 +435,11 @@ class _awaitable_wrapper::type final { template suspend_result_t await_suspend(coro::coroutine_handle h) { if (auto* frame = get_async_stack_frame(h.promise())) { - return await_suspend_impl(h, frame); + if constexpr (same_as>) { + return await_suspend_bool(h, frame); + } else { + return await_suspend_impl(h, frame); + } } using awaiter_suspend_result_t = decltype(awaiter_.await_suspend(h)); diff --git a/include/unifex/config.hpp b/include/unifex/config.hpp index 69a977ab..95d48327 100644 --- a/include/unifex/config.hpp +++ b/include/unifex/config.hpp @@ -301,13 +301,36 @@ #if !defined(UNIFEX_NO_ASYNC_STACKS) // default: // - release builds do not have async stacks -// - Windows builds do not have async stacks // -// adding async stacks adds non-trivial binary size at the moment, and I can't -// figure out how to make all the relevant Windows builds succeed -# if defined(NDEBUG) || defined(_MSC_VER) +// adding async stacks adds non-trivial binary size at the moment +# if defined(NDEBUG) # define UNIFEX_NO_ASYNC_STACKS 1 # else # define UNIFEX_NO_ASYNC_STACKS 0 # endif +#elif UNIFEX_NO_ASYNC_STACKS +// make sure the truthy value is 1 +# undef UNIFEX_NO_ASYNC_STACKS +# define UNIFEX_NO_ASYNC_STACKS 1 +#else +// make sure the falsey value is 0 +# undef UNIFEX_NO_ASYNC_STACKS +# define UNIFEX_NO_ASYNC_STACKS 0 #endif // !defined(UNIFEX_NO_ASYNC_STACKS) + +#if UNIFEX_HAS_BUILTIN(__builtin_return_address) +# define UNIFEX_RETURN_ADDRESS __builtin_return_address(0) +#elif defined(_MSC_VER) +# define UNIFEX_RETURN_ADDRESS _ReturnAddress() +#else +# define UNIFEX_RETURN_ADDRESS nullptr +#endif + +#if UNIFEX_HAS_BUILTIN(__builtin_frame_address) +# define UNIFEX_FRAME_ADDRESS __builtin_frame_address(0) +#elif defined(_MSC_VER) +// not sure, yet, that this is right, but it's where we're starting +# define UNIFEX_FRAME_ADDRESS _AddressOfReturnAddress() +#else +# define UNIFEX_FRAME_ADDRESS nullptr +#endif diff --git a/include/unifex/tracing/async_stack.hpp b/include/unifex/tracing/async_stack.hpp index ca52d394..e8b287fd 100644 --- a/include/unifex/tracing/async_stack.hpp +++ b/include/unifex/tracing/async_stack.hpp @@ -22,6 +22,11 @@ #include #include +#if defined(_MSC_VER) +// needed for _ReturnAddress() and _AddressOfReturnAddress() +#include +#endif + #include namespace unifex { @@ -273,13 +278,8 @@ struct instruction_ptr final { // Generally a function that uses this macro should be declared FOLLY_NOINLINE // to prevent this returning surprising results in cases where the function // is inlined. -#if UNIFEX_HAS_BUILTIN(__builtin_return_address) - static constexpr instruction_ptr - read_return_address(void* p = __builtin_return_address(0)) noexcept { -#else static constexpr instruction_ptr - read_return_address(void* p = nullptr) noexcept { -#endif + read_return_address(void* p = UNIFEX_RETURN_ADDRESS) noexcept { return instruction_ptr{p}; } @@ -311,12 +311,8 @@ struct frame_ptr { // Generally a function that uses this macro should be declared FOLLY_NOINLINE // to prevent this returning surprising results in cases where the function // is inlined. -#if UNIFEX_HAS_BUILTIN(__builtin_frame_address) static constexpr frame_ptr - read_frame_pointer(void* p = __builtin_frame_address(0)) noexcept { -#else - static constexpr frame_ptr read_frame_pointer(void* p = nullptr) noexcept { -#endif + read_frame_pointer(void* p = UNIFEX_FRAME_ADDRESS) noexcept { return frame_ptr{p}; }