Files
Interpreter/compiler/src/main.cpp
T
Admin a5f49caa94 阶段 D 步骤 9:CLI 接线收尾(--machine 仅编译/反汇编必填)。
- 打印模式(无 -o)不再要求 --machine(恢复 12.3 行为)
- 编译路径与 --disasm 必填 --machine,加载/校验失败报错退出
- 验证:打印/编译/disasm/缺参四种模式行为正确;ctest 12/12
2026-08-21 22:30:44 +08:00

242 lines
8.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file main.cpp
* @brief STCompiler 可执行入口
* @author
* @date 2026-08-21
*/
#include <cctype>
#include <cstdio>
#include <cstring>
#include <filesystem>
#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"
namespace {
void usage() {
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"
" --machine <path> 机器定义(machine.toml,编译路径必填)\n"
" --disasm 反汇编一个已编译的 .stb 映像(需要 --machine\n"
" --help 打印本帮助\n");
}
// 反汇编一个已编译映像(函数表逐条 + 常量表 + 数据段摘要)。
// 指令偏移为文件绝对字节偏移;反汇编按 machine.toml 的 format 输出。
int dump_image(const char* path, const compiler::MachineConfig& cfg) {
std::vector<uint8_t> bytes;
std::string err;
if (!compiler::read_stb_file(path, &bytes, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
const compiler::StbView v = compiler::StbView::from(bytes);
if (!v.ok()) {
std::fprintf(stderr, "error: %s\n", v.error().c_str());
return 1;
}
std::printf("image: %s (%zu bytes, %u functions, %u globals, entry fn %u)\n",
path, bytes.size(), v.n_funcs(), v.n_globals(), v.entry_fn_id());
std::printf(" dt_ms=%u cycle_limit=%u hash=0x%016llx model=%s sha=%s\n",
v.dt_ms(), v.cycle_limit(),
static_cast<unsigned long long>(v.project_hash()),
v.model_id().c_str(), v.sha_ok() ? "ok" : "BAD");
if (v.n_consts()) {
std::printf("constants:\n");
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 < 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];
compiler::disasm(cfg, reinterpret_cast<const uint32_t*>(base)[j], buf,
sizeof buf);
std::printf(" 0x%04x %s\n",
v.offset_code() + r.code_offset + j * 4, buf);
}
}
if (v.data_len()) {
std::printf("data (%zu bytes):\n", v.data_len());
const uint8_t* d = v.data_bytes();
for (size_t i = 0; i < v.data_len(); i += 16) {
std::printf(" 0x%04x:", static_cast<unsigned>(i));
for (size_t j = 0; j < 16 && i + j < v.data_len(); ++j) {
std::printf(" %02x", d[i + j]);
}
std::printf("\n");
}
}
return 0;
}
}
int main(int argc, char** argv) {
if (argc < 2) {
std::printf("STCompiler 0.1\n");
usage();
return 0;
}
if (std::strcmp(argv[1], "--help") == 0) {
usage();
return 0;
}
// 参数收集
std::string machine_path;
std::string out_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];
} else if (std::strcmp(argv[i], "-o") == 0) {
out_path = argv[i + 1];
}
}
for (int i = 1; i < argc; ++i) {
if (std::strcmp(argv[i], "--disasm") == 0) {
disasm_mode = true;
}
}
// --disasm:需要机器定义(反汇编按 machine.toml 的 format 输出)
if (disasm_mode) {
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;
}
return dump_image(argv[1], cfg);
}
const std::string toml_path = argv[1];
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;
}
const std::vector<std::string> files = compiler::compile_files(proj);
// 打印模式(无 -o):不需要机器定义
if (out_path.empty()) {
uint64_t hash = 0;
if (!compiler::compute_project_hash(proj, &hash, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
std::printf("project: %s\n", proj.name.c_str());
std::printf("files:\n");
for (const std::string& f : files) {
std::printf(" %s\n", f.c_str());
}
std::printf("hash: 0x%016llx\n", static_cast<unsigned long long>(hash));
return 0;
}
// 编译路径:机器定义必填(编码/类型/FB 布局来自 machine.toml
if (machine_path.empty()) {
std::fprintf(stderr, "error: missing --machine <machine.toml>\n");
usage();
return 1;
}
compiler::MachineConfig cfg;
if (!cfg.load(machine_path, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
// 完整管线:读 .st → 链接 → 类型检查 → 寄存器码
std::vector<compiler::SourceUnit> units;
for (const std::string& f : files) {
compiler::SourceUnit u;
if (!compiler::load_unit(proj.base_dir + "/" + f, &u, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
units.push_back(std::move(u));
}
compiler::LinkResult link;
if (!compiler::link_project(proj, units, &link, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
if (!compiler::check_project(proj, units, link, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
std::vector<uint8_t> image;
if (!compiler::codegen_project(proj, units, link, cfg, &image, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
if (!compiler::write_stb_file(out_path.c_str(), image, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
// 写后自检:型号标识与 SHA-256
const compiler::StbView self = compiler::StbView::from(image);
if (!self.ok() || !self.sha_ok()) {
std::fprintf(stderr, "error: self-check failed: %s\n", self.error().c_str());
return 1;
}
if (!self.model_matches(cfg.model_name(), cfg.version())) {
std::fprintf(stderr, "error: self-check model mismatch\n");
return 1;
}
// sidecarI/O 绑定 var → 槽号 → channel/bit(不进映像,执行器采样用)
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)));
}
const auto it = link.global_index.find(key);
if (it != link.global_index.end()) {
out_b.slot = it->second; // 12.6 已校验存在
}
bindings.push_back(out_b);
}
std::filesystem::path sidecar = std::filesystem::path(out_path);
sidecar.replace_extension(".runtime.toml");
if (!compiler::write_sidecar_file(sidecar.string().c_str(), bindings, &err)) {
std::fprintf(stderr, "error: %s\n", err.c_str());
return 1;
}
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.n_funcs(), v.n_globals());
return 0;
}