40个版本
0.0.39 | 2024年7月29日 |
---|---|
0.0.37 | 2024年6月27日 |
0.0.25 | 2024年3月28日 |
0.0.22 | 2023年4月19日 |
0.0.0 | 2021年11月18日 |
#697 in WebAssembly
568 每月下载量
在 weval 中使用
485KB
11K SLoC
WAFFLE:轻量级实验的WebAssembly分析框架
摘要:一个针对Wasm-to-Wasm转换的SSA IR编译器框架,用Rust编写。
状态:针对Wasm MVP工作;成功往返复杂模块
从Wasm到IR和从IR到Wasm的转换工作良好,已通过各种方式进行模糊测试。特别是,waffle通过往返SSA IR进行模糊测试,并在Wasmtime下(限制执行时间)分别执行原始和往返的Wasm。到目前为止,尚未发现任何正确性问题。
Waffle能够往返(转换为IR,然后编译回Wasm)诸如SpiderMonkey JS引擎编译为Wasm的复杂模块。
Waffle有一些基本的中端优化正在运行,例如GVN和常量传播。还有更多可以完成。
生成的Wasm字节码可以通过各种方式改进;目前正在对此进行研究。
架构
IR是由块组成的CFG,包含与Wasm运算符一一对应的运算符。数据流是通过SSA实现的,并且块有块参数(而不是phi节点)。Wasm局部变量在IR中不使用(它们被转换为SSA)。
前端在构建SSA的同时将Wasm转换为这种IR,在发现对局部变量的多个到达定义时插入块参数。多值Wasm(每个控制流块的参数和结果)完全支持,并转换为SSA。这个过程大致类似于Cranelift的方式,除了内存、表等操作保持在Wasm抽象层(不降低到实现细节),并且算术运算符与Wasm完全一致。
后端分为三个阶段操作
-
结构化控制流恢复,它使用 Ramsey的算法 将CFG转换回Wasm控制流原语(块、循环和if-then AST节点)的AST。
-
树化(Treeification),该功能计算某些SSA值是否只被使用一次,并且可以被移动到其唯一消费者之前,直接在Wasm栈上计算值,而不需要中间局部变量。这是一种非常简单的代码调度形式。
-
局部化(Localification),该功能执行寄存器分配(使用简单的线性扫描算法),将所有SSA值分配给局部变量,以确保没有活跃范围在同一个局部变量中重叠。
比较/相关工作
-
类似于Binaryen,但它使用SSA IR而不是基于AST的IR。在没有处理对局部变量的任意读写时,数据流分析要容易得多。Binaryen能够对任意控制流(CFG到Wasm)进行栈化/循环,但不实现反向操作(Wasm到CFG),并且它只有C/C++ API,没有Rust API。
-
类似于Walrus,但它也使用SSA IR。Walrus是用Rust编写的,旨在进行Wasm到Wasm的转换,但其IR紧密地反映了Wasm字节码,因此与传统CFG-of-SSA风格的编译器分析和转换一样,具有相同的困难。
-
在一定程度上类似于Cranelift,因为其IR类似于Cranelift的(具有blockparams的SSA IR的CFG),但还有Wasm后端(Cranelift只做Wasm到IR)。WAFFLE的IR也故意保持在Wasm抽象级别,与所有运算符保持1:1对应,同时保持内存、表格等概念,而Cranelift将操作和存储抽象降低到IR中的运行时/嵌入式特定实现细节。
依赖关系
~9.5MB
~192K SLoC