Skip to content

Commit

Permalink
test: draft abi transform test for stdlib blake3 hash function
Browse files Browse the repository at this point in the history
  • Loading branch information
greenhat committed Apr 30, 2024
1 parent 2ac171f commit f417f35
Show file tree
Hide file tree
Showing 9 changed files with 745 additions and 10 deletions.
13 changes: 8 additions & 5 deletions codegen/masm/src/codegen/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,11 +418,14 @@ impl<'b, 'f: 'b> BlockEmitter<'b, 'f> {

fn emit_global_value(&mut self, inst_info: &InstInfo, op: &hir::GlobalValueOp) {
assert_eq!(op.op, hir::Opcode::GlobalValue);
let addr = self
.function
.globals
.get_computed_addr(&self.function.f.id, op.global)
.expect("expected linker to identify all undefined symbols");
let addr = self.function.globals.get_computed_addr(&self.function.f.id, op.global).expect(
format!(
"expected linker to identify all undefined symbols, but failed on func id: {}, \
gv: {}",
self.function.f.id, op.global
)
.as_str(),
);
match self.function.f.dfg.global_value(op.global) {
hir::GlobalValueData::Load { ref ty, .. } => {
let mut emitter = self.inst_emitter(inst_info.inst);
Expand Down
3 changes: 2 additions & 1 deletion sdk/prelude/src/stdlib/crypto/hashes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
//! value per element.
use crate::Felt;

#[link(wasm_import_module = "miden:prelude/std_crypto_hashes")]
// #[link(wasm_import_module = "miden:prelude/std_crypto_hashes")]
#[link(wasm_import_module = "std::crypto_hashes")]
extern "C" {
/// Computes BLAKE3 1-to-1 hash.
///
Expand Down
395 changes: 395 additions & 0 deletions tests/integration/expected/abi_transform_stdlib_blake3_hash.hir

Large diffs are not rendered by default.

295 changes: 295 additions & 0 deletions tests/integration/expected/abi_transform_stdlib_blake3_hash.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
(module $abi_transform_stdlib_blake3_hash.wasm
(type (;0;) (func (param i64) (result f64)))
(type (;1;) (func (param f64 f64 f64 f64 f64 f64 f64 f64 f64 f64 f64 f64 f64 f64 f64 f64 i32)))
(type (;2;) (func (param f64) (result i64)))
(type (;3;) (func (param i32 i32 i32)))
(type (;4;) (func (param i32 i32 i32 i32 i32)))
(import "miden:prelude/intrinsics_felt" "from_u64_unchecked" (func $miden_prelude::intrinsics::felt::extern_from_u64_unchecked (;0;) (type 0)))
(import "std::crypto_hashes" "blake3_hash_2to1<0x0000000000000000000000000000000000000000000000000000000000000000>" (func $miden_prelude::stdlib::crypto::hashes::extern_blake3_hash_2to1 (;1;) (type 1)))
(import "miden:prelude/intrinsics_felt" "as_u64" (func $miden_prelude::intrinsics::felt::extern_as_u64 (;2;) (type 2)))
(func $entrypoint (;3;) (type 3) (param i32 i32 i32)
(local i32 i32 f64)
global.get $__stack_pointer
i32.const 432
i32.sub
local.tee 3
global.set $__stack_pointer
i32.const 0
local.set 4
i64.const 0
call $miden_prelude::intrinsics::felt::extern_from_u64_unchecked
local.set 5
loop ;; label = @1
block ;; label = @2
local.get 4
i32.const 64
i32.ne
br_if 0 (;@2;)
i32.const 0
local.set 4
loop ;; label = @3
block ;; label = @4
local.get 4
i32.const 64
i32.ne
br_if 0 (;@4;)
i32.const 0
local.set 4
i64.const 0
call $miden_prelude::intrinsics::felt::extern_from_u64_unchecked
local.set 5
loop ;; label = @5
block ;; label = @6
local.get 4
i32.const 64
i32.ne
br_if 0 (;@6;)
i32.const 0
local.set 4
block ;; label = @7
loop ;; label = @8
block ;; label = @9
local.get 4
i32.const 64
i32.ne
br_if 0 (;@9;)
local.get 3
f64.load offset=8
local.get 3
f64.load offset=16
local.get 3
f64.load offset=24
local.get 3
f64.load offset=32
local.get 3
f64.load offset=40
local.get 3
f64.load offset=48
local.get 3
f64.load offset=56
local.get 3
f64.load offset=64
local.get 3
f64.load offset=72
local.get 3
f64.load offset=80
local.get 3
f64.load offset=88
local.get 3
f64.load offset=96
local.get 3
f64.load offset=104
local.get 3
f64.load offset=112
local.get 3
f64.load offset=120
local.get 3
f64.load offset=128
local.get 3
i32.const 136
i32.add
call $miden_prelude::stdlib::crypto::hashes::extern_blake3_hash_2to1
local.get 3
i32.const 264
i32.add
local.get 3
i32.const 136
i32.add
i32.const 128
memory.copy
local.get 3
i32.const 416
i32.add
i64.const 0
i64.store
local.get 3
i32.const 408
i32.add
i64.const 0
i64.store
local.get 3
i32.const 392
i32.add
i32.const 8
i32.add
i64.const 0
i64.store
local.get 3
i64.const 0
i64.store offset=392
local.get 3
i32.const 264
i32.add
local.set 2
i32.const 0
local.set 4
loop ;; label = @10
local.get 4
i32.const 32
i32.eq
br_if 3 (;@7;)
local.get 3
local.get 2
f64.load
call $miden_prelude::intrinsics::felt::extern_as_u64
i64.store offset=424
local.get 3
i32.const 392
i32.add
local.get 4
i32.add
i32.const 4
local.get 3
i32.const 424
i32.add
i32.const 4
i32.const 1048620
call $core::slice::<impl [T]>::copy_from_slice
local.get 4
i32.const 4
i32.add
local.set 4
local.get 2
i32.const 8
i32.add
local.set 2
br 0 (;@10;)
end
end
local.get 3
i32.const 72
i32.add
local.get 4
i32.add
local.get 2
i64.load32_u align=1
call $miden_prelude::intrinsics::felt::extern_from_u64_unchecked
f64.store
local.get 4
i32.const 8
i32.add
local.set 4
local.get 2
i32.const 4
i32.add
local.set 2
br 0 (;@8;)
end
end
local.get 0
local.get 3
i64.load offset=392
i64.store align=1
local.get 0
i32.const 24
i32.add
local.get 3
i32.const 392
i32.add
i32.const 24
i32.add
i64.load
i64.store align=1
local.get 0
i32.const 16
i32.add
local.get 3
i32.const 392
i32.add
i32.const 16
i32.add
i64.load
i64.store align=1
local.get 0
i32.const 8
i32.add
local.get 3
i32.const 392
i32.add
i32.const 8
i32.add
i64.load
i64.store align=1
local.get 3
i32.const 432
i32.add
global.set $__stack_pointer
return
end
local.get 3
i32.const 72
i32.add
local.get 4
i32.add
local.get 5
f64.store
local.get 4
i32.const 8
i32.add
local.set 4
br 0 (;@5;)
end
end
local.get 3
i32.const 8
i32.add
local.get 4
i32.add
local.get 1
i64.load32_u align=1
call $miden_prelude::intrinsics::felt::extern_from_u64_unchecked
f64.store
local.get 4
i32.const 8
i32.add
local.set 4
local.get 1
i32.const 4
i32.add
local.set 1
br 0 (;@3;)
end
end
local.get 3
i32.const 8
i32.add
local.get 4
i32.add
local.get 5
f64.store
local.get 4
i32.const 8
i32.add
local.set 4
br 0 (;@1;)
end
)
(func $core::slice::<impl [T]>::copy_from_slice::len_mismatch_fail (;4;) (type 3) (param i32 i32 i32)
unreachable
unreachable
)
(func $core::slice::<impl [T]>::copy_from_slice (;5;) (type 4) (param i32 i32 i32 i32 i32)
block ;; label = @1
local.get 1
local.get 3
i32.ne
br_if 0 (;@1;)
local.get 0
local.get 2
local.get 1
memory.copy
return
end
local.get 1
local.get 1
local.get 1
call $core::slice::<impl [T]>::copy_from_slice::len_mismatch_fail
unreachable
)
(table (;0;) 1 1 funcref)
(memory (;0;) 17)
(global $__stack_pointer (;0;) (mut i32) i32.const 1048576)
(export "memory" (memory 0))
(export "entrypoint" (func $entrypoint))
(data $.rodata (;0;) (i32.const 1048576) "~/sdk/prelude/src/stdlib/crypto/hashes.rs\00\00\00\00\00\10\00)\00\00\00\d1\00\00\00(\00\00\00")
)
5 changes: 3 additions & 2 deletions tests/integration/src/compiler_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ impl CompilerTest {
}

/// Set the Rust source code to compile with `miden-prelude` (stdlib + intrinsics)
pub fn rust_fn_body_with_prelude(name: &str, rust_source: &str) -> Self {
pub fn rust_fn_body_with_prelude(name: &str, rust_source: &str, is_build_std: bool) -> Self {
let cwd = std::env::current_dir().unwrap();
let miden_prelude_path =
cwd.parent().unwrap().parent().unwrap().join("sdk").join("prelude");
Expand Down Expand Up @@ -441,7 +441,8 @@ impl CompilerTest {
.as_str(),
)
.build();
let test = Self::rust_source_cargo_lib(proj.root(), false, Some("entrypoint".to_string()));
let test =
Self::rust_source_cargo_lib(proj.root(), is_build_std, Some("entrypoint".to_string()));
test
}

Expand Down
1 change: 1 addition & 0 deletions tests/integration/src/rust_masm_tests/abi_transform/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod stdlib;
38 changes: 38 additions & 0 deletions tests/integration/src/rust_masm_tests/abi_transform/stdlib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use core::panic;

use expect_test::expect_file;
use proptest::{
arbitrary::any,
test_runner::{TestError, TestRunner},
};

use crate::CompilerTest;

#[test]
fn test_blake3_hash() {
let main_fn = format!(
"(a: [u8; 32], b: [u8; 32]) -> [u8; 32] {{ miden_prelude::blake3_hash_2to1(a, b) }}"
);
let artifact_name = "abi_transform_stdlib_blake3_hash";
let mut test = CompilerTest::rust_fn_body_with_prelude(&artifact_name, &main_fn, true);
// Test expected compilation artifacts
test.expect_wasm(expect_file![format!("../../../expected/{artifact_name}.wat")]);
test.expect_ir(expect_file![format!("../../../expected/{artifact_name}.hir")]);
test.expect_masm(expect_file![format!("../../../expected/{artifact_name}.masm")]);
// let ir_masm = test.ir_masm_program();
// let vm_program = test.vm_masm_program();

// Run the Rust and compiled MASM code against a bunch of random inputs and compare the results
let res =
TestRunner::default().run(&(any::<[u8; 32]>(), any::<[u8; 32]>()), move |(_a, _b)| {
todo!("test against rust");
// run_masm_vs_rust(rs_out, &vm_program, ir_masm.clone(), &args)
});
match res {
Err(TestError::Fail(_, value)) => {
panic!("Found minimal(shrinked) failing case: {:?}", value);
}
Ok(_) => (),
_ => panic!("Unexpected test result: {:?}", res),
}
}
Loading

0 comments on commit f417f35

Please sign in to comment.