阶段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:
2026-08-26 09:47:24 +08:00
parent b19a61aabf
commit 7b4961f7ed
5 changed files with 207 additions and 9 deletions
+129
View File
@@ -0,0 +1,129 @@
# 用例反汇编对照(源码 ↔ 指令验证)
> 状态:**13 个正例全部对照通过(2026-08-26**。方法:`STCompiler` 编译 → `--dump-map`
> 取变量/槽映射 → `--disasm` 取指令序列 → 逐条对照源码语义。
> 每用例记录「源码语句 ↔ 指令序列 ↔ 结论」;完整输出见 build/audit/(临时)。
## 01_empty_main:最小映像
```text
PROGRAM MAIN → fn0: RETnregs=8, 4 字节)✓
```
## 02_bool_assign:常量表 + BOOL 字面量
| 源码 | 指令 | 结论 |
|---|---|---|
| a := TRUE | LOADK.U8 r8, 0(常量[0]=1 | ✓ |
| b := FALSE | LOADK.U8 r9, 1(常量[1]=0 | ✓ |
常量表 8B 无 tag、BOOL func=U8 ✓
## 03_short_circuit:短路 AND/OR
| 源码 | 指令 | 结论 |
|---|---|---|
| x := a AND b | MOVE r10,r8 / JF r10,+8 / MOVE r11,r9 / MOVE r10,r11 | ✓ 短路跳过 rhs |
| x := a OR b | MOVE r10,r8 / JT r10,+8 / ... | ✓ |
## 04_if_elsif_else:分支跳转
| 源码 | 指令 | 结论 |
|---|---|---|
| IF sel=0 THEN out:=10 | MOVE/LOADK(0)/CMP_EQ.I16/JF +16/LOADK(10)/JMP +52 | ✓ |
| ELSIF sel=1 THEN out:=20 | MOVE/LOADK(1)/CMP_EQ/JF/LOADK(20)/JMP +8 | ✓ |
| ELSE out:=30 | LOADK(30) | ✓ |
跳转回填、常量正确 ✓
## 05_while_normalWHILE 回填
| 源码 | 指令 | 结论 |
|---|---|---|
| n := 0 | LOADK.I16 r8, 0 | ✓ |
| WHILE n<10 | MOVE/LOADK(10)/CMP_LT.I16/JF +28 | ✓ |
| n := n+1 | MOVE/LOADK(1)/ADD.I16 r8 | ✓ |
| 回跳 | JMP -56 | ✓ |
## 07_int_arith:算术 func
| 源码 | 指令 | 结论 |
|---|---|---|
| a := 7*6 | LOADK(7)/LOADK(6)/MUL.I16 r8 | ✓ |
| b := a/4 | MOVE/LOADK(4)/DIV.I16 r9 | ✓ |
| c := a-b | MOVE/MOVE/SUB.I16 r10 | ✓ |
| eq := c>30 | MOVE/LOADK(30)/CMP_GT.I16 | ✓ |
## 08_time_literalTIME 字面量
| 源码 | 指令 | 结论 |
|---|---|---|
| t1 := T#10ms | LOADK.I64 r8, 0(常量 10 | ✓ |
| t2 := T#1s250ms | LOADK.I64 r9, 1(常量 1250 | ✓ |
## 09_gvl_external:全局 + 初值
| 项 | 值 | 结论 |
|---|---|---|
| G1 槽 | slot=0 off=0 type=int func=3 | ✓ |
| G1 初值 | 值段 `05 00`5 小端) | ✓ |
| x := G1 | LOAD.I16 r8, s0 | ✓ |
## 13_function_call:调用约定 + max_stack
| 源码 | 指令 | 结论 |
|---|---|---|
| Add: a+b | MOVE r8,r1 / MOVE r9,r2 / ADD.I16 r0 | ✓ r0 结果 |
| x := Add(3,4) | LOADK(3)/LOADK(4)/MOVE r1/MOVE r2/CALL 0/MOVE r8,r0 | ✓ 实参 r1..r7 |
| max_stack | 192 = (12+11×8) + (12+10×8) | ✓ 编译期 DAG |
| 映射 | add: a=r1 b=r2 result=r0main: x=r8 | ✓ |
## 15_fb_instance:用户 FB 内联
| 源码 | 指令 | 结论 |
|---|---|---|
| starter(start:=TRUE,...) | LOADK(TRUE)/STORE_OFF r9,s0,0LOADK(FALSE)/STORE_OFF r10,s0,1 | ✓ 字段@0/1 |
| Q := start AND NOT stop | LOAD_OFF s0,0 / JF / LOAD_OFF s0,1 / NOT / MOVE / STORE_OFF s0,2 | ✓ 内联+短路 |
| q := starter.Q | LOAD_OFF r8, s0, 2 | ✓ |
值段 3B、映射 start@0 stop@1 q@2
## 17_ton:内建 TON
| 源码 | 指令 | 结论 |
|---|---|---|
| t(in:=TRUE, pt:=T#30ms) | STORE_OFF.U8 s0,0STORE_OFF.I64 s0,8 | ✓ pt=TIME→I64 |
| 调用 | CAL.TON s0 | ✓ fb 名显示 |
| q := t.Q | LOAD_OFF.U8 s0,16 | ✓ 偏移 16 |
值段 32Bin@0/pt@8/q@16/et@24)✓
## 18_tof_ctu:双实例 + 字段偏移
| 源码 | 指令 | 结论 |
|---|---|---|
| tf(in:=FALSE, pt:=T#20ms) | STORE_OFF s0,0/8CAL.TOF s0LOAD_OFF s0,16 | ✓ |
| c(cu:=TRUE,r:=FALSE,pv:=3) | STORE_OFF s1,0/1STORE_OFF.I16 s1,2CAL.CTU s1 | ✓ pv=INT 2B |
| q2 := c.Q / cnt := c.CV | LOAD_OFF.U8 s1,4LOAD_OFF.I16 s1,6 | ✓ q@4 cv@6 |
槽表 2 条(addr 0/32)、值段 40B ✓
## 20_line1:全链路
| 源码 | 指令 | 结论 |
|---|---|---|
| starter(start:=I0_0, stop:=I0_1) | LOAD.U8 r8,s1 → STORE_OFF s4,0LOAD.U8 r9,s2 → STORE_OFF s4,1 | ✓ I 读 |
| Q := start AND NOT stop AND NOT EmergencyStop | LOAD_OFF s4,0/JF/LOAD_OFF s4,1/NOT/MOVE/JF/LOAD s0(急停)/NOT/MOVE/STORE_OFF s4,2 | ✓ 双短路+全局 |
| Q0_0 := starter.Q | LOAD_OFF s4,2 / STORE.U8 r8,s3 | ✓ Q 写 |
槽表 5 条(addr 0..4)、值段 7B ✓
## 结构自检(stbcheck13 用例)
寄存器越界 / func 非法 / 跳转越界 / 槽号越界 / 指令长度越界:**全部通过**。
## 结论
- 编译器生成正确性:**13 正例全部对照通过**
- 结构自检:**全部通过**
- 已知缺陷(未修):LREAL 字面量装载按 REALLOADK.F32),F64 运算位模式错位(TODO)