Skip to content

Commit 1508883

Browse files
authored
Merge pull request #76 from Shopify/ap.allow-multiple-passes-of-trampoline
Allow multiple passes of trampoline
2 parents 490c9e6 + 7d1ee76 commit 1508883

File tree

3 files changed

+71
-20
lines changed

3 files changed

+71
-20
lines changed

trampoline/src/lib.rs

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ pub struct TrampolineCodegen {
108108

109109
impl TrampolineCodegen {
110110
pub fn new(module: Module) -> walrus::Result<Self> {
111-
let guest_memory_id = module.get_memory_id()?;
111+
let guest_memory_id = Self::guest_memory_id(&module)?;
112112

113113
Ok(Self {
114114
module,
@@ -136,6 +136,21 @@ impl TrampolineCodegen {
136136
})
137137
}
138138

139+
fn guest_memory_id(module: &Module) -> walrus::Result<MemoryId> {
140+
let non_imported_memories = module
141+
.memories
142+
.iter()
143+
.filter(|&memory| memory.import.is_none())
144+
.map(|memory| memory.id())
145+
.collect::<Vec<_>>();
146+
147+
if let Some((memory_id, [])) = non_imported_memories.split_first() {
148+
Ok(*memory_id)
149+
} else {
150+
anyhow::bail!("expected exactly one non-imported guest memory")
151+
}
152+
}
153+
139154
fn emit_memcpy_to_guest(&mut self) -> FunctionId {
140155
let provider_memory_id = self.provider_memory_id();
141156

@@ -470,6 +485,18 @@ mod test {
470485
use super::{TrampolineCodegen, IMPORTS, PROVIDER_MODULE_NAME};
471486
use walrus::Module;
472487

488+
fn trampoline_wat(wat_bytes: &[u8]) -> walrus::Result<String> {
489+
let wasm_buf = wat::parse_bytes(wat_bytes)?;
490+
trampoline_wasm(&wasm_buf)
491+
}
492+
493+
fn trampoline_wasm(wasm_bytes: &[u8]) -> walrus::Result<String> {
494+
let module = Module::from_buffer(wasm_bytes)?;
495+
let codegen = TrampolineCodegen::new(module)?;
496+
let mut result = codegen.apply()?;
497+
wasmprinter::print_bytes(result.emit_wasm())
498+
}
499+
473500
#[test]
474501
fn disassemble_trampoline() {
475502
// to add a new test case, add a new file to the `test_data` directory and run `cargo test`
@@ -478,10 +505,7 @@ mod test {
478505
// environment variable as documented at https://docs.rs/insta/latest/insta/index.html#updating-snapshots
479506
insta::glob!("test_data/*.wat", |path| {
480507
let input = wat::parse_file(path).unwrap();
481-
let module = Module::from_buffer(&input).unwrap();
482-
let codegen = TrampolineCodegen::new(module).unwrap();
483-
let mut result = codegen.apply().unwrap();
484-
let actual = wasmprinter::print_bytes(result.emit_wasm()).unwrap();
508+
let actual = trampoline_wat(&input).unwrap();
485509
insta::assert_snapshot!(actual);
486510
});
487511
}
@@ -495,4 +519,30 @@ mod test {
495519
assert!(module.imports.find(PROVIDER_MODULE_NAME, import).is_some());
496520
}
497521
}
522+
523+
#[test]
524+
fn test_consumer_second_pass_is_a_no_op() {
525+
let input = include_bytes!("test_data/consumer.wat");
526+
let first_wat = trampoline_wat(input).unwrap();
527+
let second_wat = trampoline_wat(first_wat.as_bytes()).unwrap();
528+
529+
assert_eq!(first_wat, second_wat);
530+
}
531+
532+
#[test]
533+
fn test_error_for_multiple_guest_memories() {
534+
let module = r#"
535+
(module
536+
(memory 1)
537+
(memory 1)
538+
)
539+
"#;
540+
let result = trampoline_wat(module.as_bytes());
541+
assert!(result.is_err());
542+
let err = result.unwrap_err();
543+
assert_eq!(
544+
err.to_string(),
545+
"expected exactly one non-imported guest memory"
546+
);
547+
}
498548
}

trampoline/src/snapshots/shopify_function_trampoline__test__disassemble_trampoline@consumer.wat.snap

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,22 @@ input_file: trampoline/src/test_data/consumer.wat
1111
(type (;4;) (func (param i32 i32) (result i64)))
1212
(type (;5;) (func (param i32 i32 i32)))
1313
(type (;6;) (func (param i32 i32 i32) (result i32)))
14-
(type (;7;) (func (param i32 i32 i32 i32) (result i32)))
15-
(type (;8;) (func (param i32 i64) (result i32)))
16-
(type (;9;) (func (param i32 i64 i32) (result i64)))
17-
(type (;10;) (func (param i32 i64 i32 i32) (result i64)))
18-
(type (;11;) (func (param i32 f64) (result i32)))
14+
(type (;7;) (func (param i32 i32 i32 i32)))
15+
(type (;8;) (func (param i32 i32 i32 i32) (result i32)))
16+
(type (;9;) (func (param i32 i64) (result i32)))
17+
(type (;10;) (func (param i32 i64 i32) (result i64)))
18+
(type (;11;) (func (param i32 i64 i32 i32) (result i64)))
19+
(type (;12;) (func (param i32 f64) (result i32)))
1920
(import "shopify_function_v1" "_shopify_function_context_new" (func (;0;) (type 0)))
2021
(import "shopify_function_v1" "_shopify_function_input_get" (func (;1;) (type 2)))
21-
(import "shopify_function_v1" "_shopify_function_input_get_interned_obj_prop" (func (;2;) (type 9)))
22-
(import "shopify_function_v1" "_shopify_function_input_get_at_index" (func (;3;) (type 9)))
23-
(import "shopify_function_v1" "_shopify_function_input_get_obj_key_at_index" (func (;4;) (type 9)))
24-
(import "shopify_function_v1" "_shopify_function_input_get_val_len" (func (;5;) (type 8)))
22+
(import "shopify_function_v1" "_shopify_function_input_get_interned_obj_prop" (func (;2;) (type 10)))
23+
(import "shopify_function_v1" "_shopify_function_input_get_at_index" (func (;3;) (type 10)))
24+
(import "shopify_function_v1" "_shopify_function_input_get_obj_key_at_index" (func (;4;) (type 10)))
25+
(import "shopify_function_v1" "_shopify_function_input_get_val_len" (func (;5;) (type 9)))
2526
(import "shopify_function_v1" "_shopify_function_output_new_bool" (func (;6;) (type 3)))
2627
(import "shopify_function_v1" "_shopify_function_output_new_null" (func (;7;) (type 1)))
2728
(import "shopify_function_v1" "_shopify_function_output_new_i32" (func (;8;) (type 1)))
28-
(import "shopify_function_v1" "_shopify_function_output_new_f64" (func (;9;) (type 11)))
29+
(import "shopify_function_v1" "_shopify_function_output_new_f64" (func (;9;) (type 12)))
2930
(import "shopify_function_v1" "_shopify_function_output_new_object" (func (;10;) (type 3)))
3031
(import "shopify_function_v1" "_shopify_function_output_finish_object" (func (;11;) (type 1)))
3132
(import "shopify_function_v1" "_shopify_function_output_new_array" (func (;12;) (type 3)))
@@ -34,8 +35,8 @@ input_file: trampoline/src/test_data/consumer.wat
3435
(import "shopify_function_v1" "_shopify_function_output_finalize" (func (;15;) (type 1)))
3536
(import "shopify_function_v1" "_shopify_function_input_get_utf8_str_addr" (func (;16;) (type 3)))
3637
(import "shopify_function_v1" "memory" (memory (;0;) 1))
37-
(import "shopify_function_v1" "_shopify_function_input_get_obj_prop" (func (;17;) (type 10)))
38-
(import "shopify_function_v1" "shopify_function_realloc" (func (;18;) (type 7)))
38+
(import "shopify_function_v1" "_shopify_function_input_get_obj_prop" (func (;17;) (type 11)))
39+
(import "shopify_function_v1" "shopify_function_realloc" (func (;18;) (type 8)))
3940
(import "shopify_function_v1" "_shopify_function_output_new_utf8_str" (func (;19;) (type 4)))
4041
(import "shopify_function_v1" "_shopify_function_intern_utf8_str" (func (;20;) (type 4)))
4142
(memory (;1;) 1)
@@ -70,7 +71,7 @@ input_file: trampoline/src/test_data/consumer.wat
7071
local.get 2
7172
call 27
7273
)
73-
(func (;23;) (type 10) (param i32 i64 i32 i32) (result i64)
74+
(func (;23;) (type 11) (param i32 i64 i32 i32) (result i64)
7475
(local i32)
7576
local.get 3
7677
call 25
@@ -84,7 +85,7 @@ input_file: trampoline/src/test_data/consumer.wat
8485
local.get 3
8586
call 17
8687
)
87-
(func (;24;) (type 7) (param i32 i32 i32 i32) (result i32)
88+
(func (;24;) (type 7) (param i32 i32 i32 i32)
8889
local.get 2
8990
local.get 0
9091
local.get 1

trampoline/src/test_data/consumer.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
(import "shopify_function_v1" "shopify_function_input_get_at_index" (func (param i32 i64 i32) (result i64)))
1111
(import "shopify_function_v1" "shopify_function_input_get_obj_key_at_index" (func (param i32 i64 i32) (result i64)))
1212
(import "shopify_function_v1" "shopify_function_input_get_val_len" (func (param i32 i64) (result i32)))
13-
(import "shopify_function_v1" "shopify_function_input_read_utf8_str" (func (param i32 i32 i32 i32) (result i32)))
13+
(import "shopify_function_v1" "shopify_function_input_read_utf8_str" (func (param i32 i32 i32 i32)))
1414

1515
;; Write.
1616
(import "shopify_function_v1" "shopify_function_output_new_bool" (func (param i32 i32) (result i32)))

0 commit comments

Comments
 (0)