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

Download history 5/week @ 2024-04-27 292/week @ 2024-05-04 367/week @ 2024-05-11 218/week @ 2024-05-18 20/week @ 2024-05-25 2/week @ 2024-06-01 1/week @ 2024-06-08 14/week @ 2024-06-15 159/week @ 2024-06-22 23/week @ 2024-06-29 4/week @ 2024-07-06 78/week @ 2024-07-20 476/week @ 2024-07-27 12/week @ 2024-08-03 2/week @ 2024-08-10

568 每月下载量
weval 中使用

Apache-2.0 WITH LLVM-exception

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