Skip to content

Commit

Permalink
chore: add Rust->Wasm->IR Fibonacci example
Browse files Browse the repository at this point in the history
Set opt-level=z (optimize for size) to avoid loops unrolling optimization
in Fibonacci Rust test.
  • Loading branch information
greenhat committed Aug 25, 2023
1 parent 002de0c commit f180c24
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 12 deletions.
25 changes: 25 additions & 0 deletions frontend-wasm/tests/rust_source/fib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#![no_std]
#![no_main]

#[panic_handler]
fn my_panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}

#[inline(never)]
#[no_mangle]
pub fn fib(n: u32) -> u32 {
let mut a = 0;
let mut b = 1;
for _ in 0..n {
let c = a + b;
a = b;
b = c;
}
a
}

#[no_mangle]
pub extern "C" fn __main() -> u32 {
fib(25)
}
121 changes: 109 additions & 12 deletions frontend-wasm/tests/test_rust_comp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,29 @@ use miden_diagnostics::Verbosity;
use miden_frontend_wasm::translate_module;
use miden_frontend_wasm::WasmTranslationConfig;

fn hash_string(input: &str) -> String {
fn hash_string(inputs: &[&str]) -> String {
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
hasher.update(input);
for input in inputs {
hasher.update(input);
}
format!("{:x}", hasher.finalize())
}

fn compile_wasm(rust_source: &str) -> Vec<u8> {
use std::fs;
use std::process::Command;

let file_name = hash_string(rust_source);
let rustc_opts = [
"-C",
"opt-level=z", // optimize for size
"--target",
"wasm32-unknown-unknown",
];

// include rustc_opts in the hash to ensure that the output file changes when options change
let file_name = hash_string(&[&rustc_opts.concat(), rust_source]);

let temp_dir = std::env::temp_dir();
let input_file = temp_dir.join(format!("{file_name}.rs"));
let output_file = temp_dir.join(format!("{file_name}.wasm"));
Expand All @@ -36,14 +47,10 @@ fn compile_wasm(rust_source: &str) -> Vec<u8> {
fs::write(&input_file, rust_source).unwrap();

let output = Command::new("rustc")
.args(&[
"--target",
"wasm32-unknown-unknown",
input_file.to_str().unwrap(),
"-o",
output_file.to_str().unwrap(),
"-O",
])
.args(&rustc_opts)
.arg(&input_file)
.arg("-o")
.arg(&output_file)
.output()
.expect("Failed to execute rustc.");

Expand Down Expand Up @@ -88,7 +95,7 @@ fn default_emitter(verbosity: Verbosity, color: ColorChoice) -> Arc<dyn Emitter>
}

#[test]
fn test_rust_add() {
fn rust_add() {
check_ir(
include_str!("rust_source/add.rs"),
expect![[r#"
Expand Down Expand Up @@ -140,3 +147,93 @@ fn test_rust_add() {
"#]],
);
}

#[test]
fn rust_fib() {
check_ir(
include_str!("rust_source/fib.rs"),
expect![[r#"
(module
(type (;0;) (func (param i32) (result i32)))
(type (;1;) (func (result i32)))
(func $fib (;0;) (type 0) (param i32) (result i32)
(local i32 i32 i32)
i32.const 0
local.set 1
i32.const 1
local.set 2
loop (result i32) ;; label = @1
local.get 2
local.set 3
block ;; label = @2
local.get 0
br_if 0 (;@2;)
local.get 1
return
end
local.get 0
i32.const -1
i32.add
local.set 0
local.get 1
local.get 3
i32.add
local.set 2
local.get 3
local.set 1
br 0 (;@1;)
end
)
(func $__main (;1;) (type 1) (result i32)
i32.const 25
call $fib
)
(memory (;0;) 16)
(global $__stack_pointer (;0;) (mut i32) i32.const 1048576)
(global (;1;) i32 i32.const 1048576)
(global (;2;) i32 i32.const 1048576)
(export "memory" (memory 0))
(export "fib" (func $fib))
(export "__main" (func $__main))
(export "__data_end" (global 1))
(export "__heap_base" (global 2))
)"#]],
expect![[r#"
module noname
pub fn fib(i32) -> i32 {
block0(v0: i32):
v2 = const.int 0 : i32
v3 = const.int 0 : i32
v4 = const.int 1 : i32
br block2(v4, v0, v3)
block1(v1: i32):
block2(v6: i32, v7: i32, v8: i32):
condbr v7, block4, block5
block3(v5: i32):
block4:
v10 = const.int -1 : i32
v11 = add v7, v10 : i32
v12 = add v8, v6 : i32
br block2(v12, v11, v6)
block5:
v9 = ret v8 : ()
}
pub fn __main() -> i32 {
block0:
v1 = const.int 25 : i32
v2 = call fib(v1) : i32
br block1(v2)
block1(v0: i32):
v3 = ret v0 : ()
}
"#]],
);
}

0 comments on commit f180c24

Please sign in to comment.