| 85 | } |
| 86 | |
| 87 | N64Recomp::LiveGeneratorOutput N64Recomp::LiveGenerator::finish() { |
| 88 | LiveGeneratorOutput ret{}; |
| 89 | if (errored) { |
| 90 | ret.good = false; |
| 91 | return ret; |
| 92 | } |
| 93 | |
| 94 | ret.good = true; |
| 95 | |
| 96 | // Populate all the pending inner function calls. |
| 97 | for (const InnerCall& call : context->inner_calls) { |
| 98 | sljit_label* target_func_label = context->func_labels[call.target_func_index]; |
| 99 | |
| 100 | // Generation isn't valid if the target function wasn't recompiled. |
| 101 | if (target_func_label == nullptr) { |
| 102 | return { }; |
| 103 | } |
| 104 | |
| 105 | sljit_set_label(call.jump, target_func_label); |
| 106 | } |
| 107 | |
| 108 | // Generate the switch error jump targets and assign the jump labels. |
| 109 | if (!context->switch_error_jumps.empty()) { |
| 110 | // Allocate the function name and place it in the literals. |
| 111 | char* func_name = new char[context->function_name.size() + 1]; |
| 112 | memcpy(func_name, context->function_name.c_str(), context->function_name.size()); |
| 113 | func_name[context->function_name.size()] = '\x00'; |
| 114 | ret.string_literals.emplace_back(func_name); |
| 115 | |
| 116 | std::vector<sljit_jump*> switch_error_return_jumps{}; |
| 117 | switch_error_return_jumps.resize(context->switch_error_jumps.size()); |
| 118 | |
| 119 | // Generate and assign the labels for the switch error jumps. |
| 120 | for (size_t i = 0; i < context->switch_error_jumps.size(); i++) { |
| 121 | const auto& cur_error_jump = context->switch_error_jumps[i]; |
| 122 | |
| 123 | // Generate a label and assign it to the jump. |
| 124 | sljit_set_label(cur_error_jump.jump, sljit_emit_label(compiler)); |
| 125 | |
| 126 | // Load the arguments (function name, vram, jump table address) |
| 127 | sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sljit_sw(func_name)); |
| 128 | sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, sljit_sw(cur_error_jump.instr_vram)); |
| 129 | sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, sljit_sw(cur_error_jump.jtbl_vram)); |
| 130 | |
| 131 | // Call switch_error. |
| 132 | sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3V(P, 32, 32), SLJIT_IMM, sljit_sw(inputs.switch_error)); |
| 133 | |
| 134 | // Jump to the return statement. |
| 135 | switch_error_return_jumps[i] = sljit_emit_jump(compiler, SLJIT_JUMP); |
| 136 | } |
| 137 | |
| 138 | // Generate the return statement. |
| 139 | sljit_label* return_label = sljit_emit_label(compiler); |
| 140 | sljit_emit_return_void(compiler); |
| 141 | |
| 142 | // Assign the label for all the return jumps. |
| 143 | for (sljit_jump* cur_jump : switch_error_return_jumps) { |
| 144 | sljit_set_label(cur_jump, return_label); |