blob: 1a4090a16bbed727309158f66d1ce6b1e6016962 [file] [edit]
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; RUN: foreach %s %t wasm-opt -all --closed-world --preserve-type-order \
;; RUN: --merge-j2cl-itables -all -S -o - | filecheck %s
;; Custom descriptors - Shared itable instance.
(module
(rec
;; CHECK: (rec
;; CHECK-NEXT: (type $Object (sub (descriptor $Object.vtable) (struct (field $itable (ref $Object.itable)))))
(type $Object (sub (descriptor $Object.vtable) (struct
(field $itable (ref $Object.itable)))))
;; CHECK: (type $SubObject (sub $Object (descriptor $SubObject.vtable) (struct (field $itable (ref $Object.itable)))))
(type $SubObject (sub $Object (descriptor $SubObject.vtable) (struct
(field $itable (ref $Object.itable)))))
;; CHECK: (type $function (func))
(type $function (func))
;; The $Object.itable field (a structref) will be added as a field after
;; the first field of this vtable.
;; CHECK: (type $Object.vtable (sub (describes $Object) (struct (field externref) (field structref))))
(type $Object.vtable (sub (describes $Object) (struct
(field externref))))
;; The $Object.itable field (a structref) will be added as a field after
;; the first field of this vtable.
;; CHECK: (type $SubObject.vtable (sub $Object.vtable (describes $SubObject) (struct (field externref) (field structref) (field (ref $function)))))
(type $SubObject.vtable (sub $Object.vtable (describes $SubObject) (struct
(field externref)
(field (ref $function)))))
;; CHECK: (type $Object.itable (struct (field structref)))
(type $Object.itable (struct
(field (ref null struct))))
)
;; CHECK: (type $6 (func))
;; CHECK: (global $Object.itable (ref $Object.itable) (struct.new_default $Object.itable))
(global $Object.itable (ref $Object.itable)
(struct.new_default $Object.itable))
;; CHECK: (global $SubObject.itable (ref $Object.itable) (global.get $Object.itable))
(global $SubObject.itable (ref $Object.itable)
(global.get $Object.itable)) ;; uses shared empty itable instance.
;; The initialization for the itable field (null struct) will be added to this
;; vtable instance.
;; CHECK: (global $SubObject.vtable (ref (exact $SubObject.vtable)) (struct.new $SubObject.vtable
;; CHECK-NEXT: (ref.null noextern)
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: (ref.func $SubObject.f)
;; CHECK-NEXT: ))
(global $SubObject.vtable (ref (exact $SubObject.vtable))
(struct.new $SubObject.vtable (ref.null extern) (ref.func $SubObject.f)))
;; The initialization for the itable field (null struct) will be added to this
;; vtable instance.
;; CHECK: (global $Object.vtable (ref (exact $Object.vtable)) (struct.new $Object.vtable
;; CHECK-NEXT: (ref.null noextern)
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: ))
(global $Object.vtable (ref (exact $Object.vtable))
(struct.new $Object.vtable (ref.null extern)))
;; CHECK: (func $SubObject.f (type $function)
;; CHECK-NEXT: )
(func $SubObject.f
(type $function)
)
;; CHECK: (func $usages (type $6)
;; CHECK-NEXT: (local $o (ref null $SubObject))
;; CHECK-NEXT: (local.set $o
;; CHECK-NEXT: (struct.new_desc $SubObject
;; CHECK-NEXT: (global.get $SubObject.itable)
;; CHECK-NEXT: (global.get $SubObject.vtable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (struct.get $SubObject.vtable 0
;; CHECK-NEXT: (ref.get_desc $SubObject
;; CHECK-NEXT: (local.get $o)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (struct.get $SubObject.vtable 2
;; CHECK-NEXT: (ref.get_desc $SubObject
;; CHECK-NEXT: (local.get $o)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (struct.get $SubObject.vtable 1
;; CHECK-NEXT: (ref.get_desc $SubObject
;; CHECK-NEXT: (local.get $o)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $usages
(local $o (ref null $SubObject))
(local.set $o
(struct.new_desc $SubObject
(global.get $SubObject.itable)
(global.get $SubObject.vtable)))
(drop
;; The access to vtable field 0 is NOT offset and will remain an
;; access to field 0.
(struct.get $SubObject.vtable 0
(ref.get_desc $SubObject
(local.get $o))))
(drop
;; The access to vtable field 1 is offset by the itable size and
;; will be an access to field 2.
(struct.get $SubObject.vtable 1
(ref.get_desc $SubObject
(local.get $o))))
(drop
;; The access to itable field 0 will be rerouted to be an access to
;; vtable field 1.
(struct.get $Object.itable 0
(struct.get $SubObject $itable
(local.get $o))))
)
)
;; Custom descriptors - Each type has its own itable.
(module
(rec
;; CHECK: (rec
;; CHECK-NEXT: (type $Object (sub (descriptor $Object.vtable) (struct (field $itable (ref $Object.itable)))))
(type $Object (sub (descriptor $Object.vtable) (struct
(field $itable (ref $Object.itable)))))
;; CHECK: (type $SubObject (sub $Object (descriptor $SubObject.vtable) (struct (field $itable (ref $SubObject.itable)))))
(type $SubObject (sub $Object (descriptor $SubObject.vtable) (struct
(field $itable (ref $SubObject.itable)))))
;; CHECK: (type $function (func))
(type $function (func))
;; CHECK: (type $Object.itable (sub (struct (field structref))))
(type $Object.itable (sub (struct
(field (ref null struct)))))
;; CHECK: (type $SubObject.itable (sub $Object.itable (struct (field structref))))
(type $SubObject.itable (sub $Object.itable
(struct (field (ref null struct)))))
;; The $Object.itable field (a structref) will be added as a field after
;; the first field of this vtable.
;; CHECK: (type $Object.vtable (sub (describes $Object) (struct (field externref) (field structref))))
(type $Object.vtable (sub (describes $Object) (struct
(field externref))))
;; The $SubObject.itable field (a structref) will be added as a field after
;; the first field of this vtable.
;; CHECK: (type $SubObject.vtable (sub $Object.vtable (describes $SubObject) (struct (field externref) (field structref) (field (ref $function)))))
(type $SubObject.vtable (sub $Object.vtable (describes $SubObject) (struct
(field externref)
(field (ref $function)))))
)
;; The initialization for the itable field (null struct) will be added to this
;; vtable instance.
;; CHECK: (type $7 (func))
;; CHECK: (global $SubObject.vtable (ref (exact $SubObject.vtable)) (struct.new $SubObject.vtable
;; CHECK-NEXT: (ref.null noextern)
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: (ref.func $SubObject.f)
;; CHECK-NEXT: ))
(global $SubObject.vtable (ref (exact $SubObject.vtable))
(struct.new $SubObject.vtable (ref.null extern) (ref.func $SubObject.f)))
;; CHECK: (global $SubObject.itable (ref $SubObject.itable) (struct.new_default $SubObject.itable))
(global $SubObject.itable (ref $SubObject.itable)
(struct.new_default $SubObject.itable))
;; The initialization for the itable field (null struct) will be added to this
;; vtable instance.
;; CHECK: (global $Object.vtable (ref (exact $Object.vtable)) (struct.new $Object.vtable
;; CHECK-NEXT: (ref.null noextern)
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: ))
(global $Object.vtable (ref (exact $Object.vtable))
(struct.new $Object.vtable (ref.null extern)))
;; CHECK: (global $Object.itable (ref $Object.itable) (struct.new_default $Object.itable))
(global $Object.itable (ref $Object.itable)
(struct.new_default $Object.itable))
;; CHECK: (func $SubObject.f (type $function)
;; CHECK-NEXT: )
(func $SubObject.f
(type $function)
)
;; CHECK: (func $usages (type $7)
;; CHECK-NEXT: (local $o (ref null $SubObject))
;; CHECK-NEXT: (local.set $o
;; CHECK-NEXT: (struct.new_desc $SubObject
;; CHECK-NEXT: (global.get $SubObject.itable)
;; CHECK-NEXT: (global.get $SubObject.vtable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (struct.get $SubObject.vtable 0
;; CHECK-NEXT: (ref.get_desc $SubObject
;; CHECK-NEXT: (local.get $o)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (struct.get $SubObject.vtable 2
;; CHECK-NEXT: (ref.get_desc $SubObject
;; CHECK-NEXT: (local.get $o)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (struct.get $SubObject.vtable 1
;; CHECK-NEXT: (ref.get_desc $SubObject
;; CHECK-NEXT: (local.get $o)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $usages
(local $o (ref null $SubObject))
(local.set $o
(struct.new_desc $SubObject
(global.get $SubObject.itable)
(global.get $SubObject.vtable)))
(drop
;; The access to vtable field 0 is NOT offset and will remain an
;; access to field 0.
(struct.get $SubObject.vtable 0
(ref.get_desc $SubObject
(local.get $o))))
(drop
;; The access to vtable field 1 is offset by the itable size and
;; will be an access to field 2.
(struct.get $SubObject.vtable 1
(ref.get_desc $SubObject
(local.get $o))))
(drop
;; The access to itable field 0 will be rerouted to be an access to
;; vtable field 1.
(struct.get $Object.itable 0
(struct.get $SubObject $itable
(local.get $o))))
)
)