Files
Interpreter/Doc/compiler/编译器优化.md
T
Admin 109f9a7619 文档:编译器优化 V2 草案(编译策略层,与指令集优化.md 分层)
- §2 V1 现状:FB 内联/FC CALL/CAL_* 三种调用、短路跳转、固定寄存器分配、
  调用约定、跳转回填、常量表去重
- §3 V2 变更:FB 基址寻址消除内联、type 位段驱动语义、槽表/值区布局职责、
  变长发射字节化回填、类型扩展与升宽规则
- §4 待确认(引用指令集优化 §4 编译器相关项);§5 编译器侧影响面;§6 阶段;§7 决策历史
2026-08-24 10:53:47 +08:00

99 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 编译器优化(V2 草案)
> 状态:**设计中**。本文聚焦**编译器(codegen/优化策略)侧**的现状与 V2 变更;
> 指令集/映像层(指令格式、槽表/值区、类型位段)见 [`isa/指令集优化.md`](../isa/指令集优化.md)。
> 全部内容为草案,未进入实现。
## 1. 定位
| 文档 | 覆盖层 | 内容 |
|---|---|---|
| [`isa/指令集优化.md`](../isa/指令集优化.md) | ISA/映像层 | 变长指令、槽表/值区、type 位段、映像格式 |
| **本文**compiler) | 编译策略层 | 代码生成策略、POU 调用方式、寄存器分配、优化方向 |
## 2. V1 现状(已实现的编译策略)
### 2.1 POU 调用方式(三种)
| 对象 | V1 处理 | 理由 | 代价 |
|---|---|---|---|
| 用户 FB | **调用点内联展开** | FB 体访问绝对字段地址(`LOAD_GLOBAL rd, 基槽+字段序`),不同实例基址不同,共享体无法复用;无递归、无动态实例 → 内联安全(12.8 定案) | 字节码随调用点数膨胀 |
| FUNCTION | 独立函数 + `CALL fn_id` 帧栈 | 无状态、寄存器约定(r1..r7 实参 / r0 结果)无地址冲突 | 帧压栈 |
| 内建 FB | `CAL_*` 指令(VM 原语) | 定时器/计数器在 VM 侧 | 无 |
### 2.2 其他编译策略(V1 冻结)
- **短路求值必须编跳转**`AND`/`OR` 禁止两边都算(`JF(AND)/JT(OR) rd, L_end`
- **寄存器分配**:变量固定前段(r0..k-1)、表达式临时从 k 起、语句结束复用基址(不分析生命周期);`nregs` = 峰值 + 1;上限 256`register overflow (>256)`
- **调用约定**:r0 结果、r1..r7 参数(≤7)、r8+ 变量/临时;调用点实参求值到 r8+ → `MOVE r(1+i), t``CALL``MOVE rd, r0`
- **跳转留洞回填**`patch_jump`(相对下一条:目标 = 当前 + 1 + off)
- **常量统一进常量表**`const_id` = 首次出现序,去重
- **空条件寄存器**r0 恒 0`enc_jmp` 用);一元负号 = `SUB rd, r0, t`
- **IF/WHILE 模式**`JF` 跳 else、`JMP` 连 end、`WHILE` 回跳循环头
## 3. V2 编译器侧变更(对应指令集优化)
### 3.1 FB 共享体(基址寻址)——消除内联膨胀
- **现状问题**:FB 每调用一次复制一份体,字节码膨胀
- **V2 方案**:槽表模型下引入**基址寻址指令**(`LOAD/STORE rd, base_slot, field_off`,base 槽取自寄存器/立即数,16B 长度组已预留)→ FB 体编译**一次**,运行时按实例基址定位字段
- 收益:字节码不再随调用点膨胀;代价:每次字段访问多一个基址操作数
- **待确认**:见指令集优化.md §4 项 9(推荐实施)
### 3.2 类型驱动语义(type 位段红利)
- CMP/算术按 `type` 位段自动选择语义:无符号**无符号比较**、整数**饱和到类型宽度**(模板化)、浮点 **IEEE 754**(无饱和,溢出→±inf
- 读取按宽度 + 符号/零扩展(`slot_read(addr, width, signed)`
- 常量表 tag = type 位段值(0..15),REAL=14 / LREAL=15 存位模式
### 3.3 槽表/值区布局(codegen 职责)
- **槽表段**:每槽 {addr:u32},编译器为每个变量分配槽 + 值区地址(编译期算死)
- **值段**:紧凑变宽布局,对齐规则 1/2/8 字节(BOOL 1 / INT 2 / TIME·LREAL·LWORD·ULINT·LINT 8 / REAL·DWORD·UDINT·DINT 4),**对齐由编译器保证**,VM 从 type 位段已知宽度
- 初值写值段(编译期 layout);结构体 = 值区连续字段块(元数据段字段表,v1 预留)
### 3.4 变长指令对 codegen 的影响
- **跳转回填改字节单位**`patch_jump` 按字节(off32,相对下一条),pc/code_offset/code_len 全字节化
- 发射器(E_*)按 fmt 决定长度组(4/8/16B),指令缓冲按字节追加
- 取指/对齐:code 段 16 字节对齐
### 3.5 类型系统扩展(ST 层)
- 12 个 IEC 整数类型 + REAL/LREAL 进关键字(全量支持:声明即可用)
- 类型检查:**隐式升宽**允许(SINT→INT→DINT→LINT、BYTE→WORD→…)、降宽禁止
- 浮点字面量(`1.5``-2.5e3`v1 是否支持——待确认
## 4. 待确认(引用指令集优化.md §4 中编译器相关项)
| 项 | 问题 | 推荐 |
|---|---|---|
| 4 | I/Q/M 六条 LOAD/STORE 合并为两条 | 合并 |
| 5 | 结构体 v1 只留编码不实现语法 | 预留 |
| 6 | ST 层类型全量支持(12 类型名进关键字) | 全量 |
| 7 | 隐式升宽允许、降宽禁止 | 按此 |
| 8 | 字面量:十进制 only(含浮点字面量) | 十进制 |
| 9 | FB 共享体:基址寻址指令实施 | 实施 |
| 10 | REAL/LREAL 引入后 type:4 满编 | 满编(结构体走元数据) |
## 5. 影响面(编译器侧)
| 子模块 | 改动 |
|---|---|
| Lexer | 类型关键字扩展(14 → 16+)、浮点字面量(若确认) |
| Parser | 类型引用、字面量 AST |
| Typecheck | 隐式升宽规则、16 类型元数据 |
| Linker | 槽表条目分配(addr:u32)、FB 实例字段偏移 |
| Codegen | E_* 变长发射、字节化回填、槽表+值区 layout、FB 共享体(若实施)、基址寻址 |
| MachineConfig / machine.toml | type 表 16 条(base/width/signed/tag)、fmt/type 位段互锁校验 |
## 6. 实施阶段(合并进指令集优化.md §6)
- 阶段 2isa)后接**阶段 3compiler 侧)**machine.toml V2 → MachineConfig → Codec → Codegen(槽表/值区/变长发射)→ Stb → 对应测试
- FB 共享体(§3.1)若确认实施,并入阶段 3 的 Codegen 子步骤
## 7. 决策历史
- V1 定案(12.8):用户 FB 内联 / FUNCTION CALL / 内建 FB CAL_*;短路必须跳转;固定寄存器分配
- V2 讨论:用户确认 V1 内联现状;提出 V2 用基址寻址消除内联膨胀(写入 §2.7/§4 项 9)