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
8 changes: 5 additions & 3 deletions src/passes/GlobalTypeOptimization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ struct GlobalTypeOptimization : public Pass {
// That is, we can only append fields: we cannot reorder or remove any
// field that is in the super.
Index numSuperFields = 0;
bool superHasKeptFields = false;
if (super) {
// We have visited the super before. Get the information about its
// fields.
Expand Down Expand Up @@ -408,6 +409,7 @@ struct GlobalTypeOptimization : public Pass {
// The super kept this field, so we must keep it as well. This can
// happen when we need the field in both, but also in the corner
// case where we don't need the field but the super is public.
superHasKeptFields = true;

// We need to keep it at the same index so we remain compatible.
indexesAfterRemoval[i] = superIndex;
Expand All @@ -433,10 +435,10 @@ struct GlobalTypeOptimization : public Pass {
}
}

// If the type has no supertype (or its supertype has no fields), check
// if its first field becomes prototype-exposing. If so, add a
// If the type has no supertype (or its supertype has no kept fields),
// check if its first field becomes prototype-exposing. If so, add a
// placeholder at index 0 and shift all computed indices.
if (isExposedNoProto && (!super || super->getStruct().fields.empty())) {
if (isExposedNoProto && !superHasKeptFields) {
// Find the field that will become field 0.
Index i = 0;
for (; i < fields.size(); ++i) {
Expand Down
61 changes: 61 additions & 0 deletions test/lit/passes/gto-jsinterop.wast
Original file line number Diff line number Diff line change
Expand Up @@ -1753,3 +1753,64 @@
)
)
)

(module
;; All fields of $super-desc are unread and removed by GTO, leaving
;; $super-desc empty after optimization. In $sub-desc, the unread supertype
;; field is also removed and the following externref field shifts to index 0,
;; so $sub-desc must get an i8 placeholder at index 0 to avoid exposing a
;; prototype.
(rec
;; CHECK: (rec
;; CHECK-NEXT: (type $super (sub (descriptor $super-desc) (struct)))
(type $super (sub (descriptor $super-desc) (struct)))
;; CHECK: (type $super-desc (sub (describes $super) (struct)))
(type $super-desc (sub (describes $super) (struct (field f64))))
;; CHECK: (type $sub (sub final $super (descriptor $sub-desc) (struct)))
(type $sub (sub final $super (descriptor $sub-desc) (struct)))
;; CHECK: (type $sub-desc (sub final $super-desc (describes $sub) (struct (field i8) (field externref))))
(type $sub-desc (sub final $super-desc (describes $sub) (struct (field f64) (field externref))))
)

;; CHECK: (type $4 (func (param (ref $sub-desc)) (result externref)))

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

;; CHECK: (import "env" "ext" (global $ext externref))
(import "env" "ext" (global $ext externref))
;; CHECK: (export "export" (func $test))
(export "export" (func $test))

;; CHECK: (func $test (type $5) (result externref)
;; CHECK-NEXT: (extern.convert_any
;; CHECK-NEXT: (struct.new_default_desc $sub
;; CHECK-NEXT: (struct.new $sub-desc
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (global.get $ext)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $test (result externref)
;; Convert to extern to expose the value to JS.
(extern.convert_any
(struct.new_default_desc $sub
(struct.new $sub-desc
(f64.const 0)
(global.get $ext)
)
)
)
)

;; CHECK: (func $use (type $4) (param $d (ref $sub-desc)) (result externref)
;; CHECK-NEXT: (struct.get $sub-desc 1
;; CHECK-NEXT: (local.get $d)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $use (param $d (ref $sub-desc)) (result externref)
(struct.get $sub-desc 1
(local.get $d)
)
)
)
Loading