Wamr Loader/GC giving a type mismatch failure
I'm too sure whether the issue I'm having is with the ocaml wasm compiler or with the bytecodealliance's runtime (wamr).
I've wrote a simple ocaml program:
let _ = Printf.printf "Hello")
compiled it with:
ocamlfind ocamlc -package js_of_ocaml -linkpkg -o hello.byte hello.ml
generated the wasm:
wasm_of_ocaml hello.byte
After building the wamr runtime with the following flags ...
-DWAMR_BUILD_TAIL_CALL=1
-DWAMR_BUILD_EXCE_HANDLING=1
-DWAMR_BUILD_GC=1
... I was able to run a simple wasm file generated from C.
When attempting to run the ocaml wasm file I got the following error:
WASM module load failed: type mismatch: expect (ref ht) but got other
So, could anyone suggest possible ways for me to narrow down the cause of the error?
I think I fixed this issue in https://github.com/bytecodealliance/wasm-micro-runtime/pull/4075.
But the implementation of the GC proposal in WAMR is partial and not sufficient to run programs produced by wasm_of_ocaml. I have just reopened an issue: https://github.com/bytecodealliance/wasm-micro-runtime/issues/4190
Ah, sorry - you're right, I was using an older commit.
However, I rebuilt and this time got a unhandled SIGSEGV, si_addr: 0x575800000002 - it does seem to be fragile
What's the best way of debugging this? Perhaps I should just raise a new issue on bytecodealliance/wasm-micro-runtime?
You can get a backtrace by running it with gdb:
gdb --args ~/sources/wasm-micro-runtime/product-mini/platforms/linux/build/iwasm hello.assets/code*.wasm
It seems it fails because the Wasm module is not a WASI module, and then crashes while trying to unload the module. You can raise an issue on bytecodealliance/wasm-micro-runtime, indeed. By the way, if you want to produce WASI modules (which do not depend on some JavaScript helper code), you should use https://github.com/ocsigen/js_of_ocaml/pull/1831 and compile using the --enable wasi option.
0x000055555567bb68 in destroy_init_expr_data_recursive (module=0x55555574d340,
data=0x555500000005)
at /home/jerome/sources/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c:509
509 wasm_type = module->types[struct_init_values->type_idx];
(gdb) bt
#0 0x000055555567bb68 in destroy_init_expr_data_recursive (
module=0x55555574d340, data=0x555500000005)
at /home/jerome/sources/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c:509
#1 0x000055555567bd7a in destroy_init_expr_data_recursive (
module=0x55555574d340, data=0x55555577f790)
at /home/jerome/sources/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c:552
#2 0x000055555567bc72 in destroy_init_expr_data_recursive (
module=0x55555574d340, data=0x55555577f970)
at /home/jerome/sources/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c:535
#3 0x00005555556a5f7d in destroy_init_expr (module=<optimized out>,
expr=<optimized out>)
at /home/jerome/sources/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c:647
#4 destroy_init_expr (module=<optimized out>, expr=<optimized out>)
at /home/jerome/sources/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c:642
#5 wasm_loader_unload (module=0x55555574d340)
at /home/jerome/sources/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c:6889
#6 0x00005555556a69ac in wasm_loader_load (buf=buf@entry=0x7ffff7e56010 "",
size=size@entry=167172, args=args@entry=0x7fffffffd580,
error_buf=error_buf@entry=0x7fffffffd8f0 "WASM module load failed: a module with WASI apis must export memory by default",
error_buf_size=error_buf_size@entry=128)
at /home/jerome/sources/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c:6794
Thanks for the above! Yes, after building the wasi branch, array as a field in struct object is definitely a show stopper - I'll add frustration to 4190. Thanks again for your help
I think I fixed this issue in bytecodealliance/wasm-micro-runtime#4075.
But the implementation of the GC proposal in WAMR is partial and not sufficient to run programs produced by wasm_of_ocaml. I have just reopened an issue: bytecodealliance/wasm-micro-runtime#4190
I'm going to spend some time on this soon - any suggestions on how to proceed? - ie do I need to attempt to implement the whole gc spec for ocaml on wamr or do I just need a subset?
The GC spec is already mostly implemented. I think there are only two things missing, both related to the initialization of global variables.
First, WAMR does not support nesting arrays inside structures in constant expressions:
(type $bytes (array (mut i8)))
(type $struct (struct (field (ref $bytes))))
(global $s (ref $struct)
(struct.new $struct (array.new_fixed $bytes 1 (i32.const 48))))
This should not be too hard to fix by refactoring a bit core/iwasm/interpreter/wasm_runtime.c.
The other issue is that, with the GC proposal, global.get is a constant instruction and can access preceding (immutable) global definitions:
(type $bytes (array (mut i8)))
(type $block (array (ref eq)))
(global $a (ref $bytes) (array.new_fixed $bytes 1 (i32.const 48)))
(global $b (ref $block) (array.new_fixed $block 1 (global.get $a)))
Given the way the initialization of global variables is performed in WAMR, that might be complicated to implement. But as a temporary workaround, I could add a flag to wasm_of_ocaml so that it does not generate this kind of code.
Thanks for the above! I'll get onto it as soon as I possibly can. Adding a flag to wasm_of_ocaml would be useful - certainly in the early stages of getting wamr/ocaml to work.
I've been doing some work on this in [https://github.com/nickbetteridge/wasm-micro-runtime]
When I compile a simple ocaml file with wasm_of_ocaml and run it with iwasm, I get a WASM module load failed: a module with WASI apis must export memory by default error - is there any way I can run wasm_of_ocaml to include the export or perhaps this is something I need to include in the ocaml file?
When I compile a simple ocaml file with wasm_of_ocaml and run it with iwasm, I get a
WASM module load failed: a module with WASI apis must export memory by defaulterror - is there any way I can run wasm_of_ocaml to include the export or perhaps this is something I need to include in the ocaml file?
Are you sure you used the wasi branch and compiled your program with the --enable wasi flag?
Yes, used —enable wasi
On Tue, 19 Aug 2025 at 16:58, Jérôme Vouillon @.***> wrote:
vouillon left a comment (ocsigen/js_of_ocaml#1929) https://github.com/ocsigen/js_of_ocaml/issues/1929#issuecomment-3201110317
When I compile a simple ocaml file with wasm_of_ocaml and run it with iwasm, I get a WASM module load failed: a module with WASI apis must export memory by default error - is there any way I can run wasm_of_ocaml to include the export or perhaps this is something I need to include in the ocaml file?
Are you sure you used the wasi branch and compiled your program with the --enable wasi flag?
— Reply to this email directly, view it on GitHub https://github.com/ocsigen/js_of_ocaml/issues/1929#issuecomment-3201110317, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC3HXJLPDWXGIZ4O2CVGONL3OM3RRAVCNFSM6AAAAAB2377W2WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTEMBRGEYTAMZRG4 . You are receiving this because you authored the thread.Message ID: @.***>
I have tried with an empty OCaml program. Your branch of Wamr was compiled with
cmake .. -DWAMR_BUILD_GC=1 -DWAMR_BUILD_EXCE_HANDLING=1 -DWAMR_BUILD_TAIL_CALL=1 -DWAMR_BUILD_FAST_INTERP=0
When compiling with wasm_of_ocaml --enable wasi /tmp/a.out, I get the following errors:
$ ~/sources/wasm-micro-runtime/product-mini/platforms/linux/build/iwasm /tmp/a.assets/code.wasm
[...]
[14:17:06:425 - 7B5C41ABE780]: Invalid heap object pointer detected: 0x5d86fffffff0 (heap: 0x7b5c41a9d2cc-0x7b5c41abd00c)
[14:17:06:425 - 7B5C41ABE780]: warning: failed to allocate memory for gc object
Exception: create array object failed
With just wasm_of_ocaml /tmp/a.out, I get the following errors:
$ ~/sources/wasm-micro-runtime/product-mini/platforms/linux/build/iwasm /tmp/a.assets/code-4179a667264f1fc2c2b4.wasm
WASM module load failed: a module with WASI apis must export memory by default
Ah - that's what happens when you're in a rush to get down to the South of France and copy the wrong tree onto a small 10 year-old laptop!
Anyhow - a quick question - I'm trying to get your tests to run and the ones that are failing (with null references) are the ones depending on io/stdlib runtime - ie printf. I've '--enable wasi' so I'm not too sure if I also need to also either '--link' or '--link-wasm' as well? As I'm not currently using dune with using wasm_of_ocaml (compilation_mode), what is the build-chain that I'm missing?
No, you don't have to do anything special.
I'm having an issue with string_of_int.
let () =
print_endline "Testing Option value extraction";
let x = Some 42 in
print_endline "Option created";
match x with
| Some n ->
print_endline "Matched Some";
print_endline ("Value: " ^ (string_of_int n))
| None ->
print_endline "No value"
The crash occurs right after "Matched Some" is printed. The issue happens when OCaml tries to extract the integer value from the Some wrapper and use it in string_of_int.
I'm having to use Claude here for debugging this, and I'm not too sure if what it understands is correct, and what it proposes is the best way forward.
The Issue: The object 0x56910000002a contains the value 0x2a (which is 42
in hex), but it's NOT a proper i31 object. When OCaml tries to cast it to
i31 type for use in string_of_int, the cast fails because WAMR doesn't
recognize it as a valid i31 reference.
The Analysis:
- 0x56910000002a - This looks like a heap object pointer with the value 42
(0x2a) in the lower bits
- Expected: An i31-encoded reference like 0x55 (which we saw working in
earlier tests)
- Actual: A heap object that contains the value 42 but is not itself an
i31 reference
This confirms our hypothesis: OCaml stores the integer 42 inside a GC
object wrapper (probably as a struct field), and when it extracts the
value for use in string_of_int, it tries to cast the wrapper object to i31
type instead of extracting the contained value first.
The solution requires either:
1. Fix WAMR's i31 cast validation to handle wrapped integers correctly, OR
2. Fix WAMR's struct.get operations to properly extract i31 values from GC
object fields
What are your thoughts on this?
Another quick question - do you know of any work-in-progress, which might be publicly released, which relates to WIT [1]. This seems like the obvious way forward with interfacing with the real world. If nothing is happening on this front then I'll put something together - I could build this into js_of_ocaml or, alternatively, make it a separate library?
[1] https://component-model.bytecodealliance.org/design/wit.html
I'm having an issue with
string_of_int.
How can I reproduce this?
I'm not aware of any WIT-related work. It probably makes more sense to make it a separate library.
I'm having an issue with
string_of_int.How can I reproduce this?
git clone https://github.com/nickbetteridge/wasm-micro-runtime
git clone https://github.com/nickbetteridge/wasm-micro-runtime-ocaml-test
# cd wasm-micro-runtime-ocaml-test
Edit the Makefile to set WAMR_DIR to the appropriate path.
# make build-wamr
# make test_option_extract_value.wasm
make run-test_option_extract_value
There are similar issues with other tests, such as test_pattern_match_debug, with externref and casting being the bad actors
I31 values in globals are not correctly initialized:
diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c
index addd0fc7..bae2a85b 100644
--- a/core/iwasm/interpreter/wasm_loader.c
+++ b/core/iwasm/interpreter/wasm_loader.c
@@ -1455,6 +1455,7 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
error_buf, error_buf_size)) {
goto fail;
}
+ cur_value.gc_obj = (WASMObjectRef) wasm_i31_obj_new(cur_value.i32);
wasm_set_refheaptype_common(&cur_ref_type.ref_ht_common,
false, HEAP_TYPE_I31);
There is still something wrong with the test since it outputs Value: 85 instead of Value: 42. I don't really see why since the interpreter seems to do the right thing for the instruction WASM_OP_I31_GET_S.
For test_pattern_match_debug, it seems one get an incorrect pointer, since no externref is expected there.
Actually, the fix above is incorrect. The issue is here: https://github.com/nickbetteridge/wasm-micro-runtime/blob/7ed8696a7f09053891ad0f70adec1969338269a3/core/iwasm/interpreter/wasm_runtime.c#L1193-L1194
wasm_array_obj_set_elem(array_obj, elem_idx,
&init_values->elem_data[elem_idx]);
The contents of init_values should be first converted into the appropriate Wasm object when the element has a reference type.
And here as well: https://github.com/nickbetteridge/wasm-micro-runtime/blob/7ed8696a7f09053891ad0f70adec1969338269a3/core/iwasm/interpreter/wasm_runtime.c#L3263C44-L3265
Well, I gave up, in the end, with wamr and switched to using wasmtime - I'm getting relatively small runtimes which are acceptable for the controllers, and to ease the flow I wrote a wit library. I'd like to release the wit library quite soon but I'm being held up by the wasi runtime PR - just the convenience of not requiring users to build a branch etc. Do you have any idea when the PR is likely to be merged? Also, thanks again for all the help you provided in trying to get wamr to run