diff --git a/decompiler/IR2/FormExpressionAnalysis.cpp b/decompiler/IR2/FormExpressionAnalysis.cpp index e0082e5989..ac5b4aaf48 100644 --- a/decompiler/IR2/FormExpressionAnalysis.cpp +++ b/decompiler/IR2/FormExpressionAnalysis.cpp @@ -3263,8 +3263,14 @@ void ShortCircuitElement::push_to_stack(const Env& env, FormPool& pool, FormStac entry.condition->clear(); for (auto e : new_entries) { + if (dynamic_cast(e)) { + continue; + } entry.condition->push_back(e); } + if (entry.condition->elts().empty()) { + entry.condition->push_back(pool.alloc_element()); + } } } diff --git a/decompiler/analysis/cfg_builder.cpp b/decompiler/analysis/cfg_builder.cpp index a10a021d0e..ea26ee76f1 100644 --- a/decompiler/analysis/cfg_builder.cpp +++ b/decompiler/analysis/cfg_builder.cpp @@ -611,7 +611,14 @@ bool try_splitting_nested_sc(FormPool& pool, Function& func, ShortCircuitElement * if there is a case like (and a (or b c)) */ void clean_up_sc(FormPool& pool, Function& func, ShortCircuitElement* ir) { - assert(ir->entries.size() > 1); + assert(ir->entries.size() > 0); + if (ir->entries.size() == 1) { + // need to fake the final entry. + ShortCircuitElement::Entry empty_final; + empty_final.condition = pool.alloc_single_element_form(ir); + ir->entries.push_back(empty_final); + } + if (!try_clean_up_sc_as_and(pool, func, ir)) { if (!try_clean_up_sc_as_or(pool, func, ir)) { if (!try_splitting_nested_sc(pool, func, ir)) { @@ -1615,9 +1622,6 @@ Form* cfg_to_ir_helper(FormPool& pool, Function& f, const CfgVtx* vtx) { return as_abs; } - if (svtx->entries.size() == 1) { - throw std::runtime_error("Weird short circuit form."); - } // now try as a normal and/or std::vector entries; for (auto& x : svtx->entries) { diff --git a/decompiler/config/jak1_ntsc_black_label/hacks.jsonc b/decompiler/config/jak1_ntsc_black_label/hacks.jsonc index 49bd0c5663..523f54652c 100644 --- a/decompiler/config/jak1_ntsc_black_label/hacks.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/hacks.jsonc @@ -377,9 +377,6 @@ "ocean-generate-verts", "ocean-interp-wave", - // anim-tester BUG - //"anim-tester-add-newobj", - // nav-enemy BUG "(anon-function 28 nav-enemy)", diff --git a/goal_src/engine/entity/actor-link-h.gc b/goal_src/engine/entity/actor-link-h.gc index de4d5f3888..9e1de16188 100644 --- a/goal_src/engine/entity/actor-link-h.gc +++ b/goal_src/engine/entity/actor-link-h.gc @@ -252,7 +252,7 @@ (while iter (let ((proc (-> (the entity-links (-> iter extra)) process))) (when proc - (set! result (and result (send-event proc message))) + (set! result (or (send-event proc message) result)) ) (set! iter (entity-actor-lookup iter 'next-actor 0)) ) @@ -269,7 +269,7 @@ (while iter (let ((proc (-> (the entity-links (-> iter extra)) process))) (when proc - (set! result (and result (send-event proc message))) + (set! result (or (send-event proc message) result)) ) (set! iter (entity-actor-lookup iter 'prev-actor 0)) ) diff --git a/test/decompiler/reference/engine/entity/actor-link-h_REF.gc b/test/decompiler/reference/engine/entity/actor-link-h_REF.gc index e7c33c0a0c..dfb62a52e9 100644 --- a/test/decompiler/reference/engine/entity/actor-link-h_REF.gc +++ b/test/decompiler/reference/engine/entity/actor-link-h_REF.gc @@ -248,11 +248,8 @@ (set! (-> msg-block from) pp) (set! (-> msg-block num-params) 0) (set! (-> msg-block message) message) - (let ((v1-3 (send-event-function proc msg-block))) - (b! v1-3 cfg-4 :likely-delay (set! result v1-3)) - ) + (set! result (or (send-event-function proc msg-block) result)) ) - (label cfg-4) ) ) (set! iter (entity-actor-lookup iter 'next-actor 0)) @@ -278,11 +275,8 @@ (set! (-> a1-1 from) pp) (set! (-> a1-1 num-params) 0) (set! (-> a1-1 message) arg0) - (let ((v1-3 (send-event-function a0-1 a1-1))) - (b! v1-3 cfg-4 :likely-delay (set! s5-0 v1-3)) - ) + (set! s5-0 (or (send-event-function a0-1 a1-1) s5-0)) ) - (label cfg-4) ) ) (set! s4-0 (entity-actor-lookup s4-0 'prev-actor 0)) diff --git a/test/decompiler/test_FormExpressionBuild3.cpp b/test/decompiler/test_FormExpressionBuild3.cpp index d77a213765..dac6dcf805 100644 --- a/test/decompiler/test_FormExpressionBuild3.cpp +++ b/test/decompiler/test_FormExpressionBuild3.cpp @@ -53,4 +53,113 @@ TEST_F(FormRegressionTest, VectorDegToVectorRad) { " )\n" " )"; test_final_function(func, type, expected); +} + +// weird short circuit thing +TEST_F(FormRegressionTest, WeirdShortCircuit) { + std::string func = + "sll r0, r0, 0\n" + " daddiu sp, sp, -144\n" + " sd ra, 0(sp)\n" + " sq s4, 96(sp)\n" + " sq s5, 112(sp)\n" + " sq gp, 128(sp)\n" + + " or gp, a1, r0\n" + " or v1, a0, r0\n" + " lwu s4, 4(v1)\n" + " or s5, s7, r0\n" // s5 = result + " beq r0, r0, L43\n" + " sll r0, r0, 0\n" + + "L40:\n" + " lwu v1, 20(s4)\n" + " lwu a0, 12(v1)\n" + " beq s7, a0, L42\n" + " or v1, s7, r0\n" + + " daddiu a1, sp, 16\n" + " sw s6, 4(a1)\n" + " sw r0, 8(a1)\n" + " sw gp, 12(a1)\n" + " lw t9, send-event-function(s7)\n" + " jalr ra, t9\n" + " sll v0, ra, 0\n" + + " or v1, v0, r0\n" + " bnel s7, v1, L41\n" + + " or s5, v1, r0\n" + + // there's nothing here! + + "L41:\n" + " or v1, s5, r0\n" + + "L42:\n" + " lw t9, entity-actor-lookup(s7)\n" + " daddiu a1, s7, next-actor\n" + " addiu a2, r0, 0\n" + " or a0, s4, r0\n" + " jalr ra, t9\n" + + " sll v0, ra, 0\n" + + " or v1, v0, r0\n" + " or s4, v1, r0\n" + + "L43:\n" + " bne s7, s4, L40\n" + " sll r0, r0, 0\n" + + " or v1, s7, r0\n" + " or v0, s5, r0\n" + " ld ra, 0(sp)\n" + " lq gp, 128(sp)\n" + " lq s5, 112(sp)\n" + " lq s4, 96(sp)\n" + " jr ra\n" + " daddiu sp, sp, 144"; + std::string type = "(function actor-link-info symbol object)"; + std::string expected = + "(let ((s4-0 (-> arg0 next))\n" + " (s5-0 (the-as object #f))\n" + " )\n" + " (while s4-0\n" + " (let ((a0-1 (-> s4-0 extra process)))\n" + " (when a0-1\n" + " (let ((a1-1 (new 'stack-no-clear 'event-message-block)))\n" + " (set! (-> a1-1 from) pp)\n" + " (set! (-> a1-1 num-params) 0)\n" + " (set! (-> a1-1 message) arg1)\n" + " (set! s5-0 (or (send-event-function a0-1 a1-1) s5-0))\n" + " )\n" + " )\n" + " )\n" + " (set! s4-0 (entity-actor-lookup s4-0 'next-actor 0))\n" + " )\n" + " s5-0\n" + " )"; + test_with_stack_structures(func, type, expected, "[[16, \"event-message-block\"]]"); +} + +TEST_F(FormRegressionTest, WeirdShortCircuit2) { + std::string func = + "sll r0, r0, 0\n" + "L62:\n" + " lwu v1, 8(a0)\n" + " beql s7, v1, L63\n" + + " or v0, v1, r0\n" + + " lwu v1, 8(a0)\n" // here's the case + " lwu v1, 20(v1)\n" + " lwu v0, 12(v1)\n" + + "L63:\n" + " jr ra\n" + " daddu sp, sp, r0"; + std::string type = "(function actor-link-info object)"; + std::string expected = "(and (-> arg0 prev) (-> arg0 prev extra process))"; + test_with_stack_structures(func, type, expected, "[[16, \"event-message-block\"]]"); } \ No newline at end of file