【发布时间】:2021-04-30 20:40:07
【问题描述】:
我正在开发一种针对 WebAssembly 的纯函数式编程语言的工具链。我对类型理论有点熟悉,因此,该语言的类型检查器已经准备就绪。我现在面临的问题是将这种高级语言翻译成较低级别的 WebAssembly。
在检查类型之后,编译器能够获取 AST 并将其转换为相当标准的超级组合子、lambda-lifted 形式。每个表达式都可以是:
- 函数调用(顶级函数的名称 + 表示参数的表达式)
- 引用(顶级函数或常量的名称);
- 变量(参数名称或本地名称);
- 整数(
i32数字文字); - 双(
f64数字文字); - 字节串(
size+sizeUTF-8 字节序列); - Thunk(顶级函数的名称 + 捕获值的环境)。
函数调用、引用、变量、整数、双精度和字节串是不言自明的。 Thunks 是从部分应用的函数或从 lambda 提升的闭包中获得的。编译器知道 thunk 何时何地饱和,并能够自动插入 force 指令。
指针和数字字面量会很高兴地存在于堆栈中,它们体积小且复制成本低。但是复制字节串,取决于它们有多大,可能会很昂贵,而且还有溢出的可能性。在堆栈内存上操作字节串也需要副本。操作递归数据结构的函数可能需要在每一步都复制整个 thunk。
这意味着一些堆分配将非常有用(几乎是必不可少的),但是没有像malloc/free 这样的工具手动管理堆内存是灾难的根源。 this 之类的线程和 this 之类的帖子提到了我认为仅适用于 C 的 WebAssembly 分配器,我不知道如何将其中一个带入我的语言的运行时。还有 this 存储库,但我不知道如何将这个用 Rust 编写的分配器转换为通用 WebAssembly 模块并使用导出的函数。
如何开始将分配器集成到生成的 WebAssembly 字节码的运行时中,该字节码来自我的语言的编译器?
【问题讨论】:
标签: compiler-construction webassembly