您好!
这是一个使用 Cranelift JIT 实现一个简单语言的演示。
使用开发中的新 JIT 接口 。JIT 负责管理符号表、分配内存和执行重定位,提供相对简单的 API。
这个Demo受到了 Ulysse Carion 的 llvm-rust-getting-started 和 Jonathan Turner 的rustyjit的启发。
Cranelift 简介: Cranelift 是一个编译器后端。它是轻量级的,支持no_std模式,本身不使用浮点,并且可以有效地利用内存。
Cranelift 的架构允许人们灵活地使用它。有时,这种灵活性可能是一种负担,我们最近开始在一组新的 crate 中解决这个问题,cranelift-module,cranelift-jit、 和 cranelift-faerie它们将各个部分组合成一些易于使用的配置,以便同时处理多个功能。cranelift-module 是一个通用接口,用于同时处理多个功能和数据接口。这个接口可以位于上面cranelift-jit,它将代码和数据写入内存,在那里可以执行和访问它们。而且,它可以位于 .o 之上cranelift-faerie,后者将代码和数据写入本机 .o 文件,这些文件可以链接到本机可执行文件。
这篇文章通过使用cranelift-jit来介绍 Cranelift 。目前,此演示适用于 Linux x86-64 平台。它也可以在 Mac x86-64 平台上运行,尽管我还没有专门测试过。Cranelift 的设计目的是在未来支持许多其他类型的平台。
演练
首先,让我们快速浏览一下使用的语言。这是一种非常简单的语言,其中所有变量都有type isize。(Cranelift 确实完全支持其他整数和浮点类型,所以这只是为了保持语言的简单)。
为了快速了解一下,这是我们在语言中的第一个示例:
fn foo(a, b) -> (c) {
c = if a {
if b {
30
} else {
40
}
} else {
50
}
c = c + 2
}
这个语言的语法在这里定义,他使用peg解析器生成器库为其生成实际的解析器代码。
解析的输出是自定义的 AST 类型:
pub enum Expr {
Literal(String),
Identifier(String),
Assign(String, Box<Expr>),
Eq(Box<Expr>, Box<Expr>),
Ne(Box<Expr>, Box<Expr>),
Lt(Box<Expr>, Box<Expr>),
Le(Box<Expr>, Box<Expr>),
Gt(Box<Expr>,<