diff --git a/src/backend/llvm/branch_targets.cpp b/src/backend/llvm/branch_targets.cpp index 43ed05c..37e8421 100644 --- a/src/backend/llvm/branch_targets.cpp +++ b/src/backend/llvm/branch_targets.cpp @@ -112,9 +112,7 @@ BasicBlock *FunctionEmitter::exitDestination(u32 pc) { BasicBlock * FunctionEmitter::fallbackDestination(const DolIRTerminator &terminator) { - BasicBlock *source = builder_.GetInsertBlock(); - fallback_pc_->addIncoming(builder_.getInt32(terminator.guest_pc), source); - return fallback_block_; + return fallbackEdge(terminator.guest_pc); } BasicBlock *FunctionEmitter::fallbackEdge(u32 pc) { diff --git a/src/backend/llvm/emitter.cpp b/src/backend/llvm/emitter.cpp index e26aa07..b28bea4 100644 --- a/src/backend/llvm/emitter.cpp +++ b/src/backend/llvm/emitter.cpp @@ -80,7 +80,7 @@ bool FunctionEmitter::emit(raw_ostream &diagnostics) { BasicBlock *region = nullptr; for (u32 i = 0; i < source_.block_count; i++) { if (source_.blocks[i].terminator.kind == DOLIR_TERM_FALLBACK) { - blocks_[i] = fallback_block_; + blocks_[i] = fallbackEdge(source_.blocks[i].guest_address); region = nullptr; continue; } diff --git a/tests/llvm_fixture.cpp b/tests/llvm_fixture.cpp index a6b8b59..8c3cbf2 100644 --- a/tests/llvm_fixture.cpp +++ b/tests/llvm_fixture.cpp @@ -42,6 +42,10 @@ static u32 psq_dform(bool store, u8 reg, u8 base, u16 displacement) { (displacement & 0x0fffu); } +static u32 branch(bool link, u32 delta) { + return 0x48000000u | (delta & 0x03fffffcu) | (link ? 1u : 0u); +} + static bool add_chunk(DolIRModule *module, const u32 *words, u32 count, u32 address) { PPCInst *instructions = new PPCInst[count]; @@ -339,6 +343,17 @@ int main(int argc, char **argv) { CHECK(add_chunk(&module, return_continuation_words, 3, 0x80003B08u)); CHECK(add_chunk(&module, return_callee_words, 2, 0x80003C00u)); + // Both indirect returns can dispatch to the linked branch's fallback + // continuation. The mtctr/bctr path also carries modified state into it. + const u32 indirect_fallback_words[] = { + branch(true, 0x10u), + 0x00000000u, + mtspr(3, 9), + 0x4E800420u, + 0x4E800020u, + }; + CHECK(add_chunk(&module, indirect_fallback_words, 5, 0x80003D00u)); + CHECK(dolir_verify(&module, stderr)); DolLLVMOptions options{}; options.optimization_level = 2;