Skip to content

Commit 60cf89d

Browse files
feat: (CM64) Make realloc signature match the memory's address type (#2501)
* realloc * fix task.return * files * address comments
1 parent 3fd2bd7 commit 60cf89d

5 files changed

Lines changed: 123 additions & 12 deletions

File tree

crates/wasmparser/src/readers/component/canonicals.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ pub enum CanonicalOption {
1818
/// The realloc function to use if the lifting or lowering of a function requires memory
1919
/// allocation.
2020
///
21-
/// The value is an index to a core function of type `(func (param i32 i32 i32 i32) (result i32))`.
21+
/// The value is an index to a core function of type `(func (param $T $T $T $T) (result $T))` where
22+
/// `$T` is the index type of the memory, i.e., either `i32` or `i64`.
2223
Realloc(u32),
2324
/// The post-return function to use if the lifting of a function requires
2425
/// cleanup after the function returns.

crates/wasmparser/src/validator/component.rs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2635,17 +2635,7 @@ impl ComponentState {
26352635
CanonicalOption::Realloc(idx) => {
26362636
realloc = match realloc {
26372637
None => {
2638-
let ty_id = self.core_function_at(*idx, offset)?;
2639-
let func_ty = types[ty_id].unwrap_func();
2640-
if func_ty.params()
2641-
!= [ValType::I32, ValType::I32, ValType::I32, ValType::I32]
2642-
|| func_ty.results() != [ValType::I32]
2643-
{
2644-
return Err(BinaryReaderError::new(
2645-
"canonical option `realloc` uses a core function with an incorrect signature",
2646-
offset,
2647-
));
2648-
}
2638+
// Validation deferred because it may depend on the memory option.
26492639
Some(*idx)
26502640
}
26512641
Some(_) => {
@@ -2771,6 +2761,29 @@ impl ComponentState {
27712761
bail!(offset, "cannot specify `core-type` without `gc`")
27722762
}
27732763

2764+
// Validate `realloc`
2765+
if let Some(realloc_idx) = realloc {
2766+
let addr_type = match memory {
2767+
// If a memory was specified, `realloc` must match its address type.
2768+
Some(memory_idx) => match self.memory_at(memory_idx, offset)?.memory64 {
2769+
true => ValType::I64,
2770+
false => ValType::I32,
2771+
},
2772+
// Backwards compatibility: Assume `i32` memory if none was specified.
2773+
None => ValType::I32,
2774+
};
2775+
let ty_id = self.core_function_at(realloc_idx, offset)?;
2776+
let func_ty = types[ty_id].unwrap_func();
2777+
if func_ty.params() != [addr_type, addr_type, addr_type, addr_type]
2778+
|| func_ty.results() != [addr_type]
2779+
{
2780+
return Err(BinaryReaderError::new(
2781+
"canonical option `realloc` uses a core function with an incorrect signature",
2782+
offset,
2783+
));
2784+
}
2785+
}
2786+
27742787
Ok(CanonicalOptions {
27752788
string_encoding,
27762789
memory,
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
;; RUN: wast --assert default --snapshot tests/snapshots -f cm64 %
2+
3+
(component
4+
(core module $m
5+
(memory (export "m") i64 1)
6+
(func (export "f") (result i32) unreachable)
7+
(func (export "realloc") (param i64 i64 i64 i64) (result i64) unreachable)
8+
)
9+
(core instance $i (instantiate $m))
10+
(func (result string)
11+
(canon lift (core func $i "f")
12+
(memory $i "m")
13+
(realloc (func $i "realloc"))
14+
)
15+
)
16+
)
17+
18+
(assert_invalid
19+
(component
20+
(core module $m
21+
(memory (export "m") i64 1)
22+
(func (export "f") (param i32 i32))
23+
(func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable)
24+
)
25+
(core instance $i (instantiate $m))
26+
(func (param "p1" (list u8))
27+
(canon lift (core func $i "f")
28+
(memory $i "m")
29+
(realloc (func $i "realloc"))
30+
)
31+
)
32+
)
33+
"canonical option `realloc` uses a core function with an incorrect signature")
34+
35+
(assert_invalid
36+
(component
37+
(core module $m
38+
(memory (export "m") i32 1)
39+
(func (export "f") (param i32 i32))
40+
(func (export "realloc") (param i64 i64 i64 i64) (result i64) unreachable)
41+
)
42+
(core instance $i (instantiate $m))
43+
(func (param "p1" (list u8))
44+
(canon lift (core func $i "f")
45+
(memory $i "m")
46+
(realloc (func $i "realloc"))
47+
)
48+
)
49+
)
50+
"canonical option `realloc` uses a core function with an incorrect signature")
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"source_filename": "tests/cli/component-model/memory64/realloc.wast",
3+
"commands": [
4+
{
5+
"type": "module",
6+
"line": 3,
7+
"filename": "realloc.0.wasm",
8+
"module_type": "binary"
9+
},
10+
{
11+
"type": "assert_invalid",
12+
"line": 19,
13+
"filename": "realloc.1.wasm",
14+
"module_type": "binary",
15+
"text": "canonical option `realloc` uses a core function with an incorrect signature"
16+
},
17+
{
18+
"type": "assert_invalid",
19+
"line": 36,
20+
"filename": "realloc.2.wasm",
21+
"module_type": "binary",
22+
"text": "canonical option `realloc` uses a core function with an incorrect signature"
23+
}
24+
]
25+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
(component
2+
(core module $m (;0;)
3+
(type (;0;) (func (result i32)))
4+
(type (;1;) (func (param i64 i64 i64 i64) (result i64)))
5+
(memory (;0;) i64 1)
6+
(export "m" (memory 0))
7+
(export "f" (func 0))
8+
(export "realloc" (func 1))
9+
(func (;0;) (type 0) (result i32)
10+
unreachable
11+
)
12+
(func (;1;) (type 1) (param i64 i64 i64 i64) (result i64)
13+
unreachable
14+
)
15+
)
16+
(core instance $i (;0;) (instantiate $m))
17+
(type (;0;) (func (result string)))
18+
(alias core export $i "f" (core func (;0;)))
19+
(alias core export $i "m" (core memory (;0;)))
20+
(alias core export $i "realloc" (core func (;1;)))
21+
(func (;0;) (type 0) (canon lift (core func 0) (memory 0) (realloc 1)))
22+
)

0 commit comments

Comments
 (0)