Skip to content

Commit 562ddd5

Browse files
author
Pat Hickey
authored
Merge pull request #49 from Robbepop/robin-improvements
Some improvements + update to cranelift 0.68
2 parents 736e150 + 85a21ea commit 562ddd5

5 files changed

Lines changed: 243 additions & 289 deletions

File tree

‎Cargo.toml‎

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@ authors = ["The Cranelift Project Developers"]
55
license = "Apache-2.0 WITH LLVM-exception"
66
repository = "https://github.com/CraneStation/simplejit-demo"
77
description = "Toy language implemented using cranelift-simplejit"
8-
9-
[[bin]]
10-
name = "toy"
11-
path = "src/toy.rs"
8+
edition = "2018"
129

1310
[dependencies]
14-
cranelift = "0.66.0"
15-
cranelift-module = "0.66.0"
16-
cranelift-simplejit = "0.66.0"
11+
cranelift = "0.68.0"
12+
cranelift-module = "0.68.0"
13+
cranelift-simplejit = "0.68.0"
1714
peg = "0.6"

‎src/bin/toy.rs‎

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use simplejit_demo::jit;
2+
use core::mem;
3+
4+
fn main() -> Result<(), String> {
5+
// Create the JIT instance, which manages all generated functions and data.
6+
let mut jit = jit::JIT::default();
7+
println!("the answer is: {}", run_foo(&mut jit)?);
8+
println!(
9+
"recursive_fib(10) = {}",
10+
run_recursive_fib_code(&mut jit, 10)?
11+
);
12+
println!(
13+
"iterative_fib(10) = {}",
14+
run_iterative_fib_code(&mut jit, 10)?
15+
);
16+
run_hello(&mut jit)?;
17+
Ok(())
18+
}
19+
20+
fn run_foo(jit: &mut jit::JIT) -> Result<isize, String> {
21+
unsafe { run_code(jit, FOO_CODE, (1, 0)) }
22+
}
23+
24+
fn run_recursive_fib_code(jit: &mut jit::JIT, input: isize) -> Result<isize, String> {
25+
unsafe { run_code(jit, RECURSIVE_FIB_CODE, input) }
26+
}
27+
28+
fn run_iterative_fib_code(jit: &mut jit::JIT, input: isize) -> Result<isize, String> {
29+
unsafe { run_code(jit, ITERATIVE_FIB_CODE, input) }
30+
}
31+
32+
fn run_hello(jit: &mut jit::JIT) -> Result<isize, String> {
33+
jit.create_data("hello_string", "hello world!\0".as_bytes().to_vec())?;
34+
unsafe { run_code(jit, HELLO_CODE, ()) }
35+
}
36+
37+
/// Executes the given code using the cranelift JIT compiler.
38+
///
39+
/// Feeds the given input into the JIT compiled function and returns the resulting output.
40+
///
41+
/// # Safety
42+
///
43+
/// This function is unsafe since it relies on the caller to provide it with the correct
44+
/// input and output types. Using incorrect types at this point may corrupt the program's state.
45+
unsafe fn run_code<I, O>(jit: &mut jit::JIT, code: &str, input: I) -> Result<O, String> {
46+
// Pass the string to the JIT, and it returns a raw pointer to machine code.
47+
let code_ptr = jit.compile(code)?;
48+
// Cast the raw pointer to a typed function pointer. This is unsafe, because
49+
// this is the critical point where you have to trust that the generated code
50+
// is safe to be called.
51+
let code_fn = mem::transmute::<_, fn(I) -> O>(code_ptr);
52+
// And now we can call it!
53+
Ok(code_fn(input))
54+
}
55+
56+
// A small test function.
57+
//
58+
// The `(c)` declares a return variable; the function returns whatever value
59+
// it was assigned when the function exits. Note that there are multiple
60+
// assignments, so the input is not in SSA form, but that's ok because
61+
// Cranelift handles all the details of translating into SSA form itself.
62+
const FOO_CODE: &str = r#"
63+
fn foo(a, b) -> (c) {
64+
c = if a {
65+
if b {
66+
30
67+
} else {
68+
40
69+
}
70+
} else {
71+
50
72+
}
73+
c = c + 2
74+
}
75+
"#;
76+
77+
/// Another example: Recursive fibonacci.
78+
const RECURSIVE_FIB_CODE: &str = r#"
79+
fn recursive_fib(n) -> (r) {
80+
r = if n == 0 {
81+
0
82+
} else {
83+
if n == 1 {
84+
1
85+
} else {
86+
recursive_fib(n - 1) + recursive_fib(n - 2)
87+
}
88+
}
89+
}
90+
"#;
91+
92+
/// Another example: Iterative fibonacci.
93+
const ITERATIVE_FIB_CODE: &str = r#"
94+
fn iterative_fib(n) -> (r) {
95+
if n == 0 {
96+
r = 0
97+
} else {
98+
n = n - 1
99+
a = 0
100+
r = 1
101+
while n != 0 {
102+
t = r
103+
r = r + a
104+
a = t
105+
n = n - 1
106+
}
107+
}
108+
}
109+
"#;
110+
111+
/// Let's say hello, by calling into libc. The puts function is resolved by
112+
/// dlsym to the libc function, and the string &hello_string is defined below.
113+
const HELLO_CODE: &str = r#"
114+
fn hello() -> (r) {
115+
puts(&hello_string)
116+
}
117+
"#;

0 commit comments

Comments
 (0)