12.8 切片 7:FB 实例块、用户 FB 内联、CAL_TON/TOF/CTU。

- FB 实例 → 数据区实例块(字段地址 = 基址+偏移,编译期算死;跨周期持久)
- 用户 FB 调用点内联展开(实参写字段 → FB 体以实例字段为变量编译)
- 内建 TON/TOF/CTU:实参写字段 → CAL_* <实例偏移>;FB 生成空函数占位保持 fn_id
- codegen_test:189 断言(用例 15 内联序列、17 CAL_TON 字段偏移、18 TOF/CTU、line1 全链路 LOAD_I/STORE_Q),ctest 9/9
- 20 用例扫描:14 正例全部出映像,6 负例按期望在前层拒绝
This commit is contained in:
2026-08-21 11:52:25 +08:00
parent 0a36e36b16
commit 0263813a8f
2 changed files with 359 additions and 27 deletions
+149
View File
@@ -541,6 +541,151 @@ static bool test_case13() {
return true;
}
// ---- 14. 用例 15:用户 FB 内联展开 ----
static bool test_case15() {
std::vector<uint8_t> img;
std::string err;
CHECK(compile_case("15_fb_instance", &img, &err));
const isa::ImageView v = isa::ImageView::from(img);
CHECK(v.ok());
CHECK(v.header().n_funcs == 2); // FB 占位 + MAIN
CHECK(v.header().entry_fn_id == 1);
CHECK(v.data_len() == 8); // 实例 3Bstart@0 stop@1 q@2),8 对齐
const isa::FuncRow fm = v.func_row(1);
CHECK(fm.nregs == 12);
CHECK(fm.code_len == 12);
const uint32_t* im = reinterpret_cast<const uint32_t*>(v.code_bytes()) + fm.code_offset / 4;
char buf[64];
// 实参写字段:start := TRUE / stop := FALSE
isa::disasm(im[0], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOADK r9, 0") == 0);
isa::disasm(im[1], buf, sizeof buf);
CHECK(std::strcmp(buf, "STORE_GLOBAL r9, 0") == 0);
isa::disasm(im[2], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOADK r10, 1") == 0);
isa::disasm(im[3], buf, sizeof buf);
CHECK(std::strcmp(buf, "STORE_GLOBAL r10, 1") == 0);
// 内联体:Q := start AND NOT stop(短路跳转)
isa::disasm(im[4], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOAD_GLOBAL r9, 0") == 0);
isa::disasm(im[5], buf, sizeof buf);
CHECK(std::strcmp(buf, "JF r9, +3") == 0);
isa::disasm(im[9], buf, sizeof buf);
CHECK(std::strcmp(buf, "STORE_GLOBAL r9, 2") == 0); // Q 字段
// q := starter.Q
isa::disasm(im[10], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOAD_GLOBAL r8, 2") == 0);
return true;
}
// ---- 15. 用例 17TONCAL_TON + 字段偏移)----
static bool test_case17() {
std::vector<uint8_t> img;
std::string err;
CHECK(compile_case("17_ton", &img, &err));
const isa::ImageView v = isa::ImageView::from(img);
CHECK(v.ok());
CHECK(v.data_len() == 32); // in@0 pt@8 q@16 et@24
const isa::FuncRow r = v.func_row(0);
CHECK(r.nregs == 11);
const uint32_t* ins = reinterpret_cast<const uint32_t*>(v.code_bytes());
char buf[64];
isa::disasm(ins[0], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOADK r9, 0") == 0);
isa::disasm(ins[1], buf, sizeof buf);
CHECK(std::strcmp(buf, "STORE_GLOBAL r9, 0") == 0); // in
isa::disasm(ins[2], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOADK r10, 1") == 0);
isa::disasm(ins[3], buf, sizeof buf);
CHECK(std::strcmp(buf, "STORE_GLOBAL r10, 8") == 0); // ptTIME 8 对齐)
isa::disasm(ins[4], buf, sizeof buf);
CHECK(std::strcmp(buf, "CAL_TON 0") == 0);
isa::disasm(ins[5], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOAD_GLOBAL r8, 16") == 0); // t.Q
return true;
}
// ---- 16. 用例 18TOF / CTU ----
static bool test_case18() {
std::vector<uint8_t> img;
std::string err;
CHECK(compile_case("18_tof_ctu", &img, &err));
const isa::ImageView v = isa::ImageView::from(img);
CHECK(v.ok());
CHECK(v.data_len() == 40); // tf 块 0..31in@0 pt@8 q@16 et@24)、c 块 32..
const isa::FuncRow r = v.func_row(0);
CHECK(r.nregs == 14);
const uint32_t* ins = reinterpret_cast<const uint32_t*>(v.code_bytes());
char buf[64];
isa::disasm(ins[4], buf, sizeof buf);
CHECK(std::strcmp(buf, "CAL_TOF 0") == 0);
isa::disasm(ins[12], buf, sizeof buf);
CHECK(std::strcmp(buf, "CAL_CTU 32") == 0);
isa::disasm(ins[13], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOAD_GLOBAL r9, 36") == 0); // c.Q
isa::disasm(ins[14], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOAD_GLOBAL r10, 38") == 0); // c.CVINT 2 对齐)
return true;
}
// ---- 17. line1 全链路(MAIN + Motor FB + I/O + 全局)----
static bool test_line1() {
std::vector<uint8_t> img;
std::string err;
using namespace compiler;
const std::string toml = std::string(REPO_ROOT) + "/examples/line1/project.toml";
Project p;
CHECK(parse_project(toml, &p, &err));
std::vector<SourceUnit> units;
for (const std::string& f : compile_files(p)) {
SourceUnit u;
CHECK(load_unit(p.base_dir + "/" + f, &u, &err));
units.push_back(std::move(u));
}
LinkResult link;
CHECK(link_project(p, units, &link, &err));
CHECK(check_project(p, units, link, &err));
CHECK(codegen_project(p, units, link, &img, &err));
const isa::ImageView v = isa::ImageView::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() == 16); // 全局 4B + 实例块 8..108 对齐)
const isa::FuncRow fm = v.func_row(1);
CHECK(fm.nregs == 13);
CHECK(fm.code_len == 17);
const uint32_t* im = reinterpret_cast<const uint32_t*>(v.code_bytes()) + fm.code_offset / 4;
char buf[64];
isa::disasm(im[0], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOAD_I r8, 1") == 0); // I0_0io.input
isa::disasm(im[1], buf, sizeof buf);
CHECK(std::strcmp(buf, "STORE_GLOBAL r8, 8") == 0); // starter.start
isa::disasm(im[2], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOAD_GLOBAL r9, 2") == 0); // I0_1
isa::disasm(im[3], buf, sizeof buf);
CHECK(std::strcmp(buf, "STORE_GLOBAL r9, 9") == 0); // starter.stop
isa::disasm(im[13], buf, sizeof buf);
CHECK(std::strcmp(buf, "STORE_GLOBAL r8, 10") == 0); // starter.Q
isa::disasm(im[14], buf, sizeof buf);
CHECK(std::strcmp(buf, "LOAD_GLOBAL r8, 10") == 0); // starter.Q 读回
isa::disasm(im[15], buf, sizeof buf);
CHECK(std::strcmp(buf, "STORE_Q r8, 3") == 0); // Q0_0io.output
isa::disasm(im[16], buf, sizeof buf);
CHECK(std::strcmp(buf, "RET") == 0);
return true;
}
int main() {
if (!test_case01()) return 1;
if (!test_case02()) return 1;
@@ -555,6 +700,10 @@ int main() {
if (!test_case07()) return 1;
if (!test_case08()) return 1;
if (!test_case13()) return 1;
if (!test_case15()) return 1;
if (!test_case17()) return 1;
if (!test_case18()) return 1;
if (!test_line1()) return 1;
std::printf("codegen_test: %d checks passed\n", g_checks);
return 0;
}