阶段3-5:编译器验证——13 正例源码↔反汇编对照 + --dump-map
- STCompiler --dump-map:编译后打印变量/槽映射(函数局部 r 寄存器、 全局 slot/off/type/func、实例 slot/off/fb/size/字段偏移) - CodegenMap 输出结构(codegen_project 可选参数) - 修复参数循环 bug(i+1<argc 漏掉末尾单参数选项) - 结构自检(临时 stbcheck):13 用例寄存器/func/跳转/槽/长度全部通过 - 13 正例逐条对照全部通过,产出 Doc/compiler/用例反汇编对照.md - 已知缺陷记录:LREAL 字面量装载按 REAL(TODO)
This commit is contained in:
@@ -53,8 +53,9 @@ namespace {
|
||||
public:
|
||||
Builder(const Project& proj, const std::vector<SourceUnit>& units,
|
||||
const LinkResult& link, const MachineConfig& cfg,
|
||||
std::vector<uint8_t>* image, std::string* err)
|
||||
: proj_(proj), units_(units), link_(link), cfg_(cfg), image_(image), err_(err) {
|
||||
std::vector<uint8_t>* image, std::string* err, CodegenMap* map)
|
||||
: proj_(proj), units_(units), link_(link), cfg_(cfg), image_(image), err_(err),
|
||||
map_(map) {
|
||||
for (const IoBinding& b : proj_.io) {
|
||||
std::string key = b.var;
|
||||
for (char& ch : key) {
|
||||
@@ -307,6 +308,18 @@ namespace {
|
||||
}
|
||||
f->nlocals = r;
|
||||
f->nregs = r;
|
||||
if (map_ != nullptr) {
|
||||
std::map<std::string, std::string> vars;
|
||||
for (const auto& kv : f->regs) {
|
||||
std::string tn = "int";
|
||||
const auto tf = f->reg_func.find(kv.first);
|
||||
if (tf != f->reg_func.end()) {
|
||||
tn = std::to_string(tf->second);
|
||||
}
|
||||
vars[kv.first] = "r" + std::to_string(kv.second) + " (func " + tn + ")";
|
||||
}
|
||||
map_->funcs.emplace_back(f->name, vars);
|
||||
}
|
||||
for (const Stmt& st : pou.body) {
|
||||
begin_stmt(*f);
|
||||
if (!compile_stmt(*f, st)) {
|
||||
@@ -755,6 +768,12 @@ namespace {
|
||||
const int64_t v = has_init ? init : 0;
|
||||
write_value(values_, cur_addr, v, tm.width());
|
||||
global_slot_[s.name] = static_cast<uint32_t>(slots_.size() - 1);
|
||||
if (map_ != nullptr) {
|
||||
map_->globals[s.name] = "slot=" + std::to_string(slots_.size() - 1) +
|
||||
" off=" + std::to_string(cur_addr) +
|
||||
" type=" + s.type_name +
|
||||
" func=" + std::to_string(tm.func());
|
||||
}
|
||||
cur_addr += tm.width();
|
||||
}
|
||||
for (const LinkResult::PouScope& sc : link_.scopes) {
|
||||
@@ -790,6 +809,16 @@ namespace {
|
||||
slots_.push_back(cur_addr);
|
||||
values_.resize(cur_addr + static_cast<uint32_t>(off), 0);
|
||||
instances_[sc.name + "/" + s.name] = inst;
|
||||
if (map_ != nullptr) {
|
||||
std::string desc = "slot=" + std::to_string(inst.slot) +
|
||||
" off=" + std::to_string(cur_addr) +
|
||||
" fb=" + inst.type_name +
|
||||
" size=" + std::to_string(off) + " ";
|
||||
for (const auto& fo : inst.field_off) {
|
||||
desc += fo.first + "@" + std::to_string(fo.second) + " ";
|
||||
}
|
||||
map_->instances[sc.name + "/" + s.name] = desc;
|
||||
}
|
||||
cur_addr += static_cast<uint32_t>(off);
|
||||
}
|
||||
}
|
||||
@@ -1036,6 +1065,7 @@ namespace {
|
||||
std::map<std::string, InstFields> instances_; ///< "POU名/实例名" → 实例布局
|
||||
const InstFields* inline_fields_ = nullptr; ///< 内联 FB 字段表
|
||||
uint32_t max_stack_ = 0; ///< 栈区字节数
|
||||
CodegenMap* map_ = nullptr; ///< 变量/槽映射输出(可空)
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -1052,8 +1082,8 @@ namespace {
|
||||
*/
|
||||
bool codegen_project(const Project& proj, const std::vector<SourceUnit>& units,
|
||||
const LinkResult& link, const MachineConfig& cfg,
|
||||
std::vector<uint8_t>* image, std::string* err) {
|
||||
Builder b(proj, units, link, cfg, image, err);
|
||||
std::vector<uint8_t>* image, std::string* err, CodegenMap* map) {
|
||||
Builder b(proj, units, link, cfg, image, err, map);
|
||||
return b.run();
|
||||
}
|
||||
|
||||
|
||||
+27
-4
@@ -34,6 +34,7 @@ namespace {
|
||||
" -o <name>.stb 编译并写出映像文件\n"
|
||||
" --machine <path> 机器定义(machine.toml,编译路径必填)\n"
|
||||
" --disasm 反汇编一个已编译的 .stb 映像(需要 --machine)\n"
|
||||
" --dump-map 编译后打印变量/槽映射(对照源码↔反汇编用)\n"
|
||||
" --help 打印本帮助\n");
|
||||
}
|
||||
|
||||
@@ -167,11 +168,16 @@ int main(int argc, char** argv) {
|
||||
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) {
|
||||
bool dump_map = false;
|
||||
for (int i = 2; i < argc; ++i) {
|
||||
if (std::strcmp(argv[i], "--machine") == 0 && i + 1 < argc) {
|
||||
machine_path = argv[i + 1];
|
||||
} else if (std::strcmp(argv[i], "-o") == 0) {
|
||||
++i;
|
||||
} else if (std::strcmp(argv[i], "-o") == 0 && i + 1 < argc) {
|
||||
out_path = argv[i + 1];
|
||||
++i;
|
||||
} else if (std::strcmp(argv[i], "--dump-map") == 0) {
|
||||
dump_map = true;
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
@@ -253,10 +259,27 @@ int main(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
std::vector<uint8_t> image;
|
||||
if (!compiler::codegen_project(proj, units, link, cfg, &image, &err)) {
|
||||
compiler::CodegenMap cmap;
|
||||
compiler::CodegenMap* cmap_ptr = dump_map ? &cmap : nullptr;
|
||||
if (!compiler::codegen_project(proj, units, link, cfg, &image, &err, cmap_ptr)) {
|
||||
std::fprintf(stderr, "error: %s\n", err.c_str());
|
||||
return 1;
|
||||
}
|
||||
if (dump_map) {
|
||||
std::printf("map:\n");
|
||||
for (const auto& f : cmap.funcs) {
|
||||
std::printf(" function %s:\n", f.first.c_str());
|
||||
for (const auto& v : f.second) {
|
||||
std::printf(" %-24s %s\n", v.first.c_str(), v.second.c_str());
|
||||
}
|
||||
}
|
||||
for (const auto& g : cmap.globals) {
|
||||
std::printf(" global %-24s %s\n", g.first.c_str(), g.second.c_str());
|
||||
}
|
||||
for (const auto& i : cmap.instances) {
|
||||
std::printf(" instance %-24s %s\n", i.first.c_str(), i.second.c_str());
|
||||
}
|
||||
}
|
||||
if (!compiler::write_stb_file(out_path.c_str(), image, &err)) {
|
||||
std::fprintf(stderr, "error: %s\n", err.c_str());
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user