WABT 上游提案测试目录 test/spec-new 解析:以 wide-arithmetic 测试集为例
2026/9/16 11:08:03 网站建设 项目流程

WABT 上游提案测试目录 test/spec-new 解析:以 wide-arithmetic 测试集为例

【免费下载链接】wabtThe WebAssembly Binary Toolkit项目地址: https://gitcode.com/GitHub_Trending/wa/wabt

导读

test/spec-new/是 WABT(WebAssembly Binary Toolkit)仓库中一个专门承接「尚未纳入官方 testsuite 的上游提案测试」的目录。本篇文章以其中的 wide-arithmetic.wast 为核心案例,剖析该目录的存在意义、测试文件的结构与断言手法(包括 overlong 二进制编码与类型检查),并结合 opcode.def、lexer-keywords.txt 与 interp.cc 等源码,讲清 WABT 对i64.add128i64.sub128i64.mul_wide_si64.mul_wide_u四个 128 位宽算术操作码的词法、二进制解析与解释器支持现状。读完本文,你将掌握 WABT 提案测试的接入机制、测试文件写作范式以及如何定位源码中的对应实现。

test/spec-new 目录:上游提案测试的过渡缓冲区

test/spec-new/README.md 用寥寥数行说明了该目录的全部设计意图:

本目录包含来自上游提案的测试,这些测试要么尚未进入 testsuite 仓库,要么位于我们(WABT)尚未支持/导入的 testsuite 版本中。

这句话概括了目录的两种典型用途:

  1. 提案仍在演进中:对应的 WebAssembly 提案(proposal)测试已经写好,但官方 [testsuite] 仓库尚未合并;
  2. testsuite 版本滞后:测试已进入 testsuite,但当前 WABT 依赖的 testsuite 子模块版本还未包含它,无法直接通过常规路径导入。

README 明确给出了本目录唯一一个测试文件的出处:

wide-arithmetic.wast来自 WebAssembly/testsuite 仓库的proposals/wide-arithmetic目录。

并注明了一个重要的生命周期约定:一旦 WABT 导入了包含该测试的最新版 testsuite 仓库,本目录中的该文件即可删除。也就是说,test/spec-new是介于「上游提案诞生」与「正式并入官方测试集」之间的过渡缓冲区,避免 WABT 在等待 testsuite 更新的空窗期内丢失对这些提案的回归覆盖。

这种「先落地、后转正」的测试接入策略,保证了 WABT 的工具链(wat2wasmwasm2watwast2json等)始终与正在演进中的 WebAssembly 提案保持同步验证,而不是被动等待官方测试集的一次性大更新。

wide-arithmetic.wast:128 位宽算术提案测试全解

wide-arithmetic.wast 共 470 行,是一个结构相当完整的提案测试文件,覆盖了功能正确性、二进制编码兼容性与类型检查三个维度。

模块定义:四个导出函数

测试文件开头定义一个 WAT 模块,导出了 4 个包装函数,分别对应 wide-arithmetic 提案的 4 个操作码:

(module (func (export "i64.add128") (param i64 i64 i64 i64) (result i64 i64) local.get 0 local.get 1 local.get 2 local.get 3 i64.add128) (func (export "i64.sub128") (param i64 i64 i64 i64) (result i64 i64) local.get 0 local.get 1 local.get 2 local.get 3 i64.sub128) (func (export "i64.mul_wide_s") (param i64 i64) (result i64 i64) local.get 0 local.get 1 i64.mul_wide_s) (func (export "i64.mul_wide_u") (param i64 i64) (result i64 i64) local.get 0 local.get 1 i64.mul_wide_u) )

从中可以提炼出这 4 个操作码的类型签名:

操作码参数结果语义
i64.add1284 × i64(低 64 位、高 64 位各两个操作数)2 × i64(和 的低 64 位、高 64 位)128 位加法
i64.sub1284 × i642 × i64128 位减法
i64.mul_wide_s2 × i642 × i64带符号 128 位宽乘法
i64.mul_wide_u2 × i642 × i64无符号 128 位宽乘法

这些签名与 opcode.def 中的操作码定义一一对应:

WABT_OPCODE(I64, I64, I64, I64, I64, 0, 0xfc, 0x13, I64Add128, "i64.add128", "") WABT_OPCODE(I64, I64, I64, I64, I64, 0, 0xfc, 0x14, I64Sub128, "i64.sub128", "") WABT_OPCODE(I64, I64, I64, I64, ___, 0, 0xfc, 0x15, I64MulWideS, "i64.mul_wide_s", "") WABT_OPCODE(I64, I64, I64, I64, ___, 0, 0xfc, 0x16, I64MulWideU, "i64.mul_wide_u", "")

可以看到:四个操作码都属于0xfc前缀段,子码依次为0x130x16;类型位中___表示「无」,与mul_wide_*只有 2 个参数的事实吻合。

功能断言:简单用例 + 随机生成用例

测试的主体部分是assert_return断言,分为两类:

简单用例覆盖了最容易出错的边界情况,例如 128 位加法的进位传播:

(assert_return (invoke "i64.add128" (i64.const 1) (i64.const 0) (i64.const -1) (i64.const 0)) (i64.const 0) (i64.const 1))

这里低 64 位1 + (-1) = 0产生向高 64 位的进位,高 64 位0 + 0 + 进位 = 1,结果应为(0, 1)。类似地,减法用例覆盖借位传播:

(assert_return (invoke "i64.sub128" (i64.const 0) (i64.const 0) (i64.const 1) (i64.const 1)) (i64.const -1) (i64.const -2))

mul_wide的简单用例则验证符号处理:i64.mul_wide_s (-1) × (-1) → (1, 0);而无符号版本中i64.mul_wide_u (-1) × 1 → (-1, 0),即0xFFFFFFFFFFFFFFFF × 1的低 64 位仍为全 1。

随机生成用例数量庞大且分布全面:文件随后给出了各 20 个随机生成的i64.add128i64.sub128i64.mul_wide_si64.mul_wide_u用例(共 80 个),覆盖大量跨符号、跨进位边界的随机 64 位操作数组合,例如:

(assert_return (invoke "i64.add128" (i64.const 1) (i64.const -5381447440966559717) (i64.const 1020031372481336745) (i64.const 1)) (i64.const 1020031372481336746) (i64.const -5381447440966559716))

这类随机用例由提案作者离线生成、固化到测试文件中,用于对实现做统计意义上的正确性检验,比手工边界用例更能暴露进位/借位链路中的隐蔽缺陷。

overlong 二进制编码测试:对 LEB128 的宽松性验证

测试中段插入了一个完整的module binary模块,其用意非常明确:验证二进制读取器接受每个操作码的 overlong(过长)LEB128 编码。WABT 中这些操作码的二进制编码由前缀0xfc+ LEB128 编码的子码构成,例如i64.add128的标准编码为fc 13,而测试给出的是:

"\fc\93\80\00" ;; i64.add128 (overlong) "\fc\94\00" ;; i64.sub128 (overlong) "\fc\95\80\80\80\00" ;; i64.mul_wide_s (overlong) "\fc\96\80\80\00" ;; i64.mul_wide_u (overlong)

LEB128 是允许「加长表示」的变长整数编码:0x93 0x80 0x00的低 7 位依次为0x130x000x00,解码结果仍是0x13,只是本可 1 字节完成的值被写成了 3 字节。这类 overlong 编码通常被规范视为可接受(canonical 之外)的形式,读取器应当宽容处理。这段测试因此专门验证 WABT 的 binary-reader.cc 在解析0xfc前缀段时能正确容忍并解码这些非规范编码——文件中的assert_return断言确认了这些模块不仅可被解析,其函数调用结果也完全符合预期。

assert_invalid:类型检查的负向测试

测试文件的最后一部分针对 4 个操作码各给出两组assert_invalid用例,验证验证器(validator)能够拒绝签名不匹配的模块。例如:

(assert_invalid (module (func (param i64 i64 i64 i64) (result i64) local.get 0 local.get 1 local.get 2 local.get 3 i64.add128) ) "type mismatch")

以及参数个数不足(3 个参数而非 4 个)的用例。这确认了 WABT 的共享验证器对宽算术操作码实施了严格的栈类型与结果数量检查,错误消息统一为"type mismatch"

源码视角:WABT 对这 4 个操作码的支持现状

词法层:关键字注册

src/lexer-keywords.txt 中为四个操作码注册了词法关键字及其运算元类别:

i64.add128, TokenType::Quaternary, Opcode::I64Add128 i64.mul_wide_s, TokenType::Binary, Opcode::I64MulWideS i64.mul_wide_u, TokenType::Binary, Opcode::I64MulWideU

Quaternary(四元)对应 4 参数操作码,Binary(二元)对应 2 参数操作码,与提案签名完全对应。该文件经生成流程产出 src/prebuilt/lexer-keywords.cc,供wat2wasmwast2json等工具在文本解析阶段识别这些助记符——这也是wide-arithmetic.wast能被正确解析的前提。

解释器层:尚未实现

在 src/interp/interp.cc 中,这 4 个操作码被显式标记为未实现:

case O::I64Add128: case O::I64Sub128: case O::I64MulWideS: case O::I64MulWideU: return TRAP("not implemented");

从源码结构可以推断:WABT 的解释器(wasm-interpspectest-interp)目前对这四个宽算术操作码一律返回"not implemented"陷阱,尚未给出真正的执行语义。这也从侧面解释了为什么这些测试仍停留在test/spec-new的「过渡区」——工具链的解析、验证链路已就绪,但运行时语义支持还在推进中。

如何运行这些测试

WABT 的测试由 test/run-tests.py 驱动,每个.wast测试文件通常伴随一个描述测试方式的.txt元数据文件。本目录的 wide-arithmetic.txt 内容如下:

;;; TOOL: wast2json ;;; STDIN_FILE: test/spec-new/wide-arithmetic.wast

它声明了两个关键信息:

  • TOOL: wast2json:本次测试使用wast2json工具(src/tools/wast2json.cc)处理测试文件,负责将.wast中的模块、断言逐一转换,验证文本解析、二进制编码与验证器的正确性;
  • STDIN_FILE:测试文件通过标准输入喂给工具,这是 WABT 测试框架对「零长度文件」「stdin 输入」等场景的通用支持方式。

运行全部测试只需执行python3 test/run-tests.py;单独验证本目录时,可将其作为run-tests.py的过滤参数传入。测试通过的标准是:wast2json能无错误地完成解析与类型检查,且所有assert_returnassert_invalid断言得到预期结果。

小结

test/spec-new/是 WABT 与上游 WebAssembly 提案演进保持同步的窗口:它承接尚未进入官方 testsuite 的提案测试,并在 testsuite 更新后随时可被清空转正。以wide-arithmetic.wast为例可以看到,一份合格的提案测试需要同时覆盖功能正确性(简单边界 + 大规模随机用例)、二进制编码兼容性(overlong LEB128 的宽容解析)与类型安全assert_invalid负向用例)。而在 WABT 源码侧,这四个 128 位宽算术操作码已具备完整的词法关键字、0xfc前缀段二进制定义与验证支持,唯独解释器运行时不支持——这正是它们仍停留在test/spec-new、尚未并入主线测试目录的直接原因。关注 test/spec-new 目录的增删变化,即可追踪 WABT 对 wide-arithmetic 等新提案的跟进进度。

【免费下载链接】wabtThe WebAssembly Binary Toolkit项目地址: https://gitcode.com/GitHub_Trending/wa/wabt

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询