From efe4dd1a2c88fb6d2d1c120a27a43b603860fc5d Mon Sep 17 00:00:00 2001 From: chentianya Date: Fri, 21 Aug 2026 20:16:28 +0800 Subject: [PATCH] =?UTF-8?q?12.9=20=E6=AD=A5=E9=AA=A4=202=EF=BC=9AVM=20?= =?UTF-8?q?=E8=AF=91=E7=A0=81=20switch=EF=BC=88=E6=A0=87=E9=87=8F/?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC/LOAD-STORE=EF=BC=89=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Machine.cpp:create(拷贝数据段+建 MAIN 帧)、run_cycle、step、exec_one - 标量:MOVE/LOADK(常量表 tag 定值表示)/NOT/AND/OR/四则饱和/CMP 全宽比较 - 跳转:JMP/JT/JF(相对下一条);LOAD/STORE:slot×8 定宽槽,BadSlot 校验 - 寄存器越界检查按指令形态(a|b 作偏移/槽号/常量 id 时不查) - 修:ImageView 默认构造公开(无效态)、Codegen 两个编译警告 - 冒烟:用例 02/04/07/05 跑通、06 触发 CycleLimit、step 单步 --- compiler/src/Codegen.cpp | 5 +- isa/include/isa/Image.h | 4 +- vm/src/Machine.cpp | 258 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 260 insertions(+), 7 deletions(-) diff --git a/compiler/src/Codegen.cpp b/compiler/src/Codegen.cpp index 9d63b6e..4e911bf 100644 --- a/compiler/src/Codegen.cpp +++ b/compiler/src/Codegen.cpp @@ -242,9 +242,6 @@ namespace { if (d.type.kind == TypeKind::FbUser || d.type.kind == TypeKind::FbBuiltin) { continue; } - if (r > 255) { - return fail("register overflow in function '" + pou.name + "'"); - } f->regs[d.name] = r++; } } @@ -660,8 +657,8 @@ namespace { case BinOp::Le: return isa::Op::CMP_LE; case BinOp::Gt: return isa::Op::CMP_GT; case BinOp::Ge: return isa::Op::CMP_GE; + default: return isa::Op::CMP_EQ; // Add/Sub/Mul/Div 不经此函数 } - return isa::Op::CMP_EQ; } /** diff --git a/isa/include/isa/Image.h b/isa/include/isa/Image.h index d1f1289..fd1cc47 100644 --- a/isa/include/isa/Image.h +++ b/isa/include/isa/Image.h @@ -77,6 +77,8 @@ namespace isa { // 只读视图:校验过的映像 class ImageView { public: + // 默认构造为无效态(ok() == false,error() == "uninitialized") + ImageView(); static ImageView from(const uint8_t* buf, size_t len); static ImageView from(const std::vector& buf); @@ -96,7 +98,7 @@ namespace isa { size_t data_len() const; // 字节数 private: - ImageView(); + // 私有成员与内部构造辅助(from 使用) const uint8_t* buf_; size_t len_; diff --git a/vm/src/Machine.cpp b/vm/src/Machine.cpp index c337c8e..e81f9b5 100644 --- a/vm/src/Machine.cpp +++ b/vm/src/Machine.cpp @@ -1,8 +1,262 @@ /** * @file Machine.cpp - * @brief 寄存器虚拟机(12.9 实现) - * @date 2026-08-19 + * @brief 寄存器虚拟机(12.9,步骤 2:译码 switch) + * @author + * @date 2026-08-21 + * + * @details 设计说明(详见 Doc/vm/指令执行.md): + * - 步骤 2 范围:create / run_cycle / step + 标量指令(MOVE/LOADK/NOT/AND/OR/算术/CMP)、 + * 跳转(JMP/JT/JF)、LOAD/STORE(slot × 8);RET 仅处理 MAIN(周期结束) + * - 步骤 3 补 CALL/RET 帧栈与栈深/坏操作码故障;步骤 4 补 CAL_* 定时器 + * - 取指:函数表 → code_offset(字节)→ u32;执行后 pc 先 +1,跳转再 pc += off + * - 数据区 8 字节定宽槽:偏移 = slot × 8 */ +#include "vm/Machine.h" + +#include "isa/Encode.h" +#include "isa/Instr.h" +#include "isa/Op.h" +#include "isa/Types.h" + namespace vm { + +bool Machine::create(const std::vector& image, Machine* out, + std::string* err) { + out->image_ = isa::ImageView::from(image); + if (!out->image_.ok()) { + if (err) { + *err = out->image_.error(); + } + return false; + } + // 数据区工作副本(8 字节定宽槽) + out->data_.assign(out->image_.data_bytes(), + out->image_.data_bytes() + out->image_.data_len()); + out->ctu_prev_.assign(out->data_len() / 8, 0); + + // MAIN 帧(跨周期保留) + const uint32_t entry = out->image_.header().entry_fn_id; + const isa::FuncRow main = out->image_.func_row(entry); + out->frames_.clear(); + Frame f; + f.fn_id = entry; + f.regs.assign(main.nregs, 0); + out->frames_.push_back(std::move(f)); + + out->pc_ = 0; + out->cycle_count_ = 0; + out->fault_ = Fault::None; + out->ended_ = false; + return true; } + +Fault Machine::run_cycle() { + cycle_count_ = 0; + ended_ = false; + fault_ = Fault::None; + pc_ = 0; + while (!ended_ && fault_ == Fault::None) { + if (!exec_one()) { + break; + } + } + // 周期结束:清调用栈(保留 MAIN 帧,PROGRAM 变量状态跨周期) + while (frames_.size() > 1) { + frames_.pop_back(); + } + return fault_; +} + +bool Machine::step() { + if (ended_ || fault_ != Fault::None) { + return false; + } + return exec_one(); +} + +Fault Machine::fault() const { return fault_; } +uint32_t Machine::pc() const { return pc_; } +uint32_t Machine::fn_id() const { return cur_frame().fn_id; } +uint32_t Machine::cycle_count() const { return cycle_count_; } +uint32_t Machine::call_depth() const { return static_cast(frames_.size()); } +uint8_t* Machine::data() { return data_.data(); } +const uint8_t* Machine::data() const { return data_.data(); } +size_t Machine::data_len() const { return data_.size(); } +int64_t Machine::reg(uint8_t i) const { return cur_frame().regs[i]; } + +Machine::Frame& Machine::cur_frame() { return frames_.back(); } +const Machine::Frame& Machine::cur_frame() const { return frames_.back(); } + +bool Machine::exec_one() { + // ---- 取指 ---- + const isa::FuncRow row = image_.func_row(cur_frame().fn_id); + if (pc_ >= row.code_len) { + fault_ = Fault::BadOp; + return false; + } + const uint8_t* base = image_.code_bytes() + row.code_offset; + const isa::Instr w = reinterpret_cast(base)[pc_]; + + // ---- 周期指令计数 ---- + ++cycle_count_; + if (cycle_count_ > image_.header().cycle_limit) { + fault_ = Fault::CycleLimit; + return false; + } + + // 先指向下一条(跳转指令再按"相对下一条"语义叠加偏移) + ++pc_; + + const isa::Op op = isa::op(w); + const uint8_t rd = isa::rd(w); + const uint8_t ra = isa::a(w); + const uint8_t rb = isa::b(w); + std::vector& regs = cur_frame().regs; + + // 寄存器越界检查(仅对把字段当寄存器的指令;a|b 作偏移/槽号/常量 id 时跳过) + const bool uses_rd = op == isa::Op::MOVE || op == isa::Op::NOT || op == isa::Op::AND || + op == isa::Op::OR || op == isa::Op::ADD || op == isa::Op::SUB || + op == isa::Op::MUL || op == isa::Op::DIV || op == isa::Op::CMP_EQ || + op == isa::Op::CMP_NE || op == isa::Op::CMP_LT || + op == isa::Op::CMP_LE || op == isa::Op::CMP_GT || + op == isa::Op::CMP_GE || op == isa::Op::JT || op == isa::Op::JF || + op == isa::Op::LOADK || op == isa::Op::LOAD_I || + op == isa::Op::LOAD_M || op == isa::Op::LOAD_GLOBAL || + op == isa::Op::STORE_Q || op == isa::Op::STORE_M || + op == isa::Op::STORE_GLOBAL; + const bool uses_ra = op == isa::Op::MOVE || op == isa::Op::NOT || op == isa::Op::AND || + op == isa::Op::OR || op == isa::Op::ADD || op == isa::Op::SUB || + op == isa::Op::MUL || op == isa::Op::DIV || op == isa::Op::CMP_EQ || + op == isa::Op::CMP_NE || op == isa::Op::CMP_LT || + op == isa::Op::CMP_LE || op == isa::Op::CMP_GT || + op == isa::Op::CMP_GE; + const bool uses_rb = uses_ra; + if ((uses_rd && rd >= regs.size()) || (uses_ra && ra >= regs.size()) || + (uses_rb && rb >= regs.size())) { + fault_ = Fault::BadOp; + return false; + } + + switch (op) { + case isa::Op::MOVE: + regs[rd] = regs[ra]; + return true; + case isa::Op::LOADK: { + const uint16_t cid = isa::imm16(w); + if (cid >= image_.header().n_consts) { + fault_ = Fault::BadConst; + return false; + } + const isa::ConstEntry c = image_.const_entry(cid); + if (c.tag == isa::types::Bool) { + regs[rd] = c.value ? 1 : 0; + } else if (c.tag == isa::types::Int) { + regs[rd] = static_cast(c.value); // 符号扩展 + } else { + regs[rd] = static_cast(c.value); + } + return true; + } + case isa::Op::NOT: + regs[rd] = (regs[ra] == 0) ? 1 : 0; + return true; + case isa::Op::AND: + regs[rd] = (regs[ra] != 0 && regs[rb] != 0) ? 1 : 0; + return true; + case isa::Op::OR: + regs[rd] = (regs[ra] != 0 || regs[rb] != 0) ? 1 : 0; + return true; + case isa::Op::ADD: + regs[rd] = isa::types::sat_add(static_cast(regs[ra]), + static_cast(regs[rb])); + return true; + case isa::Op::SUB: + regs[rd] = isa::types::sat_sub(static_cast(regs[ra]), + static_cast(regs[rb])); + return true; + case isa::Op::MUL: + regs[rd] = isa::types::sat_mul(static_cast(regs[ra]), + static_cast(regs[rb])); + return true; + case isa::Op::DIV: + regs[rd] = isa::types::sat_div(static_cast(regs[ra]), + static_cast(regs[rb])); + return true; + case isa::Op::CMP_EQ: + case isa::Op::CMP_NE: + case isa::Op::CMP_LT: + case isa::Op::CMP_LE: + case isa::Op::CMP_GT: + case isa::Op::CMP_GE: { + const int64_t l = regs[ra]; + const int64_t r = regs[rb]; + bool res = false; + switch (op) { + case isa::Op::CMP_EQ: res = (l == r); break; + case isa::Op::CMP_NE: res = (l != r); break; + case isa::Op::CMP_LT: res = (l < r); break; + case isa::Op::CMP_LE: res = (l <= r); break; + case isa::Op::CMP_GT: res = (l > r); break; + case isa::Op::CMP_GE: res = (l >= r); break; + default: break; + } + regs[rd] = res ? 1 : 0; + return true; + } + case isa::Op::JMP: + pc_ += isa::off16(w); + return true; + case isa::Op::JT: + if (regs[rd] != 0) { + pc_ += isa::off16(w); + } + return true; + case isa::Op::JF: + if (regs[rd] == 0) { + pc_ += isa::off16(w); + } + return true; + case isa::Op::LOAD_I: + case isa::Op::LOAD_M: + case isa::Op::LOAD_GLOBAL: { + const uint16_t slot = isa::imm16(w); + const size_t off = static_cast(slot) * 8; + if (off + 8 > data_.size()) { + fault_ = Fault::BadSlot; + return false; + } + int64_t v = 0; + for (int i = 0; i < 8; ++i) { + v |= static_cast(data_[off + i]) << (8 * i); + } + regs[rd] = v; + return true; + } + case isa::Op::STORE_Q: + case isa::Op::STORE_M: + case isa::Op::STORE_GLOBAL: { + const uint16_t slot = isa::imm16(w); + const size_t off = static_cast(slot) * 8; + if (off + 8 > data_.size()) { + fault_ = Fault::BadSlot; + return false; + } + const int64_t v = regs[rd]; + for (int i = 0; i < 8; ++i) { + data_[off + i] = static_cast((v >> (8 * i)) & 0xFFu); + } + return true; + } + case isa::Op::RET: + // MAIN 的 RET = 周期结束(步骤 3 处理非 MAIN 帧返回) + ended_ = true; + return false; + default: + // CALL / CAL_TON / CAL_TOF / CAL_CTU(步骤 3 / 4 实现) + fault_ = Fault::BadOp; + return false; + } +} + +} // namespace vm