Files
Interpreter/Doc/compiler/STCompiler使用说明.md
T

7.5 KiB
Raw Blame History

STCompiler 使用说明

把 ST 工程(project.toml + 若干 .st)编译成单一映像 .stb。执行由 BytecodeExecutor 负责。

构建

cmake --preset gcc-debug          # 配置
cmake --build --preset gcc-debug  # 编译
ctest --test-dir build/gcc-debug  # 测试(14/14 全绿)

可执行文件:build/gcc-debug/compiler/STCompiler

用法

STCompiler <project.toml> [-o <name>.stb] --machine <machine.toml>
STCompiler <name>.stb --disasm --machine <machine.toml>
参数 作用
<project.toml> 工程文件(必填)
-o <name>.stb 编译并写出映像文件(+ sidecar);缺省时只打印文件集合与工程哈希(不需 --machine
--machine <machine.toml> 机器定义(指令 opcode / 类型 / FB 布局,见 Doc/isa/指令配置.md);编译与 --disasm 必填,加载/校验失败报错退出
<name>.stb --disasm 反汇编一个已编译的映像(不重新编译,见下)
--help 打印帮助

退出码:0 成功;1 失败(错误信息打到 stderr)。

反汇编(--disasm

对已编译的 .stb 逐段查看:段摘要(含型号与 SHA 校验)、函数表逐条指令(文件绝对偏移)、常量表、数据段 hex。

$ STCompiler line1.stb --disasm --machine machine.toml
image: line1.stb (399 bytes)
header:
  magic       = 0x43545353    # 魔数 "STSC"
  version     = 2             # 格式版本(V2
  model       = STATOR2        # 型号标识
  ...
  n_slots     = 5              # 槽表条目数
  values_size = 7              # 值段字节数
  max_stack   = 116            # 栈区字节数(编译期算)
  sha         = ok             # 文件尾 SHA-256 完整性
functions:
  fn 0: nregs=8, offset=0, len=4
    0x0098  RET
  fn 1: nregs=13, offset=4, len=164
    0x009c  LOAD.U8 r8, s1
    0x00a4  STORE_OFF.U8 r8, s4, 0
    ...
slots:
  [0] addr=0
data (7 bytes):
  0x0000: ...

说明:

  • 指令偏移是文件绝对字节偏移,可直接对照 xxd line1.stbV2 指令变长 4/8/16/32B
  • 映像里没有符号名(函数表只有 fn_id,槽表/值段无名字映射),因此按 fn 0 / fn 1、槽号显示;--dump-map 可打印变量/槽映射
  • model= 显示型号标识(machine.toml [meta] 生成);sha=ok|BAD 显示文件尾 SHA-256 校验结果
  • 文件损坏或打不开 → error: ... 退出码 1

编译产物(.stb 加固)

  • 型号标识[32][meta] name + version 拼成(如 "STATOR2"),写进头(V2 头 128BkOffModelId=32
  • SHA-256 文件尾[32]:对文件尾之前全部内容计算;compiler 写侧与 vm 读侧各实现一份
  • 执行器读取时型号不匹配 / SHA 不符 → 直接拒绝(详见 Doc/isa/指令与映像.md 12.13 修订)

示例(line1

$ STCompiler examples/line1/project.toml
project: line1
files:
  globals.st
  motor.st
  main.st
hash: 0xc3fe4ae74ad45900

$ STCompiler examples/line1/project.toml -o line1.stb --machine compiler/machine.toml
compiled: line1.stb (399 bytes, 2 functions, 4 globals)

产物:line1.stb(399 字节:头 128B 含型号标识 + 各段 + SHA-256 文件尾)+ line1.runtime.tomlsidecar)。指令见 Doc/isa/指令与映像.md,结构拆解见 Doc/isa/stb文件格式.md

工程文件(project.toml

只做三件事:列出源文件、指定唯一 GVL、可选地把已声明全局接到硬件。不声明变量。

字段 必填 说明
project.name 工程名
project.entry 第一版必须 "program MAIN"
project.cycle_limit 每周期指令上限(>0
project.dt_ms 本周期 Δt 毫秒(>0),给内置 FB 定时器
files.st 源文件列表(非空数组)
gvl.file 唯一允许 VAR_GLOBAL 的文件;已在 files.st 则不重复收录
[[io.input]] / [[io.output]] var + channel + bitvar 必须已在 GVL 声明
[project]
name = "line1"
entry = "program MAIN"
cycle_limit = 100000
dt_ms = 10

[files]
st = ["globals.st", "motor.st", "main.st"]

[gvl]
file = "globals.st"

[[io.input]]
var = "EmergencyStop"
channel = 0
bit = 2

ST 子集(第一版)

POUPROGRAM / FUNCTION / FUNCTION_BLOCK(含对应 END_*)。

变量段VAR / VAR_INPUT / VAR_OUTPUT / VAR_GLOBAL(仅 gvl.file 顶层)/ VAR_EXTERNAL

类型19 种(BOOL/SINT/INT/DINT/LINT/BYTE/WORD/DWORD/LWORD/USINT/UINT/UDINT/ULINT/REAL/LREAL/TIME/DATE/TOD/DT);内建 FB 15 条(TON/TOF/TP/CTU/DCTU/CTD/DCTD/CTUD/DCTUD/R_TRIG/F_TRIG/SR/RS/PWM/RTC,关键字,不可作变量名;FB 名三层判定:toml fb 表 → 用户 FB → 类型名)。

语句:赋值 :=IF / ELSIF / ELSE / END_IFWHILE / END_WHILE、FB 调用 fb(in := ..., ...);、字段读 fb.Q

表达式:字面量(TRUE/FALSE、整数、T#10ms 式 TIME、R#/D#/TOD#/DT# 浮点与日期)、NOTAND/OR短路)、比较 = <> < <= > >=(不连锁)、算术 + - * /、一元负号、函数调用 Add(3, 4)

函数:结果 = 函数名赋值(Add := a + b;);返回类型 FUNCTION Add : INT;调用约定:结果 r0、参数 r1..r7(最多 7 个输入,函数内只读)、变量与临时从 r8 起(见 Doc/compiler/寄存器码.md)。

限制(v1 明确不做):指针 / REF / CLASS / ANY / VAR_IN_OUT(语法层直接拒绝)、链式比较、FB 字段赋值、字符串、用户类型套娃、隐式类型转换(类型检查层拒绝,字面量按目标类型适配)、函数循环调用(链接层拒绝)、FUNCTION 写全局(类型检查层拒绝,含经 VAR_EXTERNAL)。

编译管线与错误类别

project.toml + .st
  → 词法(lex error)→ 语法(syntax error)→ 链接(link error
  → 类型检查(type error)→ 寄存器码(codegen error)→ .stb

错误消息前缀即阶段:lex error / syntax error / link error / type error / codegen error,均带文件与行列(type error 仅带文件)。

类别 示例
lex error 非法字符、未闭合注释、坏 T# 字面量
syntax error END_*VAR_IN_OUT 等保留名、链式比较
link error 非 GVL 文件写 VAR_GLOBAL、同名全局、io.var 未在 GVL、未声明实例、循环调用
type error FUNCTION 写全局、AND 吃 INT、赋值类型不匹配、FB 输入类型不匹配
codegen error 寄存器溢出、写 io.input、写函数输入

样例与测试

  • examples/line1/:最小闭环(MAIN + MotorStarter FB + I/O + 全局),给人看
  • tests/cases/01~20/20 个用例(每份 project.toml + .st + EXPECTED.md),编译结果按表
  • tests/CTest 14 项(compiler_toml / lexer_tokens / parser_syntax / linker_links / typecheck_types / codegen_slice1 / isa_roundtrip / machine_config / vm_test / vm_cycles / cases_all / cli_*

当前状态

  • 可编译:14 个正例用例全部产出 .stbV2 头 128B + 型号标识 + SHA-256);6 个负例按期望拒绝
  • 执行:BytecodeExecutor 加载 .stb 跑扫描周期(型号/SHA 校验、回放、单步),V2 槽表两级采样
  • 配置驱动:指令 opcode / 类型元数据 / FB 布局来自 compiler/machine.toml--machine