Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/tools/wasm-ctor-eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,13 @@ class EvallingModuleRunner : public ModuleRunnerBase<EvallingModuleRunner> {
return ModuleRunnerBase<EvallingModuleRunner>::visitGlobalGet(curr);
}

Flow visitGlobalSet(GlobalSet* curr) {
if (curr->value->type.isContinuation()) {
throw FailToEvalException("cannot serialize continuations to globals");
}
return ModuleRunnerBase<EvallingModuleRunner>::visitGlobalSet(curr);
}

Flow visitTableGet(TableGet* curr) {
// We support tableLoad, below, so that call_indirect works (it calls it
// internally), but we want to disable table.get for now.
Expand Down
73 changes: 73 additions & 0 deletions test/lit/ctor-eval/cont-noserial.wast
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,76 @@
(func $export (export "export")
)
)

;; Now the problem happens when we write a continuation to a global, which we
;; cannot do. Nothing can be optimized here.
(module
;; CHECK: (type $func (func))
;; NOKEEP: (type $func (func))
(type $func (func))
;; CHECK: (type $cont (cont $func))
;; NOKEEP: (type $cont (cont $func))
(type $cont (cont $func))

;; CHECK: (type $2 (func (result (ref null $cont))))

;; CHECK: (global $global (mut (ref null $cont)) (ref.null nocont))
;; NOKEEP: (type $2 (func (result (ref null $cont))))

;; NOKEEP: (global $global (mut (ref null $cont)) (ref.null nocont))
(global $global (mut (ref null $cont)) (ref.null $cont))

;; CHECK: (elem declare func $func)

;; CHECK: (export "read" (func $read))

;; CHECK: (export "test" (func $test))
;; NOKEEP: (elem declare func $func)

;; NOKEEP: (export "read" (func $read))

;; NOKEEP: (export "test" (func $test))
(export "test" (func $test))

;; CHECK: (func $func (type $func)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
;; NOKEEP: (func $func (type $func)
;; NOKEEP-NEXT: (nop)
;; NOKEEP-NEXT: )
(func $func
)

;; CHECK: (func $test (type $func)
;; CHECK-NEXT: (global.set $global
;; CHECK-NEXT: (cont.new $cont
;; CHECK-NEXT: (ref.func $func)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NOKEEP: (func $test (type $func)
;; NOKEEP-NEXT: (global.set $global
;; NOKEEP-NEXT: (cont.new $cont
;; NOKEEP-NEXT: (ref.func $func)
;; NOKEEP-NEXT: )
;; NOKEEP-NEXT: )
;; NOKEEP-NEXT: )
(func $test
(global.set $global
(cont.new $cont
(ref.func $func)
)
)
)

;; CHECK: (func $read (type $2) (result (ref null $cont))
;; CHECK-NEXT: (global.get $global)
;; CHECK-NEXT: )
;; NOKEEP: (func $read (type $2) (result (ref null $cont))
;; NOKEEP-NEXT: (global.get $global)
;; NOKEEP-NEXT: )
(func $read (export "read") (result (ref null $cont))
(global.get $global)
)
)
Comment on lines +416 to +425
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I guess this isn't needed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above testcases use this pattern, because without it, the global is only written to and never read, so it can be trivially optimized out. I suspect this case might not need it as it can't optimize, but I think it's better to follow the shape of the above testcases so the diff compared to them is small and clear.

(Note that even if we don't need this now, we might need it later - ctor-eval runs a few opt passes after its work, and while simplify-globals, the pass that would remove the write-only global, is not yet run, we might add it later. Similar passes are already there.)


Loading