阶段2-6:V2 生成侧 bug 修复与验证收尾

- Codec:set_byte0 的 11/10 前缀位修正(0xC0/0x80);新增 JC 形态偏移
  专用读写(off@55..24,字节 3..6)——修复 JF rd 被 off 覆盖
- Stb:offset_meta=0(空段)时值段大小校验按 SHA 尾计算(修复
  values segment size mismatch)
- Codegen:实例字段带 func(field_func),LOAD_OFF/STORE_OFF 按字段
  类型设 func(pt=TIME → I64)
- main.cpp:--disasm 按 instr_len 迭代变长字节码
- 验证:13 个正例全部编译出 V2 产物 + disasm 自读通过(RET/CAL.TON/
  STORE_OFF.I64/JF 偏移等抽查正确);ctest 11/13(vm/cases 待阶段 4)
This commit is contained in:
2026-08-25 20:23:32 +08:00
parent 924c0c1923
commit 4785cf3e3b
5 changed files with 79 additions and 31 deletions
+33 -16
View File
@@ -175,11 +175,11 @@ namespace {
set_off32(f.code.data() + s, off);
return s;
}
/// 条件跳转(r 为真则跳;off 字节相对下一条)。
/// 条件跳转(r 为真则跳;off 字节相对下一条JC 形态 off@55..24)。
size_t E_jc(FuncCtx& f, const char* name, uint8_t r, int32_t off) {
const size_t s = emit(f, opc(name));
set_rd(f.code.data() + s, r);
set_off32(f.code.data() + s, off);
set_off32_jc(f.code.data() + s, off);
return s;
}
/// CALL 指令(fn_id32)。
@@ -241,9 +241,10 @@ namespace {
* @brief FB 实例布局(V2:槽表条目 + 值区偏移 + 字段偏移)。
*/
struct InstFields {
std::map<std::string, int32_t> field_off; ///< 字段名 → 值区内偏移
uint32_t slot = 0; ///< 实例槽号(槽表条目
std::string type_name; ///< 实例的 FB 类型名
std::map<std::string, int32_t> field_off; ///< 字段名 → 值区内偏移
std::map<std::string, uint8_t> field_func; ///< 字段名 → func(类型
uint32_t slot = 0; ///< 实例槽号(槽表条目)
std::string type_name; ///< 实例的 FB 类型名
};
void begin_stmt(FuncCtx& f) { f.temp_used = 0; }
@@ -344,7 +345,12 @@ namespace {
if (!compile_expr(f, *st.value, t)) {
return false;
}
E_slot_off(f, "STORE_OFF", t, inline_fields_->slot, fit->second);
const size_t so = E_slot_off(f, "STORE_OFF", t, inline_fields_->slot,
fit->second);
const auto ff = inline_fields_->field_func.find(st.target);
if (ff != inline_fields_->field_func.end()) {
set_func(f.code.data() + so, ff->second);
}
return true;
}
}
@@ -372,7 +378,11 @@ namespace {
if (!compile_expr(f, *a.value, t)) {
return false;
}
E_slot_off(f, "STORE_OFF", t, inst->slot, it->second);
const size_t so = E_slot_off(f, "STORE_OFF", t, inst->slot, it->second);
const auto ff = inst->field_func.find(a.name);
if (ff != inst->field_func.end()) {
set_func(f.code.data() + so, ff->second);
}
}
// 内建 FBfb 表查 id
const ConfigFb* fb = cfg_.find_fb(uppercase_of(inst->type_name));
@@ -498,7 +508,12 @@ namespace {
if (inline_fields_) {
const auto fit = inline_fields_->field_off.find(e.name);
if (fit != inline_fields_->field_off.end()) {
E_slot_off(f, "LOAD_OFF", rd, inline_fields_->slot, fit->second);
const size_t lo = E_slot_off(f, "LOAD_OFF", rd,
inline_fields_->slot, fit->second);
const auto ff = inline_fields_->field_func.find(e.name);
if (ff != inline_fields_->field_func.end()) {
set_func(f.code.data() + lo, ff->second);
}
return true;
}
}
@@ -527,7 +542,11 @@ namespace {
if (fit == inst->field_off.end()) {
return fail("unknown field '" + e.field + "' for '" + e.name + "'");
}
E_slot_off(f, "LOAD_OFF", rd, inst->slot, fit->second);
const size_t lo = E_slot_off(f, "LOAD_OFF", rd, inst->slot, fit->second);
const auto ff = inst->field_func.find(e.field);
if (ff != inst->field_func.end()) {
set_func(f.code.data() + lo, ff->second);
}
return true;
}
if (e.kind == ExprKind::Add || e.kind == ExprKind::Sub ||
@@ -636,16 +655,13 @@ namespace {
const int32_t off = static_cast<int32_t>(
static_cast<int64_t>(target_off) -
(static_cast<int64_t>(idx) + static_cast<int64_t>(instr_len(f.code.data() + idx))));
const ConfigOp* j = nullptr;
// 按字节 0 前缀推导跳转指令:JMP/JT/JF010010/010011 区)
// 按前缀选偏移字段:JMP010010off@47..16JT/JF010011off@55..24
const std::string prefix = prefix_of(f.code.data() + idx);
if (prefix == "010010") {
j = cfg_.find_op("JMP");
} else if (prefix == "010011") {
j = cfg_.find_op("JF"); // 占位:JF/JT 按 rd 区分不必要(偏移相同)
set_off32(f.code.data() + idx, off);
} else {
set_off32_jc(f.code.data() + idx, off);
}
(void)j;
set_off32(f.code.data() + idx, off);
}
static const char* arith_name(ExprKind k) {
@@ -717,6 +733,7 @@ namespace {
}
off = static_cast<int32_t>(align_up(off, tm.width()));
inst.field_off[fd.name] = off;
inst.field_func[fd.name] = static_cast<uint8_t>(tm.func());
off += static_cast<int32_t>(tm.width());
}
// 实例块对齐到 max(字段对齐)