Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider functions in elems of public tables to be public #6660

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
23 changes: 17 additions & 6 deletions src/ir/module-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,10 +574,9 @@ InsertOrderedSet<HeapType> getPublicTypeSet(Module& wasm) {

// TODO: Consider Tags as well, but they should store HeapTypes instead of
// Signatures first.
ModuleUtils::iterImportedTables(wasm, [&](Table* table) {
assert(table->type.isRef());
notePublic(table->type.getHeapType());
});
std::unordered_set<Table*> publicTables;
ModuleUtils::iterImportedTables(
wasm, [&](Table* table) { publicTables.insert(table); });
ModuleUtils::iterImportedGlobals(wasm, [&](Global* global) {
if (global->type.isRef()) {
notePublic(global->type.getHeapType());
Expand All @@ -599,8 +598,7 @@ InsertOrderedSet<HeapType> getPublicTypeSet(Module& wasm) {
}
case ExternalKind::Table: {
auto* table = wasm.getTable(ex->value);
assert(table->type.isRef());
notePublic(table->type.getHeapType());
publicTables.insert(table);
continue;
}
case ExternalKind::Memory:
Expand All @@ -622,6 +620,19 @@ InsertOrderedSet<HeapType> getPublicTypeSet(Module& wasm) {
WASM_UNREACHABLE("unexpected export kind");
}

for (auto* table : publicTables) {
assert(table->type.isRef());
notePublic(table->type.getHeapType());

// All functions added to the table are public as well.
// TODO: we should also scan for table.set
iterTableSegments(wasm, table->name, [&](ElementSegment* segment) {
for (auto* data : segment->data) {
notePublic(data->type.getHeapType());
}
});
}

// Ignorable public types are public.
for (auto type : getIgnorablePublicTypes()) {
notePublic(type);
Expand Down
52 changes: 52 additions & 0 deletions test/lit/passes/unsubtyping-open.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; RUN: foreach %s %t wasm-opt --unsubtyping -all -S -o - | filecheck %s

;; Test unsubtyping *without* closed world. No public types should be modified.

;; One of the function types, $some, must both remain in its own singleton rec
;; groups, as it is public because it is on an elem of an imported table. The
;; other function type $none, can move into the new rec group (it is private).
;;
;; There are also struct types which unsubtyping can optimize (so that it has
;; work to do, and does not exit early, which would pass this test incorrectly).
;; Specifically $sub1 and $sub2 should stop being subtypes of $super.
(module
;; CHECK: (rec
;; CHECK-NEXT: (type $super (sub (struct )))
(type $super (sub (struct)))

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

;; CHECK: (type $sub2 (sub (struct (field f32))))
(type $sub2 (sub $super (struct f32)))

;; CHECK: (type $sub1 (sub (struct (field i32))))
(type $sub1 (sub $super (struct i32)))

;; CHECK: (type $some (func (param f32 i32 f32)))
(type $some (func (param f32 i32 f32)))

;; CHECK: (import "a" "b" (table $table 1 funcref))
(import "a" "b" (table $table 1 funcref))

;; CHECK: (global $sub1 (ref $sub1) (struct.new_default $sub1))
(global $sub1 (ref $sub1) (struct.new_default $sub1))
;; CHECK: (global $sub2 (ref $sub2) (struct.new_default $sub2))
(global $sub2 (ref $sub2) (struct.new_default $sub2))

;; CHECK: (elem $elem (i32.const 0) $some)
(elem $elem (i32.const 0) $some)

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

;; CHECK: (func $some (type $some) (param $0 f32) (param $1 i32) (param $2 f32)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $some (type $some) (param $0 f32) (param $1 i32) (param $2 f32)
)
)
Loading