diff --git a/decompiler/Disasm/InstructionParser.cpp b/decompiler/Disasm/InstructionParser.cpp index 4c6fd2d548..b3843495b9 100644 --- a/decompiler/Disasm/InstructionParser.cpp +++ b/decompiler/Disasm/InstructionParser.cpp @@ -43,7 +43,7 @@ InstructionParser::InstructionParser() { InstructionKind::BGTZ, InstructionKind::BLTZL, InstructionKind::BGTZL, InstructionKind::BGEZL, InstructionKind::MTC1, InstructionKind::MFC1, InstructionKind::MFLO, InstructionKind::MFHI, InstructionKind::MTLO1, - InstructionKind::MFLO1, InstructionKind::SYNCL}) { + InstructionKind::MFLO1, InstructionKind::SYNCL, InstructionKind::PCPYUD}) { auto& info = gOpcodeInfo[int(i)]; if (info.defined) { m_opcode_name_lookup[info.name] = int(i); diff --git a/decompiler/Function/CfgVtx.cpp b/decompiler/Function/CfgVtx.cpp index 1737d0cbdd..3a8723e8e0 100644 --- a/decompiler/Function/CfgVtx.cpp +++ b/decompiler/Function/CfgVtx.cpp @@ -1248,7 +1248,7 @@ bool ControlFlowGraph::find_cond_w_empty_else() { return true; } - // printf("cwe try %s %s\n", c0->to_string().c_str(), b0->to_string().c_str()); + // printf("cwe try %s %s\n", c0->to_string().c_str(), b0->to_string().c_str()); // first condition should have the _option_ to fall through to first body if (c0->succ_ft != b0 || c0->end_branch.kind != CfgVtx::DelaySlotKind::NOP) { @@ -1290,11 +1290,10 @@ bool ControlFlowGraph::find_cond_w_empty_else() { else_block = end_block; } - if (else_block->succ_branch) { - return true; - } - - assert(!else_block->end_branch.has_branch); + // the else code is empty, so the else block is the same as the end block. + // in this empty else case, we don't care what the "else" block end conditions are. + // else must fall through to end with no possible branch. + // it's not our problem to deal with the end block's branching.; std::vector entries = {{c0, b0}}; auto* prev_condition = c0; diff --git a/decompiler/Function/Function.h b/decompiler/Function/Function.h index 528cb4cf98..7dba655019 100644 --- a/decompiler/Function/Function.h +++ b/decompiler/Function/Function.h @@ -109,6 +109,7 @@ class Function { std::vector instructions; std::vector basic_blocks; std::shared_ptr cfg = nullptr; + bool cfg_ok = false; int prologue_start = -1; int prologue_end = -1; diff --git a/decompiler/ObjectFile/ObjectFileDB_IR2.cpp b/decompiler/ObjectFile/ObjectFileDB_IR2.cpp index 1af799a618..1099d7a35a 100644 --- a/decompiler/ObjectFile/ObjectFileDB_IR2.cpp +++ b/decompiler/ObjectFile/ObjectFileDB_IR2.cpp @@ -211,6 +211,8 @@ void ObjectFileDB::ir2_basic_block_pass() { lg::warn("Function {} from {} failed to build control flow graph!", func.guessed_name.to_string(), data.to_unique_name()); failed_to_build_cfg++; + } else { + func.cfg_ok = true; } } @@ -237,6 +239,9 @@ void ObjectFileDB::ir2_stack_spill_slot_pass() { int functions_with_spills = 0; int total_slots = 0; for_each_function_def_order([&](Function& func, int, ObjectFileData&) { + if (!func.cfg_ok) { + return; + } auto spill_map = build_spill_map(func.instructions, {func.prologue_end, func.epilogue_start}); auto map_size = spill_map.size(); if (map_size) { @@ -259,6 +264,9 @@ void ObjectFileDB::ir2_atomic_op_pass(const Config& config) { int attempted = 0; int successful = 0; for_each_function_def_order([&](Function& func, int segment_id, ObjectFileData& data) { + if (!func.cfg_ok) { + return; + } (void)segment_id; total_functions++; if (!func.suspected_asm) { diff --git a/test/decompiler/FormRegressionTest.cpp b/test/decompiler/FormRegressionTest.cpp index cb83f70c87..3b135f6cd7 100644 --- a/test/decompiler/FormRegressionTest.cpp +++ b/test/decompiler/FormRegressionTest.cpp @@ -153,6 +153,8 @@ std::unique_ptr FormRegressionTest::make_function( EXPECT_TRUE(test->func.cfg->is_fully_resolved()); if (!test->func.cfg->is_fully_resolved()) { fmt::print("CFG:\n{}\n", test->func.cfg->to_dot()); + } else { + test->func.cfg_ok = true; } // find stack spill slots diff --git a/test/decompiler/test_FormBeforeExpressions.cpp b/test/decompiler/test_FormBeforeExpressions.cpp index 334b81fadf..0404008369 100644 --- a/test/decompiler/test_FormBeforeExpressions.cpp +++ b/test/decompiler/test_FormBeforeExpressions.cpp @@ -123,7 +123,7 @@ TEST_F(FormRegressionTest, Min) { std::string func = " sll r0, r0, 0\n" " or v0, a0, r0\n" - " or v1, a1, r0 \n" + " or v1, a1, r0\n" " slt a0, v0, v1\n" " movz v0, v1, a0\n" " jr ra\n" @@ -179,7 +179,7 @@ TEST_F(FormRegressionTest, FormatString) { " jalr ra, t9\n" " sll v0, ra, 0\n" - " or v0, gp, r0 \n" + " or v0, gp, r0\n" " ld ra, 0(sp)\n" " ld fp, 8(sp)\n" " lq gp, 16(sp)\n" @@ -880,4 +880,4 @@ TEST_F(FormRegressionTest, TypeOf) { " (ret-value v0-0)\n" " )"; test_no_expr(func, type, expected, false); -} \ No newline at end of file +}