Skip to content

Instantly share code, notes, and snippets.

@onliniak
Last active June 13, 2024 12:02
Show Gist options
  • Save onliniak/bed0a28ebbca2d3403a8163fe87dba44 to your computer and use it in GitHub Desktop.
Save onliniak/bed0a28ebbca2d3403a8163fe87dba44 to your computer and use it in GitHub Desktop.
WAMR C Bindings
@[Link("iwasm")]
lib LibWasm
struct WASMModuleCommon
buffer : UInt8*
binary_file : UInt32
io_error : LibC::Char*
io_error_bytesize : UInt32
end
struct WASMModuleInstanceCommon
mymodule : WASMModuleCommon*
stack_size : UInt32
heap_size : UInt32
io_error : LibC::Char*
io_error_bytesize : UInt32
end
struct WASMExecEnv
module_inst : WASMModuleInstanceCommon*
stack_size : UInt32
end
struct WASMFunctionInstanceCommon
module_inst : WASMModuleInstanceCommon*
func_name : LibC::Char*
func_signature : LibC::Char*
end
fun wasm_runtime_init : Bool
# fun read_wasm_binary_to_buffer(LibC::Char*, Int32) : LibC::Char*
fun wasm_runtime_load(UInt8*, UInt32, LibC::Char*, UInt32) : WASMModuleCommon*
fun wasm_runtime_instantiate(WASMModuleCommon*, UInt32, UInt32, LibC::Char*, UInt32) : WASMModuleInstanceCommon*
fun wasm_runtime_lookup_function(WASMModuleInstanceCommon*, LibC::Char*, LibC::Char*) : WASMFunctionInstanceCommon*
fun wasm_runtime_create_exec_env(WASMModuleInstanceCommon*, UInt32) : WASMExecEnv*
fun wasm_runtime_call_wasm(WASMExecEnv*, WASMFunctionInstanceCommon*, UInt32, Int32*) : Bool
fun wasm_runtime_get_exception(WASMModuleInstanceCommon*) : LibC::Char*
fun wasm_runtime_destroy_exec_env(WASMExecEnv*)
fun wasm_runtime_deinstantiate(WASMModuleInstanceCommon*)
fun wasm_runtime_unload(WASMModuleCommon*)
fun wasm_runtime_destroy : Nil
end
def exec(wasm_file : String, argv : Array(Int32), io_error = IO::Memory.new, stack_size = 8092, heap_size = 8092)
# initialize the wasm runtime by default configurations
LibWasm.wasm_runtime_init
# read WASM file into a memory buffer
# buffer = LibWasm.read_wasm_binary_to_buffer(wasm_file, wasm_file.bytesize);
# parse the WASM file from buffer and create a WASM module
mymodule = LibWasm.wasm_runtime_load(wasm_file, wasm_file.size, io_error.to_s, io_error.bytesize)
# create an instance of the WASM module (WASM linear memory is ready)
module_inst = LibWasm.wasm_runtime_instantiate(mymodule, stack_size, heap_size, io_error.to_s, io_error.bytesize)
# lookup a WASM function by its name
# The function signature can NULL here
func = LibWasm.wasm_runtime_lookup_function(module_inst, "fib", "(i32i32)")
# creat an execution environment to execute the WASM functions
exec_env = LibWasm.wasm_runtime_create_exec_env(module_inst, stack_size)
# call the WASM function
if LibWasm.wasm_runtime_call_wasm(exec_env, func, argv.size, argv)
# the return value is stored in argv[0]
# 1 = Number of arguments
# argv = array of arguments
p "fib function return: #{argv[0]}"
else
LibWasm.wasm_runtime_get_exception(module_inst)
# exception is thrown if call fails
end
LibWasm.wasm_runtime_destroy_exec_env(exec_env)
LibWasm.wasm_runtime_deinstantiate(module_inst)
LibWasm.wasm_runtime_unload(mymodule)
LibWasm.wasm_runtime_destroy
end
# usage
argv = Array(Int32).new
argv << 8
exec(File.read("fib.wasm"), argv)
(module
(type $i32_i32_=>_i32 (func (param i32 i32) (result i32)))
(type $i32_=>_i32 (func (param i32) (result i32)))
(memory $0 0)
(export "add" (func $src/index/add))
(export "add2" (func $src/index/add2))
(export "sub" (func $src/index/sub))
(export "mul" (func $src/index/mul))
(export "div" (func $src/index/div))
(export "pow" (func $src/index/pow))
(export "memory" (memory $0))
(func $src/index/add (param $0 i32) (param $1 i32) (result i32)
local.get $0
local.get $1
i32.add
)
(func $src/index/add2 (param $0 i32) (result i32)
local.get $0
i32.const 2
i32.add
)
(func $src/index/sub (param $0 i32) (param $1 i32) (result i32)
local.get $0
local.get $1
i32.sub
)
(func $src/index/mul (param $0 i32) (param $1 i32) (result i32)
local.get $0
local.get $1
i32.mul
)
(func $src/index/div (param $0 i32) (param $1 i32) (result i32)
local.get $0
local.get $1
i32.div_s
)
(func $src/index/pow (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
block $__inlined_func$~lib/math/ipow32 (result i32)
i32.const 1
local.set $2
i32.const 1
local.get $1
i32.shl
i32.const 0
local.get $1
i32.const 32
i32.lt_u
select
local.get $0
i32.const 2
i32.eq
br_if $__inlined_func$~lib/math/ipow32
drop
local.get $1
i32.const 0
i32.le_s
if
i32.const -1
i32.const 1
local.get $1
i32.const 1
i32.and
select
local.get $0
i32.const -1
i32.eq
br_if $__inlined_func$~lib/math/ipow32
drop
local.get $1
i32.eqz
local.get $0
i32.const 1
i32.eq
i32.or
br $__inlined_func$~lib/math/ipow32
else
local.get $1
i32.const 1
i32.eq
if
local.get $0
br $__inlined_func$~lib/math/ipow32
else
local.get $1
i32.const 2
i32.eq
if
local.get $0
local.get $0
i32.mul
br $__inlined_func$~lib/math/ipow32
else
local.get $1
i32.const 32
i32.lt_s
if
block $break|0
block $case4|0
block $case3|0
block $case2|0
block $case1|0
block $case0|0
i32.const 31
local.get $1
i32.clz
i32.sub
br_table $case4|0 $case3|0 $case2|0 $case1|0 $case0|0 $break|0
end
local.get $0
i32.const 1
local.get $1
i32.const 1
i32.and
select
local.set $2
local.get $1
i32.const 1
i32.shr_u
local.set $1
local.get $0
local.get $0
i32.mul
local.set $0
end
local.get $0
local.get $2
i32.mul
local.get $2
local.get $1
i32.const 1
i32.and
select
local.set $2
local.get $1
i32.const 1
i32.shr_u
local.set $1
local.get $0
local.get $0
i32.mul
local.set $0
end
local.get $0
local.get $2
i32.mul
local.get $2
local.get $1
i32.const 1
i32.and
select
local.set $2
local.get $1
i32.const 1
i32.shr_u
local.set $1
local.get $0
local.get $0
i32.mul
local.set $0
end
local.get $0
local.get $2
i32.mul
local.get $2
local.get $1
i32.const 1
i32.and
select
local.set $2
local.get $1
i32.const 1
i32.shr_u
local.set $1
local.get $0
local.get $0
i32.mul
local.set $0
end
local.get $0
local.get $2
i32.mul
local.get $2
local.get $1
i32.const 1
i32.and
select
local.set $2
end
local.get $2
br $__inlined_func$~lib/math/ipow32
end
end
end
end
loop $while-continue|1
local.get $1
if
local.get $0
local.get $2
i32.mul
local.get $2
local.get $1
i32.const 1
i32.and
select
local.set $2
local.get $1
i32.const 1
i32.shr_u
local.set $1
local.get $0
local.get $0
i32.mul
local.set $0
br $while-continue|1
end
end
local.get $2
end
)
)
(module
(type (;0;) (func (param i32) (result i32)))
(func (;0;) (type 0) (param i32) (result i32)
local.get 0
i32.const 1
i32.eq
if ;; label = @1
i32.const 1
return
end
local.get 0
i32.const 2
i32.eq
if ;; label = @1
i32.const 1
return
end
local.get 0
i32.const 1
i32.sub
local.get 0
i32.const 2
i32.sub
call 0
i32.add)
(func (;1;) (type 0) (param i32) (result i32)
(local i32 i32 i32 i32)
i32.const 1
local.set 1
i32.const 1
local.set 2
i32.const 2
local.set 4
local.get 0
i32.const 0
i32.le_s
if ;; label = @1
i32.const 0
return
end
local.get 0
i32.const 1
i32.eq
if ;; label = @1
i32.const 1
return
end
loop ;; label = @1
local.get 4
local.get 0
i32.lt_s
if ;; label = @2
local.get 1
local.get 2
i32.add
local.set 3
local.get 2
local.set 1
local.get 3
local.set 2
local.get 4
i32.const 1
i32.add
local.set 4
br 1 (;@1;)
end
end
local.get 2)
(export "fib" (func 1))
(export "fib_iterative" (func 1))
(export "fib_recursive" (func 1)))
@onliniak
Copy link
Author

To coś pokazuje jak mając zerową wiedzę z C użyłem biblioteki w tym języku. Możliwe, że wcześniejsze wersje pomogą Ci zrozumieć błędy jakie popełniasz.

This report shows the user CPU time, system CPU time, the sum of the user and system CPU times, and the elapsed real time. The unit of time is seconds.
fib.wasm
  0.001381   0.009786   0.011167 (  0.015460)
native Crystal
  0.000002   0.000003   0.000005 (  0.000003)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment