From 89c0c29c779e307d77f237407e126436f4aaace7 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 29 Oct 2025 06:49:10 +0000 Subject: [PATCH] replace weird asserts with unreachables Signed-off-by: lizzie --- .../src/dynarmic/backend/arm64/emit_arm64.cpp | 3 +- .../dynarmic/backend/riscv64/emit_riscv64.cpp | 3 +- .../backend/riscv64/emit_riscv64_a32.cpp | 3 +- .../src/dynarmic/backend/x64/a32_emit_x64.cpp | 3 +- .../src/dynarmic/backend/x64/a64_emit_x64.cpp | 6 +-- .../dynarmic/backend/x64/block_of_code.cpp | 3 +- .../src/dynarmic/backend/x64/emit_x64.cpp | 2 +- .../backend/x64/emit_x64_data_processing.cpp | 2 +- .../src/dynarmic/backend/x64/reg_alloc.cpp | 23 ++------- src/dynarmic/src/dynarmic/common/assert.cpp | 6 +-- src/dynarmic/src/dynarmic/common/assert.h | 51 +++++-------------- .../frontend/A64/translate/impl/impl.cpp | 18 +++---- .../src/dynarmic/ir/microinstruction.cpp | 6 ++- .../src/dynarmic/ir/microinstruction.h | 6 ++- src/dynarmic/src/dynarmic/ir/opt_passes.cpp | 2 +- 15 files changed, 43 insertions(+), 94 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64.cpp index ebdc3cc3d4..fb48e73bc6 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64.cpp @@ -241,8 +241,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E #undef A32OPC #undef A64OPC default: - ASSERT(false && "Invalid opcode: {:x}", std::size_t(inst->GetOpcode())); - break; + UNREACHABLE(); } reg_alloc.UpdateAllUses(); diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp index 71d3120b2b..bc94fda91a 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp @@ -143,8 +143,7 @@ EmittedBlockInfo EmitRV64(biscuit::Assembler& as, IR::Block block, const EmitCon #undef A32OPC #undef A64OPC default: - ASSERT(false && "Invalid opcode: {:x}", std::size_t(inst->GetOpcode())); - break; + UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64_a32.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64_a32.cpp index 2b72213be8..532ad7d5a6 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64_a32.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64_a32.cpp @@ -105,8 +105,7 @@ void EmitA32Cond(biscuit::Assembler& as, EmitContext&, IR::Cond cond, biscuit::L as.BNEZ(Xscratch0, label); break; default: - ASSERT(false && "Unknown cond {}", static_cast(cond)); - break; + UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp index b588b2bfeb..c9c8da10ea 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp @@ -144,7 +144,8 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) { #undef OPCODE #undef A32OPC #undef A64OPC - default: [[unlikely]] ASSERT(false && "Invalid opcode: {:x}", std::size_t(inst->GetOpcode())); + default: + UNREACHABLE(); } reg_alloc.EndOfAllocScope(); func(reg_alloc); diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp index ab3556142a..79ee56b3dd 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp @@ -129,10 +129,8 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) noexcept { #undef OPCODE #undef A32OPC #undef A64OPC - default: [[unlikely]] { - ASSERT(false && "Invalid opcode: {:x}", std::size_t(opcode)); - goto finish_this_inst; - } + default: + UNREACHABLE(); } opcode_branch: (this->*opcode_handlers[size_t(opcode)])(ctx, &inst); diff --git a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp index b41703fd34..8dfe84b37c 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp @@ -507,8 +507,7 @@ void BlockOfCode::LoadRequiredFlagsForCondFromRax(IR::Cond cond) { case IR::Cond::NV: break; default: - ASSERT(false && "Unknown cond {}", static_cast(cond)); - break; + UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp index d0b94f69d9..0160e8ab78 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp @@ -59,7 +59,7 @@ std::optional EmitX64::GetBasicBlock(IR::LocationDescr } void EmitX64::EmitInvalid(EmitContext&, IR::Inst* inst) { - ASSERT(false && "Invalid opcode: {:x}", std::size_t(inst->GetOpcode())); + UNREACHABLE(); } void EmitX64::EmitVoid(EmitContext&, IR::Inst*) { diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp index 639a489f61..dfc09da173 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp @@ -195,7 +195,7 @@ static void EmitConditionalSelect(BlockOfCode& code, EmitContext& ctx, IR::Inst* code.mov(else_, then_); break; default: - ASSERT(false && "Invalid cond {}", static_cast(args[0].GetImmediateCond())); + UNREACHABLE(); } ctx.reg_alloc.DefineValue(inst, else_); diff --git a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp index 6564607552..587152ad53 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp @@ -40,18 +40,6 @@ static inline bool CanExchange(const HostLoc a, const HostLoc b) noexcept { // Minimum number of bits required to represent a type static inline size_t GetBitWidth(const IR::Type type) noexcept { switch (type) { - case IR::Type::A32Reg: - case IR::Type::A32ExtReg: - case IR::Type::A64Reg: - case IR::Type::A64Vec: - case IR::Type::CoprocInfo: - case IR::Type::Cond: - case IR::Type::Void: - case IR::Type::Table: - case IR::Type::AccType: - ASSERT(false && "Type {} cannot be represented at runtime", type); - case IR::Type::Opaque: - ASSERT(false && "Not a concrete type"); case IR::Type::U1: return 8; case IR::Type::U8: @@ -66,17 +54,14 @@ static inline size_t GetBitWidth(const IR::Type type) noexcept { return 128; case IR::Type::NZCVFlags: return 32; // TODO: Update to 16 when flags optimization is done + default: + // A32REG A32EXTREG A64REG A64VEC COPROCINFO COND VOID TABLE ACCTYPE OPAQUE + UNREACHABLE(); } - UNREACHABLE(); } static inline bool IsValuelessType(const IR::Type type) noexcept { - switch (type) { - case IR::Type::Table: - return true; - default: - return false; - } + return type == IR::Type::Table; } void HostLocInfo::ReleaseOne() noexcept { diff --git a/src/dynarmic/src/dynarmic/common/assert.cpp b/src/dynarmic/src/dynarmic/common/assert.cpp index 84a398f23e..e3419514e8 100644 --- a/src/dynarmic/src/dynarmic/common/assert.cpp +++ b/src/dynarmic/src/dynarmic/common/assert.cpp @@ -3,13 +3,11 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include #include -[[noreturn]] void assert_terminate_impl(const char* expr_str, fmt::string_view msg, fmt::format_args args) { - fmt::print(stderr, "assertion failed: {}\n", expr_str); - fmt::vprint(stderr, msg, args); +[[noreturn]] void assert_terminate_impl(const char* s) { + std::puts(s); std::fflush(stderr); std::terminate(); } diff --git a/src/dynarmic/src/dynarmic/common/assert.h b/src/dynarmic/src/dynarmic/common/assert.h index de889dfa7c..ee9bbeba16 100644 --- a/src/dynarmic/src/dynarmic/common/assert.h +++ b/src/dynarmic/src/dynarmic/common/assert.h @@ -6,48 +6,21 @@ #pragma once -#include - -[[noreturn]] void assert_terminate_impl(const char* expr_str, fmt::string_view msg, fmt::format_args args); -template -[[noreturn]] void assert_terminate(const char* expr_str, fmt::string_view msg, Ts... args) { - assert_terminate_impl(expr_str, msg, fmt::make_format_args(args...)); -} - -// Temporary until MCL is fully removed -#ifndef ASSERT_MSG -#define ASSERT_MSG(_a_, ...) \ - ([&]() { \ - if (!(_a_)) [[unlikely]] { \ - assert_terminate(#_a_, __VA_ARGS__); \ - } \ - }()) -#endif -#ifndef ASSERT_FALSE -#define ASSERT_FALSE(...) \ - ([&]() { \ - assert_terminate("false", __VA_ARGS__); \ - }()) -#endif - +[[noreturn]] void assert_terminate_impl(const char* s); #ifndef ASSERT -#define ASSERT(_a_) ASSERT(_a_ && "") +# define ASSERT(expr) do if(!(expr)) [[unlikely]] assert_terminate_impl(#expr); while(0) #endif #ifndef UNREACHABLE -#define UNREACHABLE() ASSERT(false && "unreachable") +# ifdef _MSC_VER +# define UNREACHABLE() ASSERT_FALSE("unreachable") +# else +# define UNREACHABLE() __builtin_unreachable(); +# endif #endif -#ifdef _DEBUG #ifndef DEBUG_ASSERT -#define DEBUG_ASSERT(_a_) ASSERT(_a_) -#endif -#ifndef DEBUG_ASSERT_MSG -#define DEBUG_ASSERT_MSG(_a_, ...) ASSERT_MSG(_a_, __VA_ARGS__) -#endif -#else // not debug -#ifndef DEBUG_ASSERT -#define DEBUG_ASSERT(_a_) -#endif -#ifndef DEBUG_ASSERT_MSG -#define DEBUG_ASSERT_MSG(_a_, _desc_, ...) -#endif +# ifdef _DEBUG +# define DEBUG_ASSERT(_a_) ASSERT(_a_) +# else +# define DEBUG_ASSERT(_a_) +# endif #endif diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp index b4f198b189..6320523b87 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp @@ -232,9 +232,8 @@ IR::UAnyU128 TranslatorVisitor::Mem(IR::U64 address, size_t bytesize, IR::AccTyp return ir.ReadMemory64(address, acc_type); case 16: return ir.ReadMemory128(address, acc_type); - default: - ASSERT(false && "Invalid bytesize parameter {}", bytesize); } + UNREACHABLE(); } void TranslatorVisitor::Mem(IR::U64 address, size_t bytesize, IR::AccType acc_type, IR::UAnyU128 value) { @@ -254,9 +253,8 @@ void TranslatorVisitor::Mem(IR::U64 address, size_t bytesize, IR::AccType acc_ty case 16: ir.WriteMemory128(address, value, acc_type); return; - default: - ASSERT(false && "Invalid bytesize parameter {}", bytesize); } + UNREACHABLE(); } IR::UAnyU128 TranslatorVisitor::ExclusiveMem(IR::U64 address, size_t bytesize, IR::AccType acc_type) { @@ -271,9 +269,8 @@ IR::UAnyU128 TranslatorVisitor::ExclusiveMem(IR::U64 address, size_t bytesize, I return ir.ExclusiveReadMemory64(address, acc_type); case 16: return ir.ExclusiveReadMemory128(address, acc_type); - default: - ASSERT(false && "Invalid bytesize parameter {}", bytesize); } + UNREACHABLE(); } IR::U32 TranslatorVisitor::ExclusiveMem(IR::U64 address, size_t bytesize, IR::AccType acc_type, IR::UAnyU128 value) { @@ -288,9 +285,8 @@ IR::U32 TranslatorVisitor::ExclusiveMem(IR::U64 address, size_t bytesize, IR::Ac return ir.ExclusiveWriteMemory64(address, value, acc_type); case 16: return ir.ExclusiveWriteMemory128(address, value, acc_type); - default: - ASSERT(false && "Invalid bytesize parameter {}", bytesize); } + UNREACHABLE(); } IR::U32U64 TranslatorVisitor::SignExtend(IR::UAny value, size_t to_size) { @@ -299,9 +295,8 @@ IR::U32U64 TranslatorVisitor::SignExtend(IR::UAny value, size_t to_size) { return ir.SignExtendToWord(value); case 64: return ir.SignExtendToLong(value); - default: - ASSERT(false && "Invalid size parameter {}", to_size); } + UNREACHABLE(); } IR::U32U64 TranslatorVisitor::ZeroExtend(IR::UAny value, size_t to_size) { @@ -310,9 +305,8 @@ IR::U32U64 TranslatorVisitor::ZeroExtend(IR::UAny value, size_t to_size) { return ir.ZeroExtendToWord(value); case 64: return ir.ZeroExtendToLong(value); - default: - ASSERT(false && "Invalid size parameter {}", to_size); } + UNREACHABLE(); } IR::U32U64 TranslatorVisitor::ShiftReg(size_t bitsize, Reg reg, Imm<2> shift, IR::U8 amount) { diff --git a/src/dynarmic/src/dynarmic/ir/microinstruction.cpp b/src/dynarmic/src/dynarmic/ir/microinstruction.cpp index 8812bf3663..cc555474ef 100644 --- a/src/dynarmic/src/dynarmic/ir/microinstruction.cpp +++ b/src/dynarmic/src/dynarmic/ir/microinstruction.cpp @@ -42,8 +42,10 @@ Type Inst::GetType() const { } void Inst::SetArg(size_t index, Value value) noexcept { - DEBUG_ASSERT(index < GetNumArgsOf(op) && "Inst::SetArg: index {} >= number of arguments of {} ({})", index, op, GetNumArgsOf(op)); - DEBUG_ASSERT(AreTypesCompatible(value.GetType(), GetArgTypeOf(op, index)) && "Inst::SetArg: type {} of argument {} not compatible with operation {} ({})", value.GetType(), index, op, GetArgTypeOf(op, index)); + DEBUG_ASSERT(index < GetNumArgsOf(op)); + DEBUG_ASSERT(AreTypesCompatible(value.GetType(), GetArgTypeOf(op, index))); + //DEBUG_ASSERT(index < GetNumArgsOf(op) && "Inst::SetArg: index {} >= number of arguments of {} ({})", index, op, GetNumArgsOf(op)); + //DEBUG_ASSERT(AreTypesCompatible(value.GetType(), GetArgTypeOf(op, index)) && "Inst::SetArg: type {} of argument {} not compatible with operation {} ({})", value.GetType(), index, op, GetArgTypeOf(op, index)); if (!args[index].IsImmediate()) { UndoUse(args[index]); } diff --git a/src/dynarmic/src/dynarmic/ir/microinstruction.h b/src/dynarmic/src/dynarmic/ir/microinstruction.h index 094fc9cd83..7c7031b7c0 100644 --- a/src/dynarmic/src/dynarmic/ir/microinstruction.h +++ b/src/dynarmic/src/dynarmic/ir/microinstruction.h @@ -53,8 +53,10 @@ public: } inline Value GetArg(size_t index) const noexcept { - DEBUG_ASSERT(index < GetNumArgsOf(op) && "Inst::GetArg: index {} >= number of arguments of {} ({})", index, op, GetNumArgsOf(op)); - DEBUG_ASSERT(!args[index].IsEmpty() || GetArgTypeOf(op, index) == IR::Type::Opaque && "Inst::GetArg: index {} is empty", index, args[index].GetType()); + DEBUG_ASSERT(index < GetNumArgsOf(op)); + DEBUG_ASSERT(!args[index].IsEmpty() || GetArgTypeOf(op, index) == IR::Type::Opaque); + //DEBUG_ASSERT(index < GetNumArgsOf(op) && "Inst::GetArg: index {} >= number of arguments of {} ({})", index, op, GetNumArgsOf(op)); + //DEBUG_ASSERT(!args[index].IsEmpty() || GetArgTypeOf(op, index) == IR::Type::Opaque && "Inst::GetArg: index {} is empty", index, args[index].GetType()); return args[index]; } void SetArg(size_t index, Value value) noexcept; diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp index a557eb5123..6cb0abc4ef 100644 --- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp @@ -1466,7 +1466,7 @@ static void VerificationPass(const IR::Block& block) { for (size_t i = 0; i < inst.NumArgs(); i++) { const IR::Type t1 = inst.GetArg(i).GetType(); const IR::Type t2 = IR::GetArgTypeOf(inst.GetOpcode(), i); - ASSERT(IR::AreTypesCompatible(t1, t2) && "Block failed:\n{}", IR::DumpBlock(block)); + ASSERT(IR::AreTypesCompatible(t1, t2)); } } ankerl::unordered_dense::map actual_uses;