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
5 changes: 5 additions & 0 deletions src/ir/possible-contents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2454,6 +2454,11 @@ Flower::Flower(Module& wasm, const PassOptions& options)
}
}

// configureAll functions are called from outside the module, as if exported.
for (auto func : Intrinsics(wasm).getConfigureAllFunctions()) {
calledFromOutside.insert(func);
}

// Apply changes to all functions called from outside.
for (auto funcName : calledFromOutside) {
auto* func = wasm.getFunction(funcName);
Expand Down
103 changes: 103 additions & 0 deletions test/lit/passes/gufa-configureAll.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.

;; RUN: foreach %s %t wasm-opt --gufa --closed-world -all -S -o - | filecheck %s

;; Test that configureAll is respected: referred functions are assumed to be
;; called from outside the module, depsite closed world.

(module
;; CHECK: (type $externs (array (mut externref)))
(type $externs (array (mut externref)))

;; CHECK: (type $funcs (array (mut funcref)))
(type $funcs (array (mut funcref)))

;; CHECK: (type $bytes (array (mut i8)))
(type $bytes (array (mut i8)))

;; CHECK: (type $3 (func (param i32) (result i32)))

;; CHECK: (type $configureAll (func (param (ref null $externs) (ref null $funcs) (ref null $bytes) externref)))
(type $configureAll (func (param (ref null $externs)) (param (ref null $funcs)) (param (ref null $bytes)) (param externref)))

;; CHECK: (type $5 (func))

;; CHECK: (import "wasm:js-prototypes" "configureAll" (func $configureAll (type $configureAll) (param (ref null $externs) (ref null $funcs) (ref null $bytes) externref)))
(import "wasm:js-prototypes" "configureAll" (func $configureAll (type $configureAll)))

;; CHECK: (data $bytes "12345678")
(data $bytes "12345678")

;; CHECK: (elem $externs externref (item (ref.null noextern)))
(elem $externs externref
(ref.null extern)
)

;; CHECK: (elem $funcs func $configured)
(elem $funcs funcref
(ref.func $configured)
)

;; CHECK: (elem $other func $unconfigured)
(elem $other funcref
(ref.func $unconfigured)
)

;; CHECK: (start $start)
(start $start)

;; CHECK: (func $start (type $5)
;; CHECK-NEXT: (call $configureAll
;; CHECK-NEXT: (array.new_elem $externs $externs
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (array.new_elem $funcs $funcs
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (array.new_data $bytes $bytes
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i32.const 8)
;; CHECK-NEXT: )
;; CHECK-NEXT: (ref.null noextern)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $start
(call $configureAll
(array.new_elem $externs $externs
(i32.const 0) (i32.const 1))
(array.new_elem $funcs $funcs
(i32.const 0) (i32.const 1))
(array.new_data $bytes $bytes
(i32.const 0) (i32.const 8))
(ref.null extern)
)
)

;; CHECK: (func $configured (type $3) (param $x i32) (result i32)
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $configured (param $x i32) (result i32)
;; The call from outside the module, through configureAll, is the only call
;; we have - without it, this would be unreachable code, and optimized away.
(i32.eqz
(local.get $x)
)
)

;; CHECK: (func $unconfigured (type $3) (param $x i32) (result i32)
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $unconfigured (param $x i32) (result i32)
;; As above, but *not* in configureAll (though it is in a table, so it is
;; not entirely removed) - so we do optimize.
(i32.eqz
(local.get $x)
)
)
)
Loading