| ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. | |
| ;; RUN: wasm-opt %s --precompute-propagate -all -S -o - | filecheck %s | |
| (module | |
| ;; CHECK: (type $0 (func (result i32))) | |
| ;; CHECK: (type $array16 (array (mut i16))) | |
| (type $array16 (array (mut i16))) | |
| (type $array16-imm (array i16)) | |
| ;; CHECK: (type $2 (func (result (ref string)))) | |
| ;; CHECK: (type $3 (func (result externref))) | |
| ;; CHECK: (type $4 (func (result (ref any)))) | |
| ;; CHECK: (export "get_codepoint-unicode" (func $get_codepoint-unicode)) | |
| ;; CHECK: (export "get_codepoint-surrogate" (func $get_codepoint-surrogate)) | |
| ;; CHECK: (export "test" (func $encode-stashed)) | |
| ;; CHECK: (export "slice" (func $slice)) | |
| ;; CHECK: (export "slice-unicode" (func $slice-unicode)) | |
| ;; CHECK: (export "slice-invalid-unicode-end" (func $slice-invalid-unicode-end)) | |
| ;; CHECK: (export "slice-invalid-unicode-begin" (func $slice-invalid-unicode-begin)) | |
| ;; CHECK: (func $eq-no (type $0) (result i32) | |
| ;; CHECK-NEXT: (i32.const 0) | |
| ;; CHECK-NEXT: ) | |
| (func $eq-no (result i32) | |
| (string.eq | |
| (string.const "ab") | |
| (string.const "cdefg") | |
| ) | |
| ) | |
| ;; CHECK: (func $eq-yes (type $0) (result i32) | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: ) | |
| (func $eq-yes (result i32) | |
| (string.eq | |
| (string.const "ab") | |
| (string.const "ab") | |
| ) | |
| ) | |
| ;; CHECK: (func $concat (type $0) (result i32) | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: ) | |
| (func $concat (result i32) | |
| (string.eq | |
| (string.concat (string.const "a") (string.const "b")) | |
| (string.const "ab") | |
| ) | |
| ) | |
| ;; CHECK: (func $concat-surrogates (type $0) (result i32) | |
| ;; CHECK-NEXT: (i32.const 1) | |
| ;; CHECK-NEXT: ) | |
| (func $concat-surrogates (result i32) | |
| (string.eq | |
| ;; Concatenating these surrogates creates '𐍈', which has a different UTF-8 encoding. | |
| (string.concat (string.const "\ED\A0\80") (string.const "\ED\BD\88")) | |
| (string.const "\F0\90\8D\88") | |
| ) | |
| ) | |
| ;; CHECK: (func $length (type $0) (result i32) | |
| ;; CHECK-NEXT: (i32.const 7) | |
| ;; CHECK-NEXT: ) | |
| (func $length (result i32) | |
| (string.measure_wtf16 | |
| (string.const "1234567") | |
| ) | |
| ) | |
| ;; CHECK: (func $length-unicode (type $0) (result i32) | |
| ;; CHECK-NEXT: (i32.const 8) | |
| ;; CHECK-NEXT: ) | |
| (func $length-unicode (result i32) | |
| (string.measure_wtf16 | |
| ;; $_£_€_𐍈 (the last character is encoded as a surrogate pair) | |
| (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") | |
| ) | |
| ) | |
| ;; CHECK: (func $get_codepoint (type $0) (result i32) | |
| ;; CHECK-NEXT: (i32.const 95) | |
| ;; CHECK-NEXT: ) | |
| (func $get_codepoint (result i32) | |
| ;; Returns 95 ('_'). | |
| (stringview_wtf16.get_codeunit | |
| ;; $_£_€_𐍈 | |
| (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") | |
| (i32.const 1) | |
| ) | |
| ) | |
| ;; CHECK: (func $get_codepoint-unicode (type $0) (result i32) | |
| ;; CHECK-NEXT: (i32.const 8364) | |
| ;; CHECK-NEXT: ) | |
| (func $get_codepoint-unicode (export "get_codepoint-unicode") (result i32) | |
| ;; Returns 8364 ('€') | |
| (stringview_wtf16.get_codeunit | |
| ;; $_£_€_𐍈 | |
| (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") | |
| (i32.const 4) | |
| ) | |
| ) | |
| ;; CHECK: (func $get_codepoint-surrogate (type $0) (result i32) | |
| ;; CHECK-NEXT: (i32.const 55296) | |
| ;; CHECK-NEXT: ) | |
| (func $get_codepoint-surrogate (export "get_codepoint-surrogate") (result i32) | |
| ;; Returns 0xd800 (the high surrogate in '𐍈') | |
| (stringview_wtf16.get_codeunit | |
| ;; $_£_€_𐍈 | |
| (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") | |
| (i32.const 6) | |
| ) | |
| ) | |
| ;; CHECK: (func $encode (type $0) (result i32) | |
| ;; CHECK-NEXT: (string.encode_wtf16_array | |
| ;; CHECK-NEXT: (string.const "$_") | |
| ;; CHECK-NEXT: (array.new_default $array16 | |
| ;; CHECK-NEXT: (i32.const 20) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (i32.const 0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $encode (result i32) | |
| ;; We could optimize away the encode operation here as the reference does not | |
| ;; escape, but we do not do escape analysis here. | |
| (string.encode_wtf16_array | |
| (string.const "$_") | |
| (array.new_default $array16 | |
| (i32.const 20) | |
| ) | |
| (i32.const 0) | |
| ) | |
| ) | |
| ;; CHECK: (func $encode-unicode (type $0) (result i32) | |
| ;; CHECK-NEXT: (string.encode_wtf16_array | |
| ;; CHECK-NEXT: (string.const "$_\c2\a3_\e2\82\ac_\f0\90\8d\88") | |
| ;; CHECK-NEXT: (array.new_default $array16 | |
| ;; CHECK-NEXT: (i32.const 20) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (i32.const 0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $encode-unicode (result i32) | |
| (string.encode_wtf16_array | |
| ;; $_£_€_𐍈 | |
| (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") | |
| (array.new_default $array16 | |
| (i32.const 20) | |
| ) | |
| (i32.const 0) | |
| ) | |
| ) | |
| ;; CHECK: (func $encode-stashed (type $4) (result (ref any)) | |
| ;; CHECK-NEXT: (local $1 (ref $array16)) | |
| ;; CHECK-NEXT: (local.set $1 | |
| ;; CHECK-NEXT: (array.new_default $array16 | |
| ;; CHECK-NEXT: (i32.const 10) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (drop | |
| ;; CHECK-NEXT: (string.encode_wtf16_array | |
| ;; CHECK-NEXT: (string.const "0123456789") | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; CHECK-NEXT: (i32.const 0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (local.get $1) | |
| ;; CHECK-NEXT: ) | |
| (func $encode-stashed (export "test") (result (ref any)) | |
| (local $1 (ref $array16)) | |
| ;; Create a zero-filled array. | |
| (local.set $1 | |
| (array.new_default $array16 | |
| (i32.const 10) | |
| ) | |
| ) | |
| ;; Fill it with some string data. | |
| (drop | |
| (string.encode_wtf16_array | |
| (string.const "0123456789") | |
| (local.get $1) | |
| (i32.const 0) | |
| ) | |
| ) | |
| ;; Return the modified array. We must not have removed the encode operation | |
| ;; above us (it has the side effect of modifying the array, just like an | |
| ;; array.copy does). | |
| (local.get $1) | |
| ) | |
| ;; CHECK: (func $slice (type $2) (result (ref string)) | |
| ;; CHECK-NEXT: (string.const "def") | |
| ;; CHECK-NEXT: ) | |
| (func $slice (export "slice") (result (ref string)) | |
| ;; Slicing [3:6] here should definitely output "def". | |
| (stringview_wtf16.slice | |
| (string.const "abcdefgh") | |
| (i32.const 3) | |
| (i32.const 6) | |
| ) | |
| ) | |
| ;; CHECK: (func $slice-unicode (type $2) (result (ref string)) | |
| ;; CHECK-NEXT: (string.const "d\c2\a3f") | |
| ;; CHECK-NEXT: ) | |
| (func $slice-unicode (export "slice-unicode") (result (ref string)) | |
| (stringview_wtf16.slice | |
| ;; abcd£fgh | |
| (string.const "abcd\C2\A3fgh") | |
| (i32.const 3) | |
| (i32.const 6) | |
| ) | |
| ) | |
| ;; CHECK: (func $slice-invalid-unicode-end (type $2) (result (ref string)) | |
| ;; CHECK-NEXT: (stringview_wtf16.slice | |
| ;; CHECK-NEXT: (string.const "a\f0\90\8d\86b") | |
| ;; CHECK-NEXT: (i32.const 0) | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $slice-invalid-unicode-end (export "slice-invalid-unicode-end") (result (ref string)) | |
| (stringview_wtf16.slice | |
| ;; a𐍆b | |
| (string.const "a\f0\90\8d\86b") | |
| (i32.const 0) | |
| (i32.const 2) | |
| ) | |
| ) | |
| ;; CHECK: (func $slice-invalid-unicode-begin (type $2) (result (ref string)) | |
| ;; CHECK-NEXT: (stringview_wtf16.slice | |
| ;; CHECK-NEXT: (string.const "a\f0\90\8d\86b") | |
| ;; CHECK-NEXT: (i32.const 2) | |
| ;; CHECK-NEXT: (i32.const 4) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $slice-invalid-unicode-begin (export "slice-invalid-unicode-begin") (result (ref string)) | |
| (stringview_wtf16.slice | |
| ;; a𐍆b | |
| (string.const "a\f0\90\8d\86b") | |
| (i32.const 2) | |
| (i32.const 4) | |
| ) | |
| ) | |
| ;; CHECK: (func $string.new-mutable (type $3) (result externref) | |
| ;; CHECK-NEXT: (string.const "ABCD") | |
| ;; CHECK-NEXT: ) | |
| (func $string.new-mutable (result externref) | |
| ;; We can precompute this only because the allocation is the immediate child. | |
| (string.new_wtf16_array | |
| (array.new_fixed $array16 4 | |
| (i32.const 65) | |
| (i32.const 66) | |
| (i32.const 67) | |
| (i32.const 68) | |
| ) | |
| (i32.const 0) | |
| (i32.const 4) | |
| ) | |
| ) | |
| ;; CHECK: (func $string.new-mutable-indirect (type $3) (result externref) | |
| ;; CHECK-NEXT: (string.new_wtf16_array | |
| ;; CHECK-NEXT: (block (result (ref (exact $array16))) | |
| ;; CHECK-NEXT: (array.new_fixed $array16 4 | |
| ;; CHECK-NEXT: (i32.const 65) | |
| ;; CHECK-NEXT: (i32.const 66) | |
| ;; CHECK-NEXT: (i32.const 67) | |
| ;; CHECK-NEXT: (i32.const 68) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (i32.const 0) | |
| ;; CHECK-NEXT: (i32.const 4) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| (func $string.new-mutable-indirect (result externref) | |
| ;; Now the allocation is not the immediate child, so we do not precompute. | |
| ;; TODO: be smarter and optimize this. | |
| (string.new_wtf16_array | |
| (block (result (ref $array16)) | |
| (array.new_fixed $array16 4 | |
| (i32.const 65) | |
| (i32.const 66) | |
| (i32.const 67) | |
| (i32.const 68) | |
| ) | |
| ) | |
| (i32.const 0) | |
| (i32.const 4) | |
| ) | |
| ) | |
| ) |