summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/JSPI.cpp28
-rw-r--r--test/lit/passes/jspi.wast48
2 files changed, 71 insertions, 5 deletions
diff --git a/src/passes/JSPI.cpp b/src/passes/JSPI.cpp
index 8ed2ba832..c7c8493d8 100644
--- a/src/passes/JSPI.cpp
+++ b/src/passes/JSPI.cpp
@@ -155,9 +155,33 @@ private:
params.push_back(param);
++i;
}
-
+ auto* block = builder.makeBlock();
+ // Store the suspender so it can be restored after the call in case it is
+ // modified by another entry into a Wasm export.
+ auto supsenderCopyIndex = Builder::addVar(stub.get(), externref);
+ // If there's a return value we need to store it so it can be returned
+ // after restoring the suspender.
+ std::optional<Index> returnIndex;
+ if (stub->getResults().isConcrete()) {
+ returnIndex = Builder::addVar(stub.get(), stub->getResults());
+ }
+ block->list.push_back(builder.makeLocalSet(
+ supsenderCopyIndex, builder.makeGlobalGet(suspender, externref)));
+ if (returnIndex) {
+ block->list.push_back(builder.makeLocalSet(*returnIndex, call));
+ } else {
+ block->list.push_back(call);
+ }
+ // Restore the suspender.
+ block->list.push_back(builder.makeGlobalSet(
+ suspender, builder.makeLocalGet(supsenderCopyIndex, externref)));
+ if (returnIndex) {
+ block->list.push_back(
+ builder.makeLocalGet(*returnIndex, stub->getResults()));
+ }
+ block->finalize();
call->type = im->getResults();
- stub->body = call;
+ stub->body = block;
wrapperIm->type = Signature(Type(params), call->type);
module->removeFunction(im->name);
diff --git a/test/lit/passes/jspi.wast b/test/lit/passes/jspi.wast
index 052e72ad7..104dc2522 100644
--- a/test/lit/passes/jspi.wast
+++ b/test/lit/passes/jspi.wast
@@ -14,10 +14,16 @@
;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32)))
+ ;; CHECK: (type $i32_=>_none (func (param i32)))
+
+ ;; CHECK: (type $externref_i32_=>_none (func (param externref i32)))
+
;; CHECK: (import "js" "compute_delta" (func $import$compute_delta (param externref f64) (result i32)))
(import "js" "compute_delta" (func $compute_delta (param f64) (result i32)))
;; CHECK: (import "js" "import_and_export" (func $import$import_and_export (param externref i32) (result i32)))
(import "js" "import_and_export" (func $import_and_export (param i32) (result i32)))
+ ;; CHECK: (import "js" "import_void_return" (func $import$import_void_return (param externref i32)))
+ (import "js" "import_void_return" (func $import_void_return (param i32)))
;; CHECK: (global $suspender (mut externref) (ref.null extern))
;; CHECK: (export "update_state_void" (func $export$update_state_void))
@@ -110,15 +116,51 @@
;; CHECK-NEXT: )
;; CHECK: (func $compute_delta (param $0 f64) (result i32)
-;; CHECK-NEXT: (call $import$compute_delta
+;; CHECK-NEXT: (local $1 externref)
+;; CHECK-NEXT: (local $2 i32)
+;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (global.get $suspender)
-;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
+;; CHECK-NEXT: (local.set $2
+;; CHECK-NEXT: (call $import$compute_delta
+;; CHECK-NEXT: (global.get $suspender)
+;; CHECK-NEXT: (local.get $0)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (global.set $suspender
+;; CHECK-NEXT: (local.get $1)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (local.get $2)
;; CHECK-NEXT: )
;; CHECK: (func $import_and_export (param $0 i32) (result i32)
-;; CHECK-NEXT: (call $import$import_and_export
+;; CHECK-NEXT: (local $1 externref)
+;; CHECK-NEXT: (local $2 i32)
+;; CHECK-NEXT: (local.set $1
+;; CHECK-NEXT: (global.get $suspender)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (local.set $2
+;; CHECK-NEXT: (call $import$import_and_export
+;; CHECK-NEXT: (global.get $suspender)
+;; CHECK-NEXT: (local.get $0)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (global.set $suspender
+;; CHECK-NEXT: (local.get $1)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (local.get $2)
+;; CHECK-NEXT: )
+
+;; CHECK: (func $import_void_return (param $0 i32)
+;; CHECK-NEXT: (local $1 externref)
+;; CHECK-NEXT: (local.set $1
+;; CHECK-NEXT: (global.get $suspender)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (call $import$import_void_return
;; CHECK-NEXT: (global.get $suspender)
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
+;; CHECK-NEXT: (global.set $suspender
+;; CHECK-NEXT: (local.get $1)
+;; CHECK-NEXT: )
;; CHECK-NEXT: )