From 5fccbadaa8697727a2561df3d6d3de4d1e9a7d95 Mon Sep 17 00:00:00 2001 From: chentianya Date: Fri, 21 Aug 2026 22:24:57 +0800 Subject: [PATCH] =?UTF-8?q?=E9=98=B6=E6=AE=B5=20C=20=E6=AD=A5=E9=AA=A4=207?= =?UTF-8?q?=EF=BC=9Aisa=20=E6=8B=86=E5=87=BA=20Image=EF=BC=8Cvm=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E6=94=B6=E7=AA=84=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删 isa/Image.h + Image.cpp(ImageView/FNV/写文件/sidecar 不再属于 isa) - vm 自实现只读视图 vm/Image.h/cpp:头 104(12.13)/段校验/缺 SHA 尾报错 (型号匹配与 SHA 校验留步骤 8);Machine 改用 vm::Image + vm::ImageHeader - executor:本地读文件(替换 isa::read_stb_file) - 测试:isa_test 删映像/FNV 部分;codegen_test/vm_test 改用 compiler::StbView / vm::ConstEntry;vm_test 手拼映像适配新格式(头 104 + 尾 32 占位) - 验证:line1 编译 288 字节 → BytecodeExecutor 回放 Q 正确;ctest 12/12 --- executor/src/main.cpp | 17 +- isa/CMakeLists.txt | 3 +- isa/include/isa/Image.h | 125 --------------- isa/src/Image.cpp | 321 ------------------------------------- tests/src/codegen_test.cpp | 134 ++++++++-------- tests/src/isa_test.cpp | 104 ------------ tests/src/vm_test.cpp | 25 ++- vm/CMakeLists.txt | 3 +- vm/include/vm/Image.h | 78 +++++++++ vm/include/vm/Machine.h | 6 +- vm/src/Image.cpp | 151 +++++++++++++++++ vm/src/Machine.cpp | 14 +- 12 files changed, 334 insertions(+), 647 deletions(-) delete mode 100644 isa/include/isa/Image.h delete mode 100644 isa/src/Image.cpp create mode 100644 vm/include/vm/Image.h create mode 100644 vm/src/Image.cpp diff --git a/executor/src/main.cpp b/executor/src/main.cpp index a11e14d..a1ca3a5 100644 --- a/executor/src/main.cpp +++ b/executor/src/main.cpp @@ -21,7 +21,7 @@ #include #include "isa/Encode.h" -#include "isa/Image.h" +#include "vm/Image.h" #include "vm/Machine.h" namespace { @@ -199,8 +199,17 @@ int main(int argc, char** argv) { std::string err; std::vector bytes; - if (!isa::read_stb_file(stb_path.c_str(), &bytes, &err)) { - std::fprintf(stderr, "error: %s\n", err.c_str()); + { + std::ifstream in(stb_path, std::ios::binary); + if (!in) { + std::fprintf(stderr, "error: cannot open: %s\n", stb_path.c_str()); + return 1; + } + bytes.assign(std::istreambuf_iterator(in), std::istreambuf_iterator()); + } + const vm::Image img = vm::Image::from(bytes); + if (!img.ok()) { + std::fprintf(stderr, "error: %s\n", img.error().c_str()); return 1; } vm::Machine machine; @@ -233,7 +242,7 @@ int main(int argc, char** argv) { } } - const isa::ImageHeader& h = machine.header(); + const vm::ImageHeader& h = machine.header(); std::printf("image: %s (%zu bytes, dt_ms=%u, cycle_limit=%u)\n", stb_path.c_str(), bytes.size(), h.dt_ms, h.cycle_limit); diff --git a/isa/CMakeLists.txt b/isa/CMakeLists.txt index 508b752..9df22ef 100644 --- a/isa/CMakeLists.txt +++ b/isa/CMakeLists.txt @@ -7,7 +7,6 @@ project(ISA DESCRIPTION "指令集架构") add_library(isa STATIC - ./src/Encode.cpp - ./src/Image.cpp) + ./src/Encode.cpp) target_include_directories(isa PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) \ No newline at end of file diff --git a/isa/include/isa/Image.h b/isa/include/isa/Image.h deleted file mode 100644 index fd1cc47..0000000 --- a/isa/include/isa/Image.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @file Image.h - * @brief 映像头、段、FNV-1a 哈希、.stb 文件与 sidecar - * @author - * @date 2026-08-19 - */ - -#pragma once - -#include -#include -#include -#include - -#include "isa/Types.h" - -namespace isa { - - // 魔数 "STSC"(小端 u32)、版本 - static const uint32_t kMagic = 0x43545353u; - static const uint32_t kVersion = 1; - - // 头与表行宽(见 Doc/isa/指令与映像.md) - static const size_t kHeaderSize = 72; - static const size_t kConstEntrySize = 12; - static const size_t kFuncRowSize = 12; - - // FNV-1a 64:basis / prime(见 Doc/isa/指令与映像.md) - static const uint64_t kFnvBasis = 0xcbf29ce484222325ull; - static const uint64_t kFnvPrime = 0x100000001b3ull; - - // FNV-1a 64 增量与一次性 - uint64_t fnv1a64_update(uint64_t h, const uint8_t* data, size_t len); - uint64_t fnv1a64(const uint8_t* data, size_t len); - - // 映像头(字节布局见 Doc/isa/指令与映像.md) - struct ImageHeader { - uint32_t cycle_limit; - uint32_t dt_ms; - uint64_t project_hash; - uint32_t entry_fn_id; - uint32_t n_globals; - uint32_t n_i; - uint32_t n_q; - uint32_t n_m; - uint32_t n_consts; - uint32_t n_funcs; - uint32_t offset_const; - uint32_t offset_funcs; - uint32_t offset_code; - uint32_t offset_fb; - uint32_t offset_data; - }; - - // 常量表一行 - struct ConstEntry { - types::TypeTag tag; - uint64_t value; - }; - - // 函数表一行 - struct FuncRow { - uint32_t nregs; - uint32_t code_offset; // 相对字节码段起点 - uint32_t code_len; // 指令条数 - }; - - // I/O 绑定(sidecar 一行) - struct IoBinding { - std::string var; - uint32_t slot; - uint32_t channel; - uint32_t bit; - bool is_input; // true = [[io.input]],false = [[io.output]] - }; - - // 只读视图:校验过的映像 - 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); - - bool ok() const; - const std::string& error() const; - const ImageHeader& header() const; - - const uint8_t* raw() const; - size_t raw_len() const; - - ConstEntry const_entry(size_t i) const; - FuncRow func_row(size_t i) const; - - const uint8_t* code_bytes() const; // 字节码段起点 - size_t code_len() const; // 字节数 - const uint8_t* data_bytes() const; // 数据段起点 - size_t data_len() const; // 字节数 - - private: - // 私有成员与内部构造辅助(from 使用) - - const uint8_t* buf_; - size_t len_; - bool ok_; - std::string err_; - ImageHeader hdr_; - }; - - // 写最小映像:空槽 + MAIN(fn_id=0)+ 一条 RET - std::vector write_ret_main(uint32_t cycle_limit, uint32_t dt_ms, - uint64_t project_hash); - - // .stb 文件读写(纯字节,校验交给 read_image / ImageView) - bool write_stb_file(const char* path, const std::vector& image, - std::string* err); - bool read_stb_file(const char* path, std::vector* image, - std::string* err); - - // sidecar 生成与写文件(格式见 Doc/isa/指令与映像.md) - std::string make_sidecar(const std::vector& bindings); - bool write_sidecar_file(const char* path, - const std::vector& bindings, - std::string* err); -} diff --git a/isa/src/Image.cpp b/isa/src/Image.cpp deleted file mode 100644 index 1d2fd7b..0000000 --- a/isa/src/Image.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/** - * @file Image.cpp - * @brief 映像头、段、FNV-1a 哈希、.stb 文件与 sidecar - * @author - * @date 2026-08-19 - */ - -#include "isa/Image.h" - -#include -#include - -#include "isa/Instr.h" - -namespace isa { - -// ---- 小端读写(只放 .cpp,不把 packed struct 当 ABI)---- - -static void put_le32(std::vector& b, size_t off, uint32_t v) { - b[off + 0] = static_cast(v & 0xFFu); - b[off + 1] = static_cast((v >> 8) & 0xFFu); - b[off + 2] = static_cast((v >> 16) & 0xFFu); - b[off + 3] = static_cast((v >> 24) & 0xFFu); -} - -static uint32_t get_le32(const uint8_t* p) { - return static_cast(p[0]) - | (static_cast(p[1]) << 8) - | (static_cast(p[2]) << 16) - | (static_cast(p[3]) << 24); -} - -static void put_le64(std::vector& b, size_t off, uint64_t v) { - for (int i = 0; i < 8; ++i) { - b[off + i] = static_cast((v >> (8 * i)) & 0xFFu); - } -} - -static uint64_t get_le64(const uint8_t* p) { - uint64_t v = 0; - for (int i = 0; i < 8; ++i) { - v |= static_cast(p[i]) << (8 * i); - } - return v; -} - -// ---- FNV-1a 64 ---- - -uint64_t fnv1a64_update(uint64_t h, const uint8_t* data, size_t len) { - for (size_t i = 0; i < len; ++i) { - h ^= data[i]; - h *= kFnvPrime; - } - return h; -} - -uint64_t fnv1a64(const uint8_t* data, size_t len) { - return fnv1a64_update(kFnvBasis, data, len); -} - -// ---- 最小映像:空槽 + MAIN + 一条 RET ---- - -std::vector write_ret_main(uint32_t cycle_limit, uint32_t dt_ms, - uint64_t project_hash) { - std::vector b(kHeaderSize + kFuncRowSize + 4, 0); - - put_le32(b, 0, kMagic); - put_le32(b, 4, kVersion); - put_le32(b, 8, cycle_limit); - put_le32(b, 12, dt_ms); - put_le64(b, 16, project_hash); - put_le32(b, 24, 0); // entry_fn_id = MAIN = 0 - // n_globals / n_i / n_q / n_m = 0 - // n_consts = 0 - put_le32(b, 48, 1); // n_funcs = 1 - - const size_t off_funcs = kHeaderSize; // 72 - const size_t off_code = off_funcs + kFuncRowSize; // 84 - const size_t off_end = off_code + 4; // 88 - - put_le32(b, 52, static_cast(off_funcs)); // offset_const - put_le32(b, 56, static_cast(off_funcs)); // offset_funcs - put_le32(b, 60, static_cast(off_code)); // offset_code - put_le32(b, 64, static_cast(off_end)); // offset_fb - put_le32(b, 68, static_cast(off_end)); // offset_data - - // 函数表一行:MAIN,无寄存器,代码 0 起 1 条 - put_le32(b, off_funcs + 0, 0); // nregs - put_le32(b, off_funcs + 4, 0); // code_offset - put_le32(b, off_funcs + 8, 1); // code_len - - // 字节码:RET - put_le32(b, off_code, pack(Op::RET, 0, 0, 0)); - - return b; -} - -// ---- 只读视图 ---- - -ImageView::ImageView() - : buf_(0), len_(0), ok_(false), err_("uninitialized"), hdr_() {} - -ImageView ImageView::from(const uint8_t* buf, size_t len) { - ImageView v; - v.buf_ = buf; - v.len_ = len; - - if (buf == 0) { - v.err_ = "null buffer"; - return v; - } - if (len < kHeaderSize) { - v.err_ = "image too short"; - return v; - } - if (get_le32(buf + 0) != kMagic) { - v.err_ = "bad magic"; - return v; - } - if (get_le32(buf + 4) != kVersion) { - v.err_ = "bad version"; - return v; - } - - ImageHeader& h = v.hdr_; - h.cycle_limit = get_le32(buf + 8); - h.dt_ms = get_le32(buf + 12); - h.project_hash = get_le64(buf + 16); - h.entry_fn_id = get_le32(buf + 24); - h.n_globals = get_le32(buf + 28); - h.n_i = get_le32(buf + 32); - h.n_q = get_le32(buf + 36); - h.n_m = get_le32(buf + 40); - h.n_consts = get_le32(buf + 44); - h.n_funcs = get_le32(buf + 48); - h.offset_const = get_le32(buf + 52); - h.offset_funcs = get_le32(buf + 56); - h.offset_code = get_le32(buf + 60); - h.offset_fb = get_le32(buf + 64); - h.offset_data = get_le32(buf + 68); - - // 段校验:连续、单调不减、末段终点不越界 - const uint64_t offs[5] = { - h.offset_const, h.offset_funcs, h.offset_code, h.offset_fb, h.offset_data, - }; - for (int i = 0; i < 5; ++i) { - if (offs[i] < kHeaderSize || offs[i] > len) { - v.err_ = "segment offset out of range"; - return v; - } - if (i > 0 && offs[i] < offs[i - 1]) { - v.err_ = "segment offsets not monotonic"; - return v; - } - } - - const uint64_t const_len = h.offset_funcs - h.offset_const; - const uint64_t funcs_len = h.offset_code - h.offset_funcs; - if (const_len != static_cast(h.n_consts) * kConstEntrySize) { - v.err_ = "const table size mismatch"; - return v; - } - if (funcs_len != static_cast(h.n_funcs) * kFuncRowSize) { - v.err_ = "function table size mismatch"; - return v; - } - if ((h.offset_fb - h.offset_code) % 4 != 0) { - v.err_ = "code segment not 4-byte aligned"; - return v; - } - if (h.entry_fn_id >= h.n_funcs && h.n_funcs != 0) { - v.err_ = "entry fn_id out of range"; - return v; - } - - v.ok_ = true; - v.err_.clear(); - return v; -} - -ImageView ImageView::from(const std::vector& buf) { - return from(buf.data(), buf.size()); -} - -bool ImageView::ok() const { return ok_; } -const std::string& ImageView::error() const { return err_; } -const ImageHeader& ImageView::header() const { return hdr_; } -const uint8_t* ImageView::raw() const { return buf_; } -size_t ImageView::raw_len() const { return len_; } - -ConstEntry ImageView::const_entry(size_t i) const { - ConstEntry e; - e.tag = types::Bool; - e.value = 0; - if (ok_ && i < hdr_.n_consts) { - const uint8_t* p = buf_ + hdr_.offset_const + i * kConstEntrySize; - const uint32_t tag = get_le32(p); - if (tag <= static_cast(types::Time)) { - e.tag = static_cast(tag); - } - e.value = get_le64(p + 4); - } - return e; -} - -FuncRow ImageView::func_row(size_t i) const { - FuncRow r = {0, 0, 0}; - if (ok_ && i < hdr_.n_funcs) { - const uint8_t* p = buf_ + hdr_.offset_funcs + i * kFuncRowSize; - r.nregs = get_le32(p + 0); - r.code_offset = get_le32(p + 4); - r.code_len = get_le32(p + 8); - } - return r; -} - -const uint8_t* ImageView::code_bytes() const { - return ok_ ? buf_ + hdr_.offset_code : 0; -} - -size_t ImageView::code_len() const { - return ok_ ? hdr_.offset_fb - hdr_.offset_code : 0; -} - -const uint8_t* ImageView::data_bytes() const { - return ok_ ? buf_ + hdr_.offset_data : 0; -} - -size_t ImageView::data_len() const { - return ok_ ? len_ - hdr_.offset_data : 0; -} - -// ---- .stb 文件读写 ---- - -bool write_stb_file(const char* path, const std::vector& image, - std::string* err) { - FILE* f = std::fopen(path, "wb"); - if (f == 0) { - if (err) { - *err = std::string("cannot open for write: ") + path; - } - return false; - } - const bool ok = image.empty() || std::fwrite(&image[0], 1, image.size(), f) == image.size(); - std::fclose(f); - if (!ok && err) { - *err = std::string("write failed: ") + path; - } - return ok; -} - -bool read_stb_file(const char* path, std::vector* image, - std::string* err) { - FILE* f = std::fopen(path, "rb"); - if (f == 0) { - if (err) { - *err = std::string("cannot open for read: ") + path; - } - return false; - } - std::fseek(f, 0, SEEK_END); - const long size = std::ftell(f); - std::fseek(f, 0, SEEK_SET); - if (size < 0) { - std::fclose(f); - if (err) { - *err = "tell failed"; - } - return false; - } - image->resize(static_cast(size)); - const bool ok = size == 0 || std::fread(&(*image)[0], 1, static_cast(size), f) == static_cast(size); - std::fclose(f); - if (!ok && err) { - *err = std::string("read failed: ") + path; - } - return ok; -} - -// ---- sidecar ---- - -std::string make_sidecar(const std::vector& bindings) { - std::string out; - for (size_t i = 0; i < bindings.size(); ++i) { - const IoBinding& b = bindings[i]; - char buf[64]; - out += b.is_input ? "[[io.input]]\n" : "[[io.output]]\n"; - out += "var = \""; - out += b.var; - out += "\"\n"; - std::snprintf(buf, sizeof buf, "slot = %u\n", static_cast(b.slot)); - out += buf; - std::snprintf(buf, sizeof buf, "channel = %u\n", static_cast(b.channel)); - out += buf; - std::snprintf(buf, sizeof buf, "bit = %u\n", static_cast(b.bit)); - out += buf; - out += "\n"; - } - return out; -} - -bool write_sidecar_file(const char* path, - const std::vector& bindings, - std::string* err) { - FILE* f = std::fopen(path, "wb"); - if (f == 0) { - if (err) { - *err = std::string("cannot open for write: ") + path; - } - return false; - } - const std::string s = make_sidecar(bindings); - const bool ok = s.empty() || std::fwrite(s.data(), 1, s.size(), f) == s.size(); - std::fclose(f); - if (!ok && err) { - *err = std::string("write failed: ") + path; - } - return ok; -} - -} // namespace isa diff --git a/tests/src/codegen_test.cpp b/tests/src/codegen_test.cpp index ade3955..4f28b18 100644 --- a/tests/src/codegen_test.cpp +++ b/tests/src/codegen_test.cpp @@ -16,7 +16,7 @@ #include "compiler/Project.h" #include "compiler/Typecheck.h" #include "isa/Encode.h" -#include "isa/Image.h" +#include "compiler/Stb.h" #ifndef REPO_ROOT #define REPO_ROOT "." @@ -123,17 +123,17 @@ static bool test_case01() { std::string err; CHECK(compile_case("01_empty_main", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - CHECK(v.header().cycle_limit == 1000); - CHECK(v.header().dt_ms == 10); - CHECK(v.header().entry_fn_id == 0); - CHECK(v.header().n_funcs == 1); - CHECK(v.header().n_consts == 0); - CHECK(v.header().n_globals == 0); - CHECK(v.header().project_hash != isa::kFnvBasis); + CHECK(v.cycle_limit() == 1000); + CHECK(v.dt_ms() == 10); + CHECK(v.entry_fn_id() == 0); + CHECK(v.n_funcs() == 1); + CHECK(v.n_consts() == 0); + CHECK(v.n_globals() == 0); + CHECK(v.project_hash() != compiler::kFnvBasis); - const isa::FuncRow r = v.func_row(0); + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 8); // 帧基址(调用约定区) CHECK(r.code_len == 1); @@ -150,12 +150,12 @@ static bool test_case02() { std::string err; CHECK(compile_case("02_bool_assign", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - CHECK(v.header().n_funcs == 1); - CHECK(v.header().n_consts == 2); // TRUE 与 FALSE + CHECK(v.n_funcs() == 1); + CHECK(v.n_consts() == 2); // TRUE 与 FALSE - const isa::FuncRow r = v.func_row(0); + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 10); // a, b(r8 起) CHECK(r.code_len == 3); @@ -170,10 +170,10 @@ static bool test_case02() { CHECK(std::strcmp(buf, "RET") == 0); // 常量表:0 = BOOL 1,1 = BOOL 0 - const isa::ConstEntry c0 = v.const_entry(0); - CHECK(c0.tag == isa::types::Bool && c0.value == 1); - const isa::ConstEntry c1 = v.const_entry(1); - CHECK(c1.tag == isa::types::Bool && c1.value == 0); + const compiler::ConstEntry c0 = v.const_entry(0); + CHECK(c0.tag == 0 && c0.value == 1); + const compiler::ConstEntry c1 = v.const_entry(1); + CHECK(c1.tag == 0 && c1.value == 0); return true; } @@ -184,14 +184,14 @@ static bool test_case09() { std::string err; CHECK(compile_case("09_gvl_external", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - CHECK(v.header().n_globals == 1); - CHECK(v.data_len() == 8 + 32); // 8 字节定宽槽 + SHA-256 尾 + CHECK(v.n_globals() == 1); + CHECK(v.data_len() == 8); // 8 字节定宽槽(不含 SHA 尾) CHECK(v.data_bytes()[0] == 5); // G1 初值 5(小端低位) CHECK(v.data_bytes()[1] == 0); - const isa::FuncRow r = v.func_row(0); + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 9); // r8 起:仅局部 x CHECK(r.code_len == 2); @@ -221,11 +221,11 @@ static bool test_io_ops() { "END_PROGRAM\n"; CHECK(compile_src("io", io_extra, globals_st, main_st, &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - CHECK(v.header().n_globals == 2); + CHECK(v.n_globals() == 2); - const isa::FuncRow r = v.func_row(0); + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 10); // r8 起:q + 1 临时 char buf[64]; @@ -258,10 +258,10 @@ static bool test_layout() { "END_PROGRAM\n"; CHECK(compile_src("layout", "", globals_st, main_st, &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - CHECK(v.header().n_globals == 3); - CHECK(v.data_len() == 24 + 32); // 3 槽 × 8 字节定宽 + SHA-256 尾 + CHECK(v.n_globals() == 3); + CHECK(v.data_len() == 24); // 3 槽 × 8 字节定宽 CHECK(v.data_bytes()[0] == 0); // B 无初值 CHECK(v.data_bytes()[8] == 0x2C && v.data_bytes()[9] == 0x01); // I = 300(槽 1) CHECK(v.data_bytes()[16] == 10); // T = 10ms(槽 2) @@ -299,9 +299,9 @@ static bool test_case03() { std::string err; CHECK(compile_case("03_short_circuit", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - const isa::FuncRow r = v.func_row(0); + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 12); // r8 起:a b x + 1 临时 CHECK(r.code_len == 9); @@ -342,9 +342,9 @@ static bool test_not() { "END_PROGRAM\n"; CHECK(compile_src("not", "", "", main_st, &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - const isa::FuncRow r = v.func_row(0); + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 11); // r8 起:a x + 1 临时 CHECK(r.code_len == 3); @@ -367,9 +367,9 @@ static bool test_case04() { std::string err; CHECK(compile_case("04_if_elsif_else", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - const isa::FuncRow r = v.func_row(0); + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 13); // r8 起:sel out + 3 临时 CHECK(r.code_len == 14); @@ -417,9 +417,9 @@ static bool test_case05() { std::string err; CHECK(compile_case("05_while_normal", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - const isa::FuncRow r = v.func_row(0); + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 12); // r8 起:n + 3 临时(条件结果 r9 + 两操作数) CHECK(r.code_len == 10); @@ -458,9 +458,9 @@ static bool test_case07() { std::string err; CHECK(compile_case("07_int_arith", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - const isa::FuncRow r = v.func_row(0); + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 14); // r8 起:a b c eq + 2 临时 char buf[64]; @@ -485,15 +485,15 @@ static bool test_case08() { std::string err; CHECK(compile_case("08_time_literal", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - CHECK(v.header().n_consts == 2); - const isa::ConstEntry c0 = v.const_entry(0); - CHECK(c0.tag == isa::types::Time && c0.value == 10); // T#10ms - const isa::ConstEntry c1 = v.const_entry(1); - CHECK(c1.tag == isa::types::Time && c1.value == 1250); // T#1s250ms + CHECK(v.n_consts() == 2); + const compiler::ConstEntry c0 = v.const_entry(0); + CHECK(c0.tag == 2 && c0.value == 10); // T#10ms + const compiler::ConstEntry c1 = v.const_entry(1); + CHECK(c1.tag == 2 && c1.value == 1250); // T#1s250ms - const isa::FuncRow r = v.func_row(0); + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 10); // r8 起 char buf[64]; const uint32_t* ins = reinterpret_cast(v.code_bytes()); @@ -511,15 +511,15 @@ static bool test_case13() { std::string err; CHECK(compile_case("13_function_call", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - CHECK(v.header().n_funcs == 2); - CHECK(v.header().entry_fn_id == 1); // MAIN 是第二个 POU + CHECK(v.n_funcs() == 2); + CHECK(v.entry_fn_id() == 1); // MAIN 是第二个 POU char buf[64]; const uint8_t* base = v.code_bytes(); // Add(fn_id 0):结果 r0、输入 r1(a) r2(b)、临时 r8/r9 - const isa::FuncRow fa = v.func_row(0); + const compiler::StbView::FuncRow fa = v.func_row(0); CHECK(fa.nregs == 10); CHECK(fa.code_len == 4); const uint32_t* ia = reinterpret_cast(base); @@ -533,7 +533,7 @@ static bool test_case13() { CHECK(std::strcmp(buf, "RET") == 0); // MAIN(fn_id 1):x 在 r8,实参临时 r9/r10 - const isa::FuncRow fm = v.func_row(1); + const compiler::StbView::FuncRow fm = v.func_row(1); CHECK(fm.nregs == 11); CHECK(fm.code_len == 7); const uint32_t* im = reinterpret_cast(base) + fm.code_offset / 4; @@ -561,13 +561,13 @@ static bool test_case15() { std::string err; CHECK(compile_case("15_fb_instance", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - CHECK(v.header().n_funcs == 2); // FB 占位 + MAIN - CHECK(v.header().entry_fn_id == 1); - CHECK(v.data_len() == 24 + 32); // 实例 3 槽 × 8 字节定宽 + SHA-256 尾 + CHECK(v.n_funcs() == 2); // FB 占位 + MAIN + CHECK(v.entry_fn_id() == 1); + CHECK(v.data_len() == 24); // 实例 3 槽 × 8 字节定宽 - const isa::FuncRow fm = v.func_row(1); + const compiler::StbView::FuncRow fm = v.func_row(1); CHECK(fm.nregs == 12); CHECK(fm.code_len == 12); const uint32_t* im = reinterpret_cast(v.code_bytes()) + fm.code_offset / 4; @@ -601,10 +601,10 @@ static bool test_case17() { std::string err; CHECK(compile_case("17_ton", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - CHECK(v.data_len() == 32 + 32); // in@0 pt@8 q@16 et@24 + SHA-256 尾 - const isa::FuncRow r = v.func_row(0); + CHECK(v.data_len() == 32); // in@0 pt@8 q@16 et@24 + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 11); const uint32_t* ins = reinterpret_cast(v.code_bytes()); char buf[64]; @@ -630,10 +630,10 @@ static bool test_case18() { std::string err; CHECK(compile_case("18_tof_ctu", &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - CHECK(v.data_len() == 72 + 32); // tf 4 槽 + c 5 槽 = 9 槽 × 8 + SHA-256 尾 - const isa::FuncRow r = v.func_row(0); + CHECK(v.data_len() == 72); // tf 4 槽 + c 5 槽 = 9 槽 × 8 + const compiler::StbView::FuncRow r = v.func_row(0); CHECK(r.nregs == 14); const uint32_t* ins = reinterpret_cast(v.code_bytes()); char buf[64]; @@ -670,14 +670,14 @@ static bool test_line1() { CHECK(load_cfg(&cfg)); CHECK(codegen_project(p, units, link, cfg, &img, &err)); - const isa::ImageView v = isa::ImageView::from(img); + const compiler::StbView v = compiler::StbView::from(img); CHECK(v.ok()); - CHECK(v.header().n_globals == 4); - CHECK(v.header().n_funcs == 2); - CHECK(v.header().entry_fn_id == 1); - CHECK(v.data_len() == 56 + 32); // 7 槽 × 8 字节定宽 + SHA-256 尾 + CHECK(v.n_globals() == 4); + CHECK(v.n_funcs() == 2); + CHECK(v.entry_fn_id() == 1); + CHECK(v.data_len() == 56); // 7 槽 × 8 字节定宽 - const isa::FuncRow fm = v.func_row(1); + const compiler::StbView::FuncRow fm = v.func_row(1); CHECK(fm.nregs == 13); CHECK(fm.code_len == 17); const uint32_t* im = reinterpret_cast(v.code_bytes()) + fm.code_offset / 4; diff --git a/tests/src/isa_test.cpp b/tests/src/isa_test.cpp index 6588332..5583c14 100644 --- a/tests/src/isa_test.cpp +++ b/tests/src/isa_test.cpp @@ -12,7 +12,6 @@ #include #include "isa/Encode.h" -#include "isa/Image.h" #include "isa/Instr.h" #include "isa/Op.h" #include "isa/Types.h" @@ -127,114 +126,11 @@ static bool test_encode() { return true; } -// ---- 5. FNV-1a 64 ---- - -static bool test_fnv() { - using namespace isa; - CHECK(fnv1a64(0, 0) == kFnvBasis); - const uint8_t a1[] = {'a'}; - CHECK(fnv1a64(a1, 1) == 0xaf63dc4c8601ec8cull); - return true; -} - -// ---- 6. 映像:write_ret_main → ImageView ---- - -static bool test_image() { - using namespace isa; - const uint64_t hash = 0x123456789abcdef0ull; - std::vector img = write_ret_main(100000, 10, hash); - - ImageView v = ImageView::from(img); - CHECK(v.ok()); - CHECK(v.error().empty()); - CHECK(v.header().cycle_limit == 100000); - CHECK(v.header().dt_ms == 10); - CHECK(v.header().project_hash == hash); - CHECK(v.header().entry_fn_id == 0); - CHECK(v.header().n_funcs == 1); - CHECK(v.header().n_globals == 0); - CHECK(v.header().n_i == 0); - CHECK(v.header().n_q == 0); - CHECK(v.header().n_m == 0); - CHECK(v.header().offset_const == kHeaderSize); - CHECK(v.header().offset_data == kHeaderSize + kFuncRowSize + 4); - CHECK(v.code_len() == 4); - CHECK(v.data_len() == 0); - - const FuncRow r = v.func_row(0); - CHECK(r.nregs == 0); - CHECK(r.code_offset == 0); - CHECK(r.code_len == 1); - - char buf[32]; - disasm(v.code_bytes()[0], buf, sizeof buf); - CHECK(std::strcmp(buf, "RET") == 0); - - // 损坏映像必须拒绝 - std::vector bad = img; - bad[0] = 'X'; - CHECK(!ImageView::from(bad).ok()); - std::vector bad2 = img; - bad2[60] = 255; // offset_code 越界 - CHECK(!ImageView::from(bad2).ok()); - std::vector bad3 = img; - bad3[48] = 2; // n_funcs=2 但表只有 1 行 - CHECK(!ImageView::from(bad3).ok()); - std::vector bad4 = img; - bad4[24] = 1; // entry_fn_id 越界 - CHECK(!ImageView::from(bad4).ok()); - std::vector short_img = img; - short_img.resize(kHeaderSize - 1); - CHECK(!ImageView::from(short_img).ok()); - return true; -} - -// ---- 7. .stb 文件与 sidecar ---- - -static bool test_files() { - using namespace isa; - std::vector img = write_ret_main(100000, 10, 0); - - const char* stb_path = "isa_test_tmp.stb"; - std::string err; - CHECK(write_stb_file(stb_path, img, &err)); - std::vector back; - CHECK(read_stb_file(stb_path, &back, &err)); - CHECK(back == img); - CHECK(ImageView::from(back).ok()); - std::remove(stb_path); - - std::vector bs; - IoBinding b1; - b1.var = "I0_0"; b1.slot = 1; b1.channel = 0; b1.bit = 0; b1.is_input = true; - IoBinding b2; - b2.var = "Q0_0"; b2.slot = 3; b2.channel = 0; b2.bit = 0; b2.is_input = false; - bs.push_back(b1); - bs.push_back(b2); - - const std::string sc = make_sidecar(bs); - CHECK(sc.find("[[io.input]]") == 0); - CHECK(sc.find("var = \"I0_0\"") != std::string::npos); - CHECK(sc.find("slot = 1") != std::string::npos); - CHECK(sc.find("channel = 0") != std::string::npos); - CHECK(sc.find("[[io.output]]") != std::string::npos); - CHECK(sc.find("var = \"Q0_0\"") != std::string::npos); - CHECK(sc.find("slot = 3") != std::string::npos); - - const char* sc_path = "isa_test_tmp.runtime.toml"; - CHECK(write_sidecar_file(sc_path, bs, &err)); - std::remove(sc_path); - return true; -} - int main() { if (!test_sat()) return 1; if (!test_op()) return 1; if (!test_instr()) return 1; if (!test_encode()) return 1; - if (!test_fnv()) return 1; - if (!test_image()) return 1; - if (!test_files()) return 1; std::printf("isa_test: %d checks passed\n", g_checks); return 0; } diff --git a/tests/src/vm_test.cpp b/tests/src/vm_test.cpp index a968942..8a9f77e 100644 --- a/tests/src/vm_test.cpp +++ b/tests/src/vm_test.cpp @@ -15,7 +15,6 @@ #include "compiler/Project.h" #include "compiler/Typecheck.h" #include "isa/Encode.h" -#include "isa/Image.h" #include "isa/Instr.h" #include "isa/Op.h" #include "vm/Machine.h" @@ -93,7 +92,7 @@ struct HFunc { uint32_t nregs = 8; }; -static std::vector hand_image(const std::vector& consts, +static std::vector hand_image(const std::vector& consts, const std::vector& funcs, uint32_t entry = 0, uint32_t cycle_limit = 100000, @@ -102,11 +101,11 @@ static std::vector hand_image(const std::vector& const for (const HFunc& f : funcs) { code_total += f.code.size() * 4; } - const uint32_t off_const = 72; + const uint32_t off_const = 104; const uint32_t off_funcs = off_const + static_cast(consts.size()) * 12; const uint32_t off_code = off_funcs + static_cast(funcs.size()) * 12; const uint32_t off_data = off_code + static_cast(code_total); - const uint32_t off_end = off_data + static_cast(data.size()); + const uint32_t off_end = off_data + static_cast(data.size()) + 32; // SHA 尾占位 std::vector b(off_end, 0); auto put32 = [&](size_t o, uint32_t v) { @@ -120,8 +119,8 @@ static std::vector hand_image(const std::vector& const b[o + i] = static_cast((v >> (8 * i)) & 0xFFu); } }; - put32(0, isa::kMagic); - put32(4, isa::kVersion); + put32(0, 0x43545353u); + put32(4, 1u); put32(8, cycle_limit); put32(12, 10); // dt_ms put32(24, entry); @@ -163,10 +162,10 @@ static std::vector hand_image(const std::vector& const static bool test_hand_scalar() { // r8 := 5;r9 := r8 + 3;槽 0 ← r9;槽 1 → r10;JT 跳过一条 - const std::vector consts = { - {isa::types::Int, 5}, - {isa::types::Int, 3}, - {isa::types::Int, 1}, + const std::vector consts = { + {1, 5}, + {1, 3}, + {1, 1}, }; const std::vector funcs = {{ { @@ -201,9 +200,9 @@ static bool test_hand_scalar() { static bool test_hand_call() { // fn0(入口):r8=5、r2=7、实参 r1←r8;CALL 1;结果 r0 → r8 // fn1:r0 = r1 + r2(r1/r2 来自调用约定区复制) - const std::vector consts = { - {isa::types::Int, 5}, - {isa::types::Int, 7}, + const std::vector consts = { + {1, 5}, + {1, 7}, }; const std::vector funcs = { {{ diff --git a/vm/CMakeLists.txt b/vm/CMakeLists.txt index 6f39576..c7a06ae 100644 --- a/vm/CMakeLists.txt +++ b/vm/CMakeLists.txt @@ -7,7 +7,8 @@ project(VM DESCRIPTION "寄存器虚拟机") add_library(vm STATIC - ./src/Machine.cpp) + ./src/Machine.cpp + ./src/Image.cpp) target_include_directories(vm PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_link_libraries(vm PUBLIC isa) diff --git a/vm/include/vm/Image.h b/vm/include/vm/Image.h new file mode 100644 index 0000000..d899354 --- /dev/null +++ b/vm/include/vm/Image.h @@ -0,0 +1,78 @@ +/** + * @file Image.h + * @brief vm 自带的 .stb 只读视图(执行器侧;compiler 各有实现) + * @author + * @date 2026-08-21 + * + * @details 格式契约见 Doc/isa/指令与映像.md(12.13 修订:头 104 = 72 + 型号标识[32], + * 文件尾 SHA-256[32])。步骤 7:解析头与段;步骤 8:补型号匹配与 SHA-256 校验。 + */ + +#pragma once + +#include +#include +#include +#include + +namespace vm { + + // 映像头(字段与 Doc/isa/指令与映像.md 一致) + struct ImageHeader { + uint32_t cycle_limit = 0; + uint32_t dt_ms = 0; + uint64_t project_hash = 0; + uint32_t entry_fn_id = 0; + uint32_t n_globals = 0; + uint32_t n_i = 0; + uint32_t n_q = 0; + uint32_t n_m = 0; + uint32_t n_consts = 0; + uint32_t n_funcs = 0; + uint32_t offset_const = 0; + uint32_t offset_funcs = 0; + uint32_t offset_code = 0; + uint32_t offset_fb = 0; + uint32_t offset_data = 0; + }; + + struct FuncRow { + uint32_t nregs = 0; + uint32_t code_offset = 0; // 相对字节码段起点(字节) + uint32_t code_len = 0; // 指令条数 + }; + + struct ConstEntry { + uint32_t tag = 0; + uint64_t value = 0; + }; + + // 只读视图:校验过的映像(指向外部缓冲) + class Image { + public: + static Image from(const uint8_t* buf, size_t len); + static Image from(const std::vector& buf); + + bool ok() const { return ok_; } + const std::string& error() const { return err_; } + const ImageHeader& header() const { return hdr_; } + + FuncRow func_row(size_t i) const; + ConstEntry const_entry(size_t i) const; + + const uint8_t* code_bytes() const; // 字节码段起点 + const uint8_t* data_bytes() const; // 数据段起点 + size_t data_len() const; // 字节数 + + public: + // 默认构造为无效态(ok() == false) + Image() : buf_(nullptr), len_(0) {} + + private: + const uint8_t* buf_; + size_t len_; + bool ok_ = false; + std::string err_; + ImageHeader hdr_; + }; +} diff --git a/vm/include/vm/Machine.h b/vm/include/vm/Machine.h index 9a63669..a3f4ba5 100644 --- a/vm/include/vm/Machine.h +++ b/vm/include/vm/Machine.h @@ -19,7 +19,7 @@ #include #include -#include "isa/Image.h" +#include "vm/Image.h" #include "isa/Instr.h" namespace vm { @@ -67,7 +67,7 @@ namespace vm { bool ended() const; /** @brief 映像头(dt_ms / cycle_limit 等) */ - const isa::ImageHeader& header() const; + const vm::ImageHeader& header() const; /** @brief 当前指令下标(相对当前函数字节码段) */ uint32_t pc() const; @@ -105,7 +105,7 @@ namespace vm { uint32_t ret_fn_id = 0; // 返回目标函数 }; - isa::ImageView image_; // 映像只读视图 + vm::Image image_; // 映像只读视图(vm 自实现) std::vector data_; // 数据区工作副本(8 字节定宽槽) std::vector frames_; // 调用栈([0] = MAIN,跨周期保留) // 边沿检测上次输入(每槽 2 字节:[slot*2] 第一边沿、[slot*2+1] 第二边沿; diff --git a/vm/src/Image.cpp b/vm/src/Image.cpp new file mode 100644 index 0000000..54bcd4c --- /dev/null +++ b/vm/src/Image.cpp @@ -0,0 +1,151 @@ +/** + * @file Image.cpp + * @brief vm 自带的 .stb 只读视图(执行器侧) + * @author + * @date 2026-08-21 + */ + +#include "vm/Image.h" + +namespace vm { + +namespace { + + const uint32_t kMagic = 0x43545353u; // "STSC" 小端 + const uint32_t kVersion = 1; + const size_t kHeaderSize = 104; + const size_t kConstEntrySize = 12; + const size_t kFuncRowSize = 12; + const size_t kSha256Size = 32; // 文件尾(步骤 8 校验) + + uint32_t get_le32(const uint8_t* p) { + return static_cast(p[0]) + | (static_cast(p[1]) << 8) + | (static_cast(p[2]) << 16) + | (static_cast(p[3]) << 24); + } + + uint64_t get_le64(const uint8_t* p) { + uint64_t v = 0; + for (int i = 0; i < 8; ++i) { + v |= static_cast(p[i]) << (8 * i); + } + return v; + } + +} // namespace + +Image Image::from(const uint8_t* buf, size_t len) { + Image v; + v.buf_ = buf; + v.len_ = len; + if (buf == nullptr) { + v.err_ = "null buffer"; + return v; + } + if (len < kHeaderSize) { + v.err_ = "image too short"; + return v; + } + if (get_le32(buf + 0) != kMagic) { + v.err_ = "bad magic"; + return v; + } + if (get_le32(buf + 4) != kVersion) { + v.err_ = "bad version"; + return v; + } + ImageHeader& h = v.hdr_; + h.cycle_limit = get_le32(buf + 8); + h.dt_ms = get_le32(buf + 12); + h.project_hash = get_le64(buf + 16); + h.entry_fn_id = get_le32(buf + 24); + h.n_globals = get_le32(buf + 28); + h.n_i = get_le32(buf + 32); + h.n_q = get_le32(buf + 36); + h.n_m = get_le32(buf + 40); + h.n_consts = get_le32(buf + 44); + h.n_funcs = get_le32(buf + 48); + h.offset_const = get_le32(buf + 52); + h.offset_funcs = get_le32(buf + 56); + h.offset_code = get_le32(buf + 60); + h.offset_fb = get_le32(buf + 64); + h.offset_data = get_le32(buf + 68); + + // 段校验(数据段之后是 SHA-256 文件尾;步骤 8 做校验,这里仅保证有尾) + if (len < static_cast(h.offset_data) + kSha256Size) { + v.err_ = "missing sha256 tail"; + return v; + } + const uint64_t offs[5] = {h.offset_const, h.offset_funcs, h.offset_code, h.offset_fb, + h.offset_data}; + for (int i = 0; i < 5; ++i) { + if (offs[i] < kHeaderSize || offs[i] > len - kSha256Size) { + v.err_ = "segment offset out of range"; + return v; + } + if (i > 0 && offs[i] < offs[i - 1]) { + v.err_ = "segment offsets not monotonic"; + return v; + } + } + if (offs[1] - offs[0] != static_cast(h.n_consts) * kConstEntrySize) { + v.err_ = "const table size mismatch"; + return v; + } + if (offs[2] - offs[1] != static_cast(h.n_funcs) * kFuncRowSize) { + v.err_ = "function table size mismatch"; + return v; + } + if ((h.offset_fb - h.offset_code) % 4 != 0) { + v.err_ = "code segment not 4-byte aligned"; + return v; + } + if (h.entry_fn_id >= h.n_funcs && h.n_funcs != 0) { + v.err_ = "entry fn_id out of range"; + return v; + } + v.ok_ = true; + v.err_.clear(); + return v; +} + +Image Image::from(const std::vector& buf) { + return from(buf.data(), buf.size()); +} + +FuncRow Image::func_row(size_t i) const { + FuncRow r; + if (ok_ && i < hdr_.n_funcs) { + const uint8_t* p = buf_ + hdr_.offset_funcs + i * kFuncRowSize; + r.nregs = get_le32(p + 0); + r.code_offset = get_le32(p + 4); + r.code_len = get_le32(p + 8); + } + return r; +} + +ConstEntry Image::const_entry(size_t i) const { + ConstEntry e; + if (ok_ && i < hdr_.n_consts) { + const uint8_t* p = buf_ + hdr_.offset_const + i * kConstEntrySize; + e.tag = get_le32(p); + e.value = get_le64(p + 4); + } + return e; +} + +const uint8_t* Image::code_bytes() const { + return ok_ ? buf_ + hdr_.offset_code : nullptr; +} + +const uint8_t* Image::data_bytes() const { + return ok_ ? buf_ + hdr_.offset_data : nullptr; +} + +size_t Image::data_len() const { + // 步骤 7:含 SHA 尾(步骤 8 收紧并校验) + return ok_ ? len_ - hdr_.offset_data : 0; +} + +} // namespace vm diff --git a/vm/src/Machine.cpp b/vm/src/Machine.cpp index 8493be0..2753b58 100644 --- a/vm/src/Machine.cpp +++ b/vm/src/Machine.cpp @@ -25,7 +25,7 @@ namespace vm { bool Machine::create(const std::vector& image, Machine* out, std::string* err) { - out->image_ = isa::ImageView::from(image); + out->image_ = vm::Image::from(image); if (!out->image_.ok()) { if (err) { *err = out->image_.error(); @@ -39,7 +39,7 @@ bool Machine::create(const std::vector& image, Machine* out, // MAIN 帧(跨周期保留) const uint32_t entry = out->image_.header().entry_fn_id; - const isa::FuncRow main = out->image_.func_row(entry); + const vm::FuncRow main = out->image_.func_row(entry); out->frames_.clear(); Frame f; f.fn_id = entry; @@ -79,7 +79,7 @@ bool Machine::step() { Fault Machine::fault() const { return fault_; } bool Machine::ended() const { return ended_; } -const isa::ImageHeader& Machine::header() const { return image_.header(); } +const vm::ImageHeader& Machine::header() const { return image_.header(); } 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_; } @@ -94,7 +94,7 @@ uint32_t Machine::nregs() const { } isa::Instr Machine::cur_instr() const { - const isa::FuncRow row = image_.func_row(cur_frame().fn_id); + const vm::FuncRow row = image_.func_row(cur_frame().fn_id); const uint8_t* base = image_.code_bytes() + row.code_offset; if (pc_ >= row.code_len) { return isa::pack(isa::Op::RET, 0, 0, 0); @@ -107,7 +107,7 @@ 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); + const vm::FuncRow row = image_.func_row(cur_frame().fn_id); if (pc_ >= row.code_len) { fault_ = Fault::BadOp; return false; @@ -165,7 +165,7 @@ bool Machine::exec_one() { fault_ = Fault::BadConst; return false; } - const isa::ConstEntry c = image_.const_entry(cid); + const vm::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) { @@ -310,7 +310,7 @@ Fault Machine::do_call(uint32_t fn_id) { if (frames_.size() >= 64) { return Fault::StackOverflow; } - const isa::FuncRow row = image_.func_row(fn_id); + const vm::FuncRow row = image_.func_row(fn_id); Frame f; f.fn_id = fn_id; f.regs.assign(row.nregs, 0);