summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2022-10-12 17:11:07 -0700
committerGravatar GitHub2022-10-12 17:11:07 -0700
commit64c2ccb0cbd41bfdeaddfd33c1da18446c6879fb (patch)
tree8291538cd7e917169699609a0539cf62bf9c0c70
parentMerge pull request #9027 from yuzu-emu/revert-8987-another-name-for-reinforce... (diff)
parentkernel: add expanded result macros (diff)
downloadyuzu-64c2ccb0cbd41bfdeaddfd33c1da18446c6879fb.tar.gz
yuzu-64c2ccb0cbd41bfdeaddfd33c1da18446c6879fb.tar.xz
yuzu-64c2ccb0cbd41bfdeaddfd33c1da18446c6879fb.zip
Merge pull request #9034 from liamwhite/result-macros
kernel: add expanded result macros
-rw-r--r--src/core/hle/result.h120
1 files changed, 114 insertions, 6 deletions
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 47a1b829b..e20e0bfee 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -5,6 +5,7 @@
5 5
6#include "common/assert.h" 6#include "common/assert.h"
7#include "common/bit_field.h" 7#include "common/bit_field.h"
8#include "common/common_funcs.h"
8#include "common/common_types.h" 9#include "common/common_types.h"
9#include "common/expected.h" 10#include "common/expected.h"
10 11
@@ -130,6 +131,10 @@ union Result {
130 [[nodiscard]] constexpr bool IsError() const { 131 [[nodiscard]] constexpr bool IsError() const {
131 return !IsSuccess(); 132 return !IsSuccess();
132 } 133 }
134
135 [[nodiscard]] constexpr bool IsFailure() const {
136 return !IsSuccess();
137 }
133}; 138};
134static_assert(std::is_trivial_v<Result>); 139static_assert(std::is_trivial_v<Result>);
135 140
@@ -349,10 +354,110 @@ private:
349 } \ 354 } \
350 } while (false) 355 } while (false)
351 356
352#define R_SUCCEEDED(res) (res.IsSuccess()) 357#define R_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess())
358#define R_FAILED(res) (static_cast<Result>(res).IsFailure())
353 359
354/// Evaluates a boolean expression, and succeeds if that expression is true. 360namespace ResultImpl {
355#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess) 361template <auto EvaluateResult, class F>
362class ScopedResultGuard {
363 YUZU_NON_COPYABLE(ScopedResultGuard);
364 YUZU_NON_MOVEABLE(ScopedResultGuard);
365
366private:
367 Result& m_ref;
368 F m_f;
369
370public:
371 constexpr ScopedResultGuard(Result& ref, F f) : m_ref(ref), m_f(std::move(f)) {}
372 constexpr ~ScopedResultGuard() {
373 if (EvaluateResult(m_ref)) {
374 m_f();
375 }
376 }
377};
378
379template <auto EvaluateResult>
380class ResultReferenceForScopedResultGuard {
381private:
382 Result& m_ref;
383
384public:
385 constexpr ResultReferenceForScopedResultGuard(Result& r) : m_ref(r) {}
386 constexpr operator Result&() const {
387 return m_ref;
388 }
389};
390
391template <auto EvaluateResult, typename F>
392constexpr ScopedResultGuard<EvaluateResult, F> operator+(
393 ResultReferenceForScopedResultGuard<EvaluateResult> ref, F&& f) {
394 return ScopedResultGuard<EvaluateResult, F>(static_cast<Result&>(ref), std::forward<F>(f));
395}
396
397constexpr bool EvaluateResultSuccess(const Result& r) {
398 return R_SUCCEEDED(r);
399}
400constexpr bool EvaluateResultFailure(const Result& r) {
401 return R_FAILED(r);
402}
403
404template <typename T>
405constexpr void UpdateCurrentResultReference(T result_reference, Result result) {
406 ASSERT(false);
407}
408
409template <>
410constexpr void UpdateCurrentResultReference<Result&>(Result& result_reference, Result result) {
411 result_reference = result;
412}
413
414template <>
415constexpr void UpdateCurrentResultReference<Result>(Result result_reference, Result result) {}
416} // namespace ResultImpl
417
418#define DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(COUNTER_VALUE) \
419 [[maybe_unused]] constexpr bool HasPrevRef_##COUNTER_VALUE = \
420 std::same_as<decltype(__TmpCurrentResultReference), Result&>; \
421 [[maybe_unused]] auto& PrevRef_##COUNTER_VALUE = __TmpCurrentResultReference; \
422 [[maybe_unused]] Result __tmp_result_##COUNTER_VALUE = ResultSuccess; \
423 Result& __TmpCurrentResultReference = \
424 HasPrevRef_##COUNTER_VALUE ? PrevRef_##COUNTER_VALUE : __tmp_result_##COUNTER_VALUE
425
426#define ON_RESULT_RETURN_IMPL(...) \
427 static_assert(std::same_as<decltype(__TmpCurrentResultReference), Result&>); \
428 auto RESULT_GUARD_STATE_##__COUNTER__ = \
429 ResultImpl::ResultReferenceForScopedResultGuard<__VA_ARGS__>( \
430 __TmpCurrentResultReference) + \
431 [&]()
432
433#define ON_RESULT_FAILURE_2 ON_RESULT_RETURN_IMPL(ResultImpl::EvaluateResultFailure)
434
435#define ON_RESULT_FAILURE \
436 DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__); \
437 ON_RESULT_FAILURE_2
438
439#define ON_RESULT_SUCCESS_2 ON_RESULT_RETURN_IMPL(ResultImpl::EvaluateResultSuccess)
440
441#define ON_RESULT_SUCCESS \
442 DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__); \
443 ON_RESULT_SUCCESS_2
444
445constexpr inline Result __TmpCurrentResultReference = ResultSuccess;
446
447/// Returns a result.
448#define R_RETURN(res_expr) \
449 { \
450 const Result _tmp_r_throw_rc = (res_expr); \
451 ResultImpl::UpdateCurrentResultReference<decltype(__TmpCurrentResultReference)>( \
452 __TmpCurrentResultReference, _tmp_r_throw_rc); \
453 return _tmp_r_throw_rc; \
454 }
455
456/// Returns ResultSuccess()
457#define R_SUCCEED() R_RETURN(ResultSuccess)
458
459/// Throws a result.
460#define R_THROW(res_expr) R_RETURN(res_expr)
356 461
357/// Evaluates a boolean expression, and returns a result unless that expression is true. 462/// Evaluates a boolean expression, and returns a result unless that expression is true.
358#define R_UNLESS(expr, res) \ 463#define R_UNLESS(expr, res) \
@@ -361,7 +466,7 @@ private:
361 if (res.IsError()) { \ 466 if (res.IsError()) { \
362 LOG_ERROR(Kernel, "Failed with result: {}", res.raw); \ 467 LOG_ERROR(Kernel, "Failed with result: {}", res.raw); \
363 } \ 468 } \
364 return res; \ 469 R_THROW(res); \
365 } \ 470 } \
366 } 471 }
367 472
@@ -369,7 +474,10 @@ private:
369#define R_TRY(res_expr) \ 474#define R_TRY(res_expr) \
370 { \ 475 { \
371 const auto _tmp_r_try_rc = (res_expr); \ 476 const auto _tmp_r_try_rc = (res_expr); \
372 if (_tmp_r_try_rc.IsError()) { \ 477 if (R_FAILED(_tmp_r_try_rc)) { \
373 return _tmp_r_try_rc; \ 478 R_THROW(_tmp_r_try_rc); \
374 } \ 479 } \
375 } 480 }
481
482/// Evaluates a boolean expression, and succeeds if that expression is true.
483#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess)