From a84a1a62ce9f69641c3ec62d6ea4ce92fd1d838c Mon Sep 17 00:00:00 2001 From: chentianya Date: Fri, 21 Aug 2026 20:17:55 +0800 Subject: [PATCH] =?UTF-8?q?12.9=20=E6=AD=A5=E9=AA=A4=203=EF=BC=9ACALL/RET?= =?UTF-8?q?=20=E5=B8=A7=E6=A0=88=E4=B8=8E=E6=95=85=E9=9A=9C=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - do_call:压新帧(nregs 分配、复制 r0..r7、记 ret_pc/ret_fn_id)→ pc=0;fn_id 越界 BadOp、深度≥64 StackOverflow - do_ret:复制 r0..r7 回调用方(r0=结果)→ 弹栈 → pc=ret_pc;MAIN 的 RET = 周期结束 - 验证:用例 13 x=Add(3,4)=7、双周期帧保留;手拼自调用映像触发 StackOverflow(深度 64 后清栈) --- vm/src/Machine.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/vm/src/Machine.cpp b/vm/src/Machine.cpp index e81f9b5..8dd0167 100644 --- a/vm/src/Machine.cpp +++ b/vm/src/Machine.cpp @@ -14,6 +14,8 @@ #include "vm/Machine.h" +#include + #include "isa/Encode.h" #include "isa/Instr.h" #include "isa/Op.h" @@ -248,15 +250,60 @@ bool Machine::exec_one() { } return true; } + case isa::Op::CALL: + fault_ = do_call(isa::imm16(w)); + return fault_ == Fault::None; case isa::Op::RET: - // MAIN 的 RET = 周期结束(步骤 3 处理非 MAIN 帧返回) - ended_ = true; - return false; + fault_ = do_ret(); + if (fault_ != Fault::None) { + return false; + } + return !ended_; // MAIN 的 RET → 周期结束(返回 false) default: - // CALL / CAL_TON / CAL_TOF / CAL_CTU(步骤 3 / 4 实现) + // CAL_TON / CAL_TOF / CAL_CTU(步骤 4 实现) fault_ = Fault::BadOp; return false; } } +Fault Machine::do_call(uint32_t fn_id) { + if (fn_id >= image_.header().n_funcs) { + return Fault::BadOp; + } + if (frames_.size() >= 64) { + return Fault::StackOverflow; + } + const isa::FuncRow row = image_.func_row(fn_id); + Frame f; + f.fn_id = fn_id; + f.regs.assign(row.nregs, 0); + f.ret_pc = pc_; // 已指向 CALL 的下一条 + f.ret_fn_id = cur_frame().fn_id; + // 调用约定:复制当前帧 r0..r7 → 新帧(实参已由调用点 MOVE 进 r1..r7) + const size_t n = std::min(8, std::min(cur_frame().regs.size(), f.regs.size())); + for (size_t i = 0; i < n; ++i) { + f.regs[i] = cur_frame().regs[i]; + } + frames_.push_back(std::move(f)); + pc_ = 0; + return Fault::None; +} + +Fault Machine::do_ret() { + if (frames_.size() <= 1) { + ended_ = true; // MAIN 的 RET:周期结束 + return Fault::None; + } + Frame& cur = cur_frame(); + Frame& caller = frames_[frames_.size() - 2]; + // 调用约定:复制当前帧 r0..r7 → 调用方(r0 = 结果,r1..r7 原样返回) + const size_t n = std::min(8, std::min(cur.regs.size(), caller.regs.size())); + for (size_t i = 0; i < n; ++i) { + caller.regs[i] = cur.regs[i]; + } + pc_ = cur.ret_pc; + frames_.pop_back(); + return Fault::None; +} + } // namespace vm