diff options
-rw-r--r-- | src/passes/JSPI.cpp | 28 | ||||
-rw-r--r-- | test/lit/passes/jspi.wast | 48 |
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: ) |