阶段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:
@@ -60,8 +60,10 @@ namespace compiler {
|
||||
uint32_t imm32_of(const uint8_t* code);
|
||||
/// @brief 取 slot32(55..24,SLOT 形态)。
|
||||
uint32_t slot32_of(const uint8_t* code);
|
||||
/// @brief 取 off32(47..16,JMP/JC 形态,有符号字节偏移)。
|
||||
/// @brief 取 off32(47..16,JMP 形态,有符号字节偏移)。
|
||||
int32_t off32_of(const uint8_t* code);
|
||||
/// @brief 取 off32(55..24,JC 形态,有符号字节偏移)。
|
||||
int32_t off32_jc_of(const uint8_t* code);
|
||||
/// @brief 取 fn_id32(47..16,CALL 形态)。
|
||||
uint32_t fn_id32_of(const uint8_t* code);
|
||||
/// @brief 取 fb_id16(31..16,CAL 形态)。
|
||||
@@ -93,8 +95,10 @@ namespace compiler {
|
||||
void set_imm32(uint8_t* out, uint32_t v);
|
||||
/// @brief 写 slot32(55..24)。
|
||||
void set_slot32(uint8_t* out, uint32_t v);
|
||||
/// @brief 写 off32(47..16)。
|
||||
/// @brief 写 off32(47..16,JMP 形态)。
|
||||
void set_off32(uint8_t* out, int32_t v);
|
||||
/// @brief 写 off32(55..24,JC 形态)。
|
||||
void set_off32_jc(uint8_t* out, int32_t v);
|
||||
/// @brief 写 fn_id32(47..16)。
|
||||
void set_fn_id32(uint8_t* out, uint32_t v);
|
||||
/// @brief 写 fb_id16(31..16)。
|
||||
|
||||
+24
-4
@@ -121,7 +121,7 @@ uint32_t imm32_of(const uint8_t* code) {
|
||||
uint32_t slot32_of(const uint8_t* code) { return imm32_of(code); }
|
||||
|
||||
/**
|
||||
* @brief 取 off32(47..16,小端 4 字节,有符号)。
|
||||
* @brief 取 off32(47..16,JMP 形态,小端 4 字节,有符号)。
|
||||
* @param code 指令字节
|
||||
* @return 字节偏移(相对下一条)
|
||||
*/
|
||||
@@ -132,6 +132,18 @@ int32_t off32_of(const uint8_t* code) {
|
||||
| (static_cast<uint32_t>(code[5]) << 24));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 取 off32(55..24,JC 形态,小端 4 字节,有符号)。
|
||||
* @param code 指令字节
|
||||
* @return 字节偏移(相对下一条)
|
||||
*/
|
||||
int32_t off32_jc_of(const uint8_t* code) {
|
||||
return static_cast<int32_t>(static_cast<uint32_t>(code[3])
|
||||
| (static_cast<uint32_t>(code[4]) << 8)
|
||||
| (static_cast<uint32_t>(code[5]) << 16)
|
||||
| (static_cast<uint32_t>(code[6]) << 24));
|
||||
}
|
||||
|
||||
uint32_t fn_id32_of(const uint8_t* code) {
|
||||
return static_cast<uint32_t>(code[2])
|
||||
| (static_cast<uint32_t>(code[3]) << 8)
|
||||
@@ -193,9 +205,9 @@ uint64_t imm64_of(const uint8_t* code) {
|
||||
*/
|
||||
void set_byte0(uint8_t* out, const std::string& prefix, uint32_t op) {
|
||||
if (prefix == "11") {
|
||||
out[0] = static_cast<uint8_t>(0x80 | (op & 0x3F));
|
||||
out[0] = static_cast<uint8_t>(0xC0 | (op & 0x3F)); // bit7..6 = 11
|
||||
} else if (prefix == "10") {
|
||||
out[0] = static_cast<uint8_t>(0x80 | 0x40 | (op & 0x3F));
|
||||
out[0] = static_cast<uint8_t>(0x80 | (op & 0x3F)); // bit7..6 = 10
|
||||
} else if (prefix == "011") {
|
||||
out[0] = static_cast<uint8_t>(0x40 | (op & 0x1F));
|
||||
} else if (prefix.size() == 6 && prefix.compare(0, 3, "010") == 0) {
|
||||
@@ -232,6 +244,14 @@ void set_off32(uint8_t* out, int32_t v) {
|
||||
out[4] = static_cast<uint8_t>((u >> 16) & 0xFF);
|
||||
out[5] = static_cast<uint8_t>((u >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
void set_off32_jc(uint8_t* out, int32_t v) {
|
||||
const uint32_t u = static_cast<uint32_t>(v);
|
||||
out[3] = static_cast<uint8_t>(u & 0xFF);
|
||||
out[4] = static_cast<uint8_t>((u >> 8) & 0xFF);
|
||||
out[5] = static_cast<uint8_t>((u >> 16) & 0xFF);
|
||||
out[6] = static_cast<uint8_t>((u >> 24) & 0xFF);
|
||||
}
|
||||
void set_fn_id32(uint8_t* out, uint32_t v) { set_off32(out, static_cast<int32_t>(v)); }
|
||||
void set_fb_id16(uint8_t* out, uint16_t v) {
|
||||
out[2] = static_cast<uint8_t>(v & 0xFF);
|
||||
@@ -302,7 +322,7 @@ void disasm(const MachineConfig& cfg, const uint8_t* code, size_t len,
|
||||
snprintf(out, cap, "%s %+d", op->name.c_str(), static_cast<int>(off32_of(code)));
|
||||
} else if (f == "JC") {
|
||||
snprintf(out, cap, "%s r%u, %+d", op->name.c_str(),
|
||||
static_cast<unsigned>(rd_of(code)), static_cast<int>(off32_of(code)));
|
||||
static_cast<unsigned>(rd_of(code)), static_cast<int>(off32_jc_of(code)));
|
||||
} else if (f == "CALL") {
|
||||
snprintf(out, cap, "%s %u", op->name.c_str(), static_cast<unsigned>(fn_id32_of(code)));
|
||||
} else if (f == "CAL") {
|
||||
|
||||
+33
-16
@@ -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);
|
||||
}
|
||||
}
|
||||
// 内建 FB:fb 表查 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/JF(010010/010011 区)
|
||||
// 按前缀选偏移字段:JMP(010010)off@47..16;JT/JF(010011)off@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(字段对齐)
|
||||
|
||||
+10
-5
@@ -271,10 +271,9 @@ StbView StbView::from(const uint8_t* buf, size_t len) {
|
||||
v.err_ = "missing sha256 tail";
|
||||
return v;
|
||||
}
|
||||
const uint64_t offs[6] = {get_le32(buf + kOffConst), get_le32(buf + kOffFuncs), v.offset_code_,
|
||||
v.offset_slots_, v.offset_values_,
|
||||
(v.offset_meta_ != 0) ? v.offset_meta_ : v.offset_values_};
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
const uint64_t offs[5] = {get_le32(buf + kOffConst), get_le32(buf + kOffFuncs), v.offset_code_,
|
||||
v.offset_slots_, v.offset_values_};
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
if (offs[i] < kHeaderSize || offs[i] > len - kSha256Size) {
|
||||
v.err_ = "segment offset out of range";
|
||||
return v;
|
||||
@@ -296,7 +295,13 @@ StbView StbView::from(const uint8_t* buf, size_t len) {
|
||||
v.err_ = "slot table size mismatch";
|
||||
return v;
|
||||
}
|
||||
if (offs[5] - offs[4] != v.values_size_) {
|
||||
// 值段大小:meta 段为 0(空段)时值段到 SHA 尾;否则到 meta 起点
|
||||
if (v.offset_meta_ != 0) {
|
||||
if (static_cast<uint64_t>(v.offset_meta_) - offs[4] != v.values_size_) {
|
||||
v.err_ = "values segment size mismatch";
|
||||
return v;
|
||||
}
|
||||
} else if (static_cast<uint64_t>(len - kSha256Size) - offs[4] != v.values_size_) {
|
||||
v.err_ = "values segment size mismatch";
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -81,12 +81,14 @@ namespace {
|
||||
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) {
|
||||
uint32_t pc = 0;
|
||||
while (pc < r.code_len) {
|
||||
char buf[64];
|
||||
// TODO(V2): Stb 重写(阶段2-4)后 code_len 为字节、instr_len 定长
|
||||
compiler::disasm(cfg, base + j * 4, 4, buf, sizeof buf);
|
||||
const size_t ilen = compiler::instr_len(base + pc);
|
||||
compiler::disasm(cfg, base + pc, ilen, buf, sizeof buf);
|
||||
std::printf(" 0x%04x %s\n",
|
||||
v.offset_code() + r.code_offset + j * 4, buf);
|
||||
v.offset_code() + r.code_offset + pc, buf);
|
||||
pc += static_cast<uint32_t>(ilen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user