阶段 B 步骤 4:compiler 配置驱动化,去除 isa 依赖。

- Project.h 自带 IoBinding;Stb.h/cpp:compiler 侧 .stb 规范(常量/ConstEntry/FNV/StbView/读写/sidecar)
- Codec.h/cpp:指令字 pack/字段/配置驱动 disasm(format 表驱动)
- Codegen:opcode 全查 MachineConfig(E_* 发射器)、常量 tag 查配置类型、初值按基元宽度写、
  映像拼装用 Stb 常量;codegen_project 增加 cfg 参数
- main.cpp:--machine <path>(编译/反汇编必填),--disasm 用 StbView+Codec
- CMake:compiler 不再链接 isa(仅 toml++ 私有);测试补链 isa(自身断言用)
- 验证:20 用例字节不变(hash 0xc3fe4ae74ad45900 相同)、ctest 12/12、缺 --machine 报错退出
This commit is contained in:
2026-08-21 22:14:29 +08:00
parent 44b5ecd46d
commit 447a8d0119
15 changed files with 739 additions and 390 deletions
+57 -35
View File
@@ -12,67 +12,66 @@
#include <string>
#include <vector>
#include "compiler/Codec.h"
#include "compiler/Codegen.h"
#include "compiler/Linker.h"
#include "compiler/MachineConfig.h"
#include "compiler/Project.h"
#include "compiler/Stb.h"
#include "compiler/Typecheck.h"
#include "isa/Encode.h"
#include "isa/Image.h"
namespace {
void usage() {
std::printf("usage: STCompiler <project.toml> [-o <name>.stb]\n"
" STCompiler <name>.stb --disasm\n"
std::printf("usage: STCompiler <project.toml> [-o <name>.stb] --machine <machine.toml>\n"
" STCompiler <name>.stb --disasm --machine <machine.toml>\n"
" 解析工程并编译(词法 → 语法 → 链接 → 类型 → 寄存器码)\n"
" -o <name>.stb 编译并写出映像文件\n"
" 无 -o 只打印文件集合与工程哈希(12.3 阶段\n"
" --disasm 反汇编一个已编译的 .stb 映像\n"
" --machine <path> 机器定义(machine.toml,编译路径必填\n"
" --disasm 反汇编一个已编译的 .stb 映像(需要 --machine\n"
" --help 打印本帮助\n");
}
// 反汇编一个已编译映像(函数表逐条 + 常量表 + 数据段摘要)。
// 映像无符号表,按 fn_id / 槽号显示;指令偏移为文件绝对字节偏移。
int dump_image(const char* path) {
// 指令偏移为文件绝对字节偏移;反汇编按 machine.toml 的 format 输出
int dump_image(const char* path, const compiler::MachineConfig& cfg) {
std::vector<uint8_t> bytes;
std::string err;
if (!isa::read_stb_file(path, &bytes, &err)) {
if (!compiler::read_stb_file(path, &bytes, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
const isa::ImageView v = isa::ImageView::from(bytes);
const compiler::StbView v = compiler::StbView::from(bytes);
if (!v.ok()) {
std::fprintf(stderr, "error: %s\n", v.error().c_str());
return 1;
}
const isa::ImageHeader& h = v.header();
std::printf("image: %s (%zu bytes, %u functions, %u globals, entry fn %u)\n",
path, bytes.size(), h.n_funcs, h.n_globals, h.entry_fn_id);
std::printf(" dt_ms=%u cycle_limit=%u hash=0x%016llx\n", h.dt_ms,
h.cycle_limit, static_cast<unsigned long long>(h.project_hash));
path, bytes.size(), v.n_funcs(), v.n_globals(), v.entry_fn_id());
std::printf(" dt_ms=%u cycle_limit=%u hash=0x%016llx\n", v.dt_ms(),
v.cycle_limit(), static_cast<unsigned long long>(v.project_hash()));
if (h.n_consts) {
if (v.n_consts()) {
std::printf("constants:\n");
for (uint32_t i = 0; i < h.n_consts; ++i) {
const isa::ConstEntry c = v.const_entry(i);
const char* tag = c.tag == isa::types::Bool ? "BOOL"
: c.tag == isa::types::Int ? "INT"
: "TIME";
for (uint32_t i = 0; i < v.n_consts(); ++i) {
const compiler::ConstEntry c = v.const_entry(i);
const char* tag = c.tag == 0 ? "BOOL" : c.tag == 1 ? "INT" : "TIME";
std::printf(" [%u] %s %llu\n", i, tag,
static_cast<unsigned long long>(c.value));
}
}
std::printf("functions:\n");
for (uint32_t i = 0; i < h.n_funcs; ++i) {
const isa::FuncRow r = v.func_row(i);
for (uint32_t i = 0; i < v.n_funcs(); ++i) {
const compiler::StbView::FuncRow r = v.func_row(i);
std::printf(" fn %u: nregs=%u, offset=%u, len=%u\n", i, r.nregs,
r.code_offset, r.code_len);
const uint8_t* base = v.code_bytes() + r.code_offset;
for (uint32_t j = 0; j < r.code_len; ++j) {
char buf[64];
isa::disasm(reinterpret_cast<const uint32_t*>(base)[j], buf, sizeof buf);
compiler::disasm(cfg, reinterpret_cast<const uint32_t*>(base)[j], buf,
sizeof buf);
std::printf(" 0x%04x %s\n",
h.offset_code + r.code_offset + j * 4, buf);
v.offset_code() + r.code_offset + j * 4, buf);
}
}
@@ -102,13 +101,37 @@ int main(int argc, char** argv) {
return 0;
}
// --disasm:第一参数是 .stb 路径,不重新编译
// 参数收集
std::string machine_path;
bool disasm_mode = false;
for (int i = 2; i + 1 < argc; ++i) {
if (std::strcmp(argv[i], "--machine") == 0) {
machine_path = argv[i + 1];
}
}
for (int i = 1; i < argc; ++i) {
if (std::strcmp(argv[i], "--disasm") == 0) {
return dump_image(argv[1]);
disasm_mode = true;
}
}
// 机器定义(编译与反汇编都需要;加载/校验失败报错退出)
if (machine_path.empty()) {
std::fprintf(stderr, "error: missing --machine <machine.toml>\n");
usage();
return 1;
}
compiler::MachineConfig cfg;
std::string err;
if (!cfg.load(machine_path, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
if (disasm_mode) {
return dump_image(argv[1], cfg);
}
const std::string toml_path = argv[1];
std::string out_path;
for (int i = 2; i + 1 < argc; ++i) {
@@ -118,7 +141,6 @@ int main(int argc, char** argv) {
}
compiler::Project proj;
std::string err;
if (!compiler::parse_project(toml_path, &proj, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
@@ -160,19 +182,19 @@ int main(int argc, char** argv) {
return 1;
}
std::vector<uint8_t> image;
if (!compiler::codegen_project(proj, units, link, &image, &err)) {
if (!compiler::codegen_project(proj, units, link, cfg, &image, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
if (!isa::write_stb_file(out_path.c_str(), image, &err)) {
if (!compiler::write_stb_file(out_path.c_str(), image, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
// sidecarI/O 绑定 var → 槽号 → channel/bit(不进映像,执行器采样用)
std::vector<isa::IoBinding> bindings;
for (const isa::IoBinding& b : proj.io) {
isa::IoBinding out_b = b;
std::vector<compiler::IoBinding> bindings;
for (const compiler::IoBinding& b : proj.io) {
compiler::IoBinding out_b = b;
std::string key = b.var;
for (char& ch : key) {
ch = static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
@@ -185,13 +207,13 @@ int main(int argc, char** argv) {
}
std::filesystem::path sidecar = std::filesystem::path(out_path);
sidecar.replace_extension(".runtime.toml");
if (!isa::write_sidecar_file(sidecar.string().c_str(), bindings, &err)) {
if (!compiler::write_sidecar_file(sidecar.string().c_str(), bindings, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
const isa::ImageView v = isa::ImageView::from(image);
const compiler::StbView v = compiler::StbView::from(image);
std::printf("compiled: %s (%zu bytes, %u functions, %u globals)\n",
out_path.c_str(), image.size(), v.header().n_funcs, v.header().n_globals);
out_path.c_str(), image.size(), v.n_funcs(), v.n_globals());
return 0;
}