stb 头字段偏移常量表:消除 vm/compiler 两侧裸魔法数

- vm/Image.cpp:匿名空间 constexpr 偏移常量(kOffMagic..kOffModelId + 段内行偏移),
  from/model_id/model_matches/func_row/const_entry 全部替换
- compiler/Stb.h:同值 inline constexpr 表(Codegen 写侧 + Stb 读侧共用)
- compiler/Codegen.cpp assemble_image:put_* 头字段/行内偏移替换
- compiler/Stb.cpp StbView:读侧偏移替换
- 两侧 static_assert:头大小 = 72 + 型号标识、字段偏移单调、行内布局自洽
This commit is contained in:
2026-08-24 08:55:57 +08:00
parent d51dce4ae3
commit 7aa2bbefcf
4 changed files with 138 additions and 66 deletions
+60 -24
View File
@@ -29,6 +29,42 @@ namespace {
/// 型号标识长度(头内 @72,不足补 '\0')。
const size_t kModelIdSize = 32;
// ---- 头字段偏移(与 Doc/isa/指令与映像.md 字段表一致;compiler 侧另有同值一份)----
constexpr size_t kOffMagic = 0; ///< 魔数 "STSC"
constexpr size_t kOffVersion = 4; ///< 格式版本
constexpr size_t kOffCycleLimit = 8; ///< 每周期指令数上限
constexpr size_t kOffDtMs = 12; ///< 周期时长(毫秒)
constexpr size_t kOffProjectHash = 16; ///< 工程哈希(8 字节)
constexpr size_t kOffEntryFnId = 24; ///< 入口函数 fn_id
constexpr size_t kOffNGlobals = 28; ///< 全局槽数
constexpr size_t kOffNI = 32; ///< 输入(I)槽数
constexpr size_t kOffNQ = 36; ///< 输出(Q)槽数
constexpr size_t kOffNM = 40; ///< 中间(M)槽数
constexpr size_t kOffNConsts = 44; ///< 常量表条目数
constexpr size_t kOffNFuncs = 48; ///< 函数表行数
constexpr size_t kOffConst = 52; ///< 常量表段偏移
constexpr size_t kOffFuncs = 56; ///< 函数表段偏移
constexpr size_t kOffCode = 60; ///< 字节码段偏移
constexpr size_t kOffFb = 64; ///< FB 表段偏移
constexpr size_t kOffData = 68; ///< 数据段偏移
constexpr size_t kOffModelId = 72; ///< 型号标识[32]12.13 修订)
// ---- 段内行偏移 ----
constexpr size_t kConstTagOff = 0; ///< 常量表行内:tag
constexpr size_t kConstValueOff = 4; ///< 常量表行内:value8 字节)
constexpr size_t kFuncNregsOff = 0; ///< 函数表行内:nregs
constexpr size_t kFuncCodeOff = 4; ///< 函数表行内:code_offset(字节)
constexpr size_t kFuncLenOff = 8; ///< 函数表行内:code_len(指令条数)
// 防漂移:头布局自洽性(与 Doc/isa/指令与映像.md 冻结表核对)
static_assert(kHeaderSize == kOffModelId + kModelIdSize, "header size = 72 + model id[32]");
static_assert(kOffData > kOffFb && kOffFb > kOffCode && kOffCode > kOffFuncs &&
kOffFuncs > kOffConst,
"header field offsets monotonic");
static_assert(kOffModelId == kOffData + 4, "model id follows data offset field");
static_assert(kConstEntrySize == kConstValueOff + 8, "const row: tag + value:8");
static_assert(kFuncRowSize == kFuncLenOff + 4, "func row: nregs/code_offset/code_len");
/// 小端读 32 位。
uint32_t get_le32(const uint8_t* p) {
return static_cast<uint32_t>(p[0])
@@ -214,30 +250,30 @@ Image Image::from(const uint8_t* buf, size_t len) {
v.err_ = "image too short";
return v;
}
if (get_le32(buf + 0) != kMagic) {
if (get_le32(buf + kOffMagic) != kMagic) {
v.err_ = "bad magic";
return v;
}
if (get_le32(buf + 4) != kVersion) {
if (get_le32(buf + kOffVersion) != kVersion) {
v.err_ = "bad version";
return v;
}
ImageHeader& h = v.hdr_;
h.cycle_limit = get_le32(buf + 8);
h.dt_ms = get_le32(buf + 12);
h.project_hash = get_le64(buf + 16);
h.entry_fn_id = get_le32(buf + 24);
h.n_globals = get_le32(buf + 28);
h.n_i = get_le32(buf + 32);
h.n_q = get_le32(buf + 36);
h.n_m = get_le32(buf + 40);
h.n_consts = get_le32(buf + 44);
h.n_funcs = get_le32(buf + 48);
h.offset_const = get_le32(buf + 52);
h.offset_funcs = get_le32(buf + 56);
h.offset_code = get_le32(buf + 60);
h.offset_fb = get_le32(buf + 64);
h.offset_data = get_le32(buf + 68);
h.cycle_limit = get_le32(buf + kOffCycleLimit);
h.dt_ms = get_le32(buf + kOffDtMs);
h.project_hash = get_le64(buf + kOffProjectHash);
h.entry_fn_id = get_le32(buf + kOffEntryFnId);
h.n_globals = get_le32(buf + kOffNGlobals);
h.n_i = get_le32(buf + kOffNI);
h.n_q = get_le32(buf + kOffNQ);
h.n_m = get_le32(buf + kOffNM);
h.n_consts = get_le32(buf + kOffNConsts);
h.n_funcs = get_le32(buf + kOffNFuncs);
h.offset_const = get_le32(buf + kOffConst);
h.offset_funcs = get_le32(buf + kOffFuncs);
h.offset_code = get_le32(buf + kOffCode);
h.offset_fb = get_le32(buf + kOffFb);
h.offset_data = get_le32(buf + kOffData);
// 段校验(数据段之后是 SHA-256 文件尾;这里仅保证有尾,sha_ok() 做完整性校验)
if (len < static_cast<size_t>(h.offset_data) + kSha256Size) {
@@ -295,9 +331,9 @@ FuncRow Image::func_row(size_t i) const {
FuncRow r;
if (ok_ && i < hdr_.n_funcs) {
const uint8_t* p = buf_ + hdr_.offset_funcs + i * kFuncRowSize;
r.nregs = get_le32(p + 0);
r.code_offset = get_le32(p + 4);
r.code_len = get_le32(p + 8);
r.nregs = get_le32(p + kFuncNregsOff);
r.code_offset = get_le32(p + kFuncCodeOff);
r.code_len = get_le32(p + kFuncLenOff);
}
return r;
}
@@ -311,8 +347,8 @@ ConstEntry Image::const_entry(size_t i) const {
ConstEntry e;
if (ok_ && i < hdr_.n_consts) {
const uint8_t* p = buf_ + hdr_.offset_const + i * kConstEntrySize;
e.tag = get_le32(p);
e.value = get_le64(p + 4);
e.tag = get_le32(p + kConstTagOff);
e.value = get_le64(p + kConstValueOff);
}
return e;
}
@@ -349,7 +385,7 @@ std::string Image::model_id() const {
if (!ok_) {
return "";
}
std::string s(reinterpret_cast<const char*>(buf_ + 72), kModelIdSize);
std::string s(reinterpret_cast<const char*>(buf_ + kOffModelId), kModelIdSize);
const size_t z = s.find('\0');
if (z != std::string::npos) {
s.resize(z);
@@ -366,7 +402,7 @@ std::string Image::model_id() const {
bool Image::model_matches(const std::string& name, uint32_t version) const {
char want[kModelIdSize];
fill_model_id(name, version, want);
return std::memcmp(buf_ + 72, want, kModelIdSize) == 0;
return std::memcmp(buf_ + kOffModelId, want, kModelIdSize) == 0;
}
/**