12.9 步骤 3:CALL/RET 帧栈与故障。
- 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 后清栈)
This commit is contained in:
+51
-4
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "vm/Machine.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#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<size_t>(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<size_t>(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
|
||||
|
||||
Reference in New Issue
Block a user