diff --git a/README.md b/README.md index b3809263edc..3400c755c99 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,17 @@ There are a few differences between Binaryen IR and the WebAssembly language: rare cases (we avoid this overhead in the common case where the `br_if` value is unused). + * Strings + + * When the string builtins feature is enabled (`--enable-string-builtins`), + string operations are optimized. First, string imports are lifted into + stringref operations, before any default optimization passes. Those + stringref operations can then be optimized (e.g., a concat of constants + turns into a concatenated constant). When we are about to finish running + default optimizations, we lower stringref back into string builtins. (Note: + reference types and GC must also be enabled, as imported string operations + depend on GC arrays.) + As a result, you might notice that round-trip conversions (wasm => Binaryen IR => wasm) change code a little in some corner cases. diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py index 8f832187f5c..e87b9d0b58b 100755 --- a/scripts/fuzz_opt.py +++ b/scripts/fuzz_opt.py @@ -51,8 +51,16 @@ # parameters # feature options that are always passed to the tools. -# XXX fp16 is not yet stable, remove from here when it is -CONSTANT_FEATURE_OPTS = ['--all-features', '--disable-fp16'] +CONSTANT_FEATURE_OPTS = [ + '--all-features', + # TODO fp16 is not yet stable, remove from here when it is + '--disable-fp16', + # TODO if we enable string-builtins then if the input module has strings, + # the output after lowering will have string imports, and the + # interpreter does not yet support executing those (we'd need to handle + # all the imported functions, magic constants, and the section) + '--disable-string-builtins', +] INPUT_SIZE_MIN = 1024 INPUT_SIZE_MEAN = 40 * 1024 diff --git a/scripts/test/fuzzing.py b/scripts/test/fuzzing.py index b074106b271..8f84ae3fc00 100644 --- a/scripts/test/fuzzing.py +++ b/scripts/test/fuzzing.py @@ -19,10 +19,13 @@ unfuzzable = [ # Float16 is still experimental. 'f16.wast', - # TODO: fuzzer and interpreter support for strings + # TODO: fuzzer and interpreter support for strings, including limitations + # like the fuzzer not handling (ref extern) imports (there is no way + # to create a replacement value) 'strings.wast', 'simplify-locals-strings.wast', 'string-lowering-instructions.wast', + 'string-builtins.wast', # TODO: fuzzer and interpreter support for extern conversions 'extern-conversions.wast', # ignore DWARF because it is incompatible with multivalue atm diff --git a/src/pass.h b/src/pass.h index 0ebd7e6d6bd..5b255e6a6ad 100644 --- a/src/pass.h +++ b/src/pass.h @@ -324,18 +324,30 @@ struct PassRunner { // warning. void addIfNoDWARFIssues(std::string passName); - // Adds the default set of optimization passes; this is - // what -O does. - void addDefaultOptimizationPasses(); + // By default, we do not know if we are running first in the ordering of + // optimization passes, or last - we could be anywhere. + struct Ordering { + bool first; + bool last; + }; + static constexpr Ordering UnknownOrdering = {false, false}; + + // Adds the default set of optimization passes; this is what -O does. + // + // The ordering indicates our position relative to other default + // optimizations, that is, if ordering.first then we are first. + void addDefaultOptimizationPasses(Ordering ordering = UnknownOrdering); // Adds the default optimization passes that work on // individual functions. - void addDefaultFunctionOptimizationPasses(); + void + addDefaultFunctionOptimizationPasses(Ordering ordering = UnknownOrdering); // Adds the default optimization passes that work on // entire modules as a whole, and make sense to // run before function passes. - void addDefaultGlobalOptimizationPrePasses(); + void + addDefaultGlobalOptimizationPrePasses(Ordering ordering = UnknownOrdering); // Adds the default optimization passes that work on // entire modules as a whole, and make sense to @@ -343,7 +355,8 @@ struct PassRunner { // This is run at the very end of the optimization // process - you can assume no other opts will be run // afterwards. - void addDefaultGlobalOptimizationPostPasses(); + void + addDefaultGlobalOptimizationPostPasses(Ordering ordering = UnknownOrdering); // Run the passes on the module void run(); diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 2042bc71d3a..4a8b87f6484 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -605,13 +605,13 @@ void PassRunner::addIfNoDWARFIssues(std::string passName) { } } -void PassRunner::addDefaultOptimizationPasses() { - addDefaultGlobalOptimizationPrePasses(); - addDefaultFunctionOptimizationPasses(); - addDefaultGlobalOptimizationPostPasses(); +void PassRunner::addDefaultOptimizationPasses(Ordering ordering) { + addDefaultGlobalOptimizationPrePasses(ordering); + addDefaultFunctionOptimizationPasses(ordering); + addDefaultGlobalOptimizationPostPasses(ordering); } -void PassRunner::addDefaultFunctionOptimizationPasses() { +void PassRunner::addDefaultFunctionOptimizationPasses(Ordering ordering) { // All the additions here are optional if DWARF must be preserved. That is, // when DWARF is relevant we run fewer optimizations. // FIXME: support DWARF in all of them. @@ -723,7 +723,17 @@ void PassRunner::addDefaultFunctionOptimizationPasses() { addIfNoDWARFIssues("vacuum"); // just to be safe } -void PassRunner::addDefaultGlobalOptimizationPrePasses() { +void PassRunner::addDefaultGlobalOptimizationPrePasses(Ordering ordering) { + // If we are optimizing string builtins then we lift at the very start of the + // optimization pipeline, not just at the beginning here, but only when we are + // ordered before other bundles of passes. + // + // We check for GC for symmetry with the lowering pass, see comment in + // addDefaultGlobalOptimizationPostPasses() below. + if (wasm->features.hasStringBuiltins() && wasm->features.hasGC() && + options.optimizeLevel >= 2 && ordering.first) { + addIfNoDWARFIssues("string-lifting"); + } // Removing duplicate functions is fast and saves work later. addIfNoDWARFIssues("duplicate-function-elimination"); // Do a global cleanup before anything heavy, as it is fairly fast and can @@ -772,7 +782,7 @@ void PassRunner::add(std::string passName, std::optional passArg) { doAdd(std::move(pass)); } -void PassRunner::addDefaultGlobalOptimizationPostPasses() { +void PassRunner::addDefaultGlobalOptimizationPostPasses(Ordering ordering) { if (options.optimizeLevel >= 2 || options.shrinkLevel >= 1) { addIfNoDWARFIssues("dae-optimizing"); } @@ -794,6 +804,20 @@ void PassRunner::addDefaultGlobalOptimizationPostPasses() { } else { addIfNoDWARFIssues("simplify-globals"); } + + // Lower away strings at the very very end. We do this before + // remove-unused-module-elements so we don't add unused imports, and also + // before reorder-globals, which will sort the new globals. + // + // Note we also test for GC here, as the pass adds imports that use GC arrays + // (and externref). Those imports may be unused, but they exist until + // remove-unused-module-elements cleans them up, which would cause an error in + // between. + if (wasm->features.hasStringBuiltins() && wasm->features.hasGC() && + options.optimizeLevel >= 2 && ordering.last) { + addIfNoDWARFIssues("string-lowering-magic-imports"); + } + addIfNoDWARFIssues("remove-unused-module-elements"); if (options.optimizeLevel >= 2 && wasm->features.hasStrings()) { // Gather strings to globals right before reorder-globals, which will then diff --git a/src/tools/optimization-options.h b/src/tools/optimization-options.h index 333380d0490..03ccc0fd53e 100644 --- a/src/tools/optimization-options.h +++ b/src/tools/optimization-options.h @@ -398,7 +398,19 @@ struct OptimizationOptions : public ToolOptions { passRunner.clear(); }; - for (auto& pass : passes) { + // Find the first and last default opt passes, so we can tell them they are + // first/last. + Index firstDefault = passes.size(); + Index lastDefault = passes.size(); + for (Index i = 0; i < passes.size(); i++) { + if (passes[i].name == DEFAULT_OPT_PASSES) { + firstDefault = std::min(firstDefault, i); + lastDefault = i; + } + } + + for (Index i = 0; i < passes.size(); i++) { + auto& pass = passes[i]; if (pass.name == DEFAULT_OPT_PASSES) { // This is something like -O3 or -Oz. We must run this now, in order to // set the proper opt and shrink levels. To do that, first reset the @@ -416,8 +428,13 @@ struct OptimizationOptions : public ToolOptions { passRunner.options.optimizeLevel = *pass.optimizeLevel; passRunner.options.shrinkLevel = *pass.shrinkLevel; + // Note the ordering of these default passes. + PassRunner::Ordering ordering; + ordering.first = (i == firstDefault); + ordering.last = (i == lastDefault); + // Run our optimizations now with the custom levels. - passRunner.addDefaultOptimizationPasses(); + passRunner.addDefaultOptimizationPasses(ordering); flush(); // Restore the default optimize/shrinkLevels. diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 3c42b6b1f13..eec2dd30a50 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -108,6 +108,8 @@ struct ToolOptions : public Options { .addFeature(FeatureSet::FP16, "float 16 operations") .addFeature(FeatureSet::CustomDescriptors, "custom descriptors (RTTs) and exact references") + .addFeature(FeatureSet::StringBuiltins, + "string builtins (imported JS strings)") .add("--enable-typed-function-references", "", "Deprecated compatibility flag", diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 5ee7452060a..c21590bd278 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -454,6 +454,7 @@ extern const char* FP16Feature; extern const char* BulkMemoryOptFeature; extern const char* CallIndirectOverlongFeature; extern const char* CustomDescriptorsFeature; +extern const char* StringBuiltinsFeature; enum Subsection { NameModule = 0, diff --git a/src/wasm-features.h b/src/wasm-features.h index a7c3ce0c4f5..f928f78445e 100644 --- a/src/wasm-features.h +++ b/src/wasm-features.h @@ -55,11 +55,12 @@ struct FeatureSet { // it does nothing. Binaryen always accepts LEB call-indirect encodings. CallIndirectOverlong = 1 << 20, CustomDescriptors = 1 << 21, + StringBuiltins = 1 << 22, MVP = None, // Keep in sync with llvm default features: // https://github.com/llvm/llvm-project/blob/c7576cb89d6c95f03968076e902d3adfd1996577/clang/lib/Basic/Targets/WebAssembly.cpp#L150-L153 Default = SignExt | MutableGlobals, - All = (1 << 22) - 1, + All = (1 << 23) - 1, }; static std::string toString(Feature f) { @@ -108,6 +109,8 @@ struct FeatureSet { return "call-indirect-overlong"; case CustomDescriptors: return "custom-descriptors"; + case StringBuiltins: + return "string-builtins"; case MVP: case Default: case All: @@ -168,6 +171,7 @@ struct FeatureSet { bool hasCustomDescriptors() const { return (features & CustomDescriptors) != 0; } + bool hasStringBuiltins() const { return (features & StringBuiltins) != 0; } bool hasAll() const { return (features & All) != 0; } void set(FeatureSet f, bool v = true) { @@ -194,6 +198,7 @@ struct FeatureSet { void setFP16(bool v = true) { set(FP16, v); } void setBulkMemoryOpt(bool v = true) { set(BulkMemoryOpt, v); } void setCustomDescriptors(bool v = true) { set(CustomDescriptors, v); } + void setStringBuiltins(bool v = true) { set(StringBuiltins, v); } void setMVP() { features = MVP; } void setAll() { features = All; } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 4421a4f471c..228b480cf8e 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1395,6 +1395,8 @@ void WasmBinaryWriter::writeFeaturesSection() { return BinaryConsts::CustomSections::CallIndirectOverlongFeature; case FeatureSet::CustomDescriptors: return BinaryConsts::CustomSections::CustomDescriptorsFeature; + case FeatureSet::StringBuiltins: + return BinaryConsts::CustomSections::StringBuiltinsFeature; case FeatureSet::None: case FeatureSet::Default: case FeatureSet::All: @@ -5193,6 +5195,8 @@ void WasmBinaryReader::readFeatures(size_t payloadLen) { feature = FeatureSet::FP16; } else if (name == BinaryConsts::CustomSections::CustomDescriptorsFeature) { feature = FeatureSet::CustomDescriptors; + } else if (name == BinaryConsts::CustomSections::StringBuiltinsFeature) { + feature = FeatureSet::StringBuiltins; } else { // Silently ignore unknown features (this may be and old binaryen running // on a new wasm). diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 655a3156382..6a96db33850 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -61,6 +61,7 @@ const char* FP16Feature = "fp16"; const char* BulkMemoryOptFeature = "bulk-memory-opt"; const char* CallIndirectOverlongFeature = "call-indirect-overlong"; const char* CustomDescriptorsFeature = "custom-descriptors"; +const char* StringBuiltinsFeature = "string-builtins"; } // namespace BinaryConsts::CustomSections diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index 45c7417dcda..b9fdf381739 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -33,7 +33,7 @@ Features.RelaxedSIMD: 4096 Features.ExtendedConst: 8192 Features.Strings: 16384 Features.MultiMemory: 32768 -Features.All: 4194303 +Features.All: 8388607 InvalidId: 0 BlockId: 1 IfId: 2 diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 1b798654d1a..1839597deca 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -47,7 +47,7 @@ BinaryenFeatureMemory64: 2048 BinaryenFeatureRelaxedSIMD: 4096 BinaryenFeatureExtendedConst: 8192 BinaryenFeatureStrings: 16384 -BinaryenFeatureAll: 4194303 +BinaryenFeatureAll: 8388607 (f32.neg (f32.const -33.61199951171875) ) diff --git a/test/lit/basic/extra-branch-values.wast b/test/lit/basic/extra-branch-values.wast index 6989bf62ca9..990a60a9ae6 100644 --- a/test/lit/basic/extra-branch-values.wast +++ b/test/lit/basic/extra-branch-values.wast @@ -28,10 +28,10 @@ (import "env" "use-i32-any" (func $use-i32-any (param i32 (ref any)))) ;; CHECK: (tag $e (type $7) (param i32)) - ;; OPT_O: (tag $e (type $5) (param i32)) + ;; OPT_O: (tag $e (type $9) (param i32)) (tag $e (param i32)) ;; CHECK: (tag $e2 (type $7) (param i32)) - ;; OPT_O: (tag $e2 (type $5) (param i32)) + ;; OPT_O: (tag $e2 (type $9) (param i32)) (tag $e2 (param i32)) ;; CHECK: (func $br_on_null-one (type $8) (param $0 i32) (param $1 anyref) (result i32) @@ -76,7 +76,7 @@ ;; CHECK-NEXT: (local.get $scratch_3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $br_on_null-one (type $6) (param $0 i32) (param $1 anyref) (result i32) + ;; OPT_O: (func $br_on_null-one (type $10) (param $0 i32) (param $1 anyref) (result i32) ;; OPT_O-NEXT: (block $block (result i32) ;; OPT_O-NEXT: (block $block0 ;; OPT_O-NEXT: (global.set $any @@ -168,7 +168,7 @@ ;; CHECK-NEXT: ) ;; OPT_O: (func $br_on_null-two (type $16) (param $0 i32) (param $1 i64) (param $2 anyref) (result i32 i64) ;; OPT_O-NEXT: (local $3 (tuple i32 i64)) - ;; OPT_O-NEXT: (block $block (type $11) (result i32 i64) + ;; OPT_O-NEXT: (block $block (type $8) (result i32 i64) ;; OPT_O-NEXT: (local.set $3 ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) @@ -254,8 +254,8 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $br_on_non_null-one (type $7) (param $0 i32) (param $1 anyref) (result i32 (ref any)) - ;; OPT_O-NEXT: (block $block (type $1) (result i32 (ref any)) + ;; OPT_O: (func $br_on_non_null-one (type $11) (param $0 i32) (param $1 anyref) (result i32 (ref any)) + ;; OPT_O-NEXT: (block $block (type $7) (result i32 (ref any)) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $block0 (result (ref any)) @@ -350,8 +350,8 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $br_on_non_null-two (type $8) (param $0 i32) (param $1 i64) (param $2 anyref) (result i32 i64 (ref any)) - ;; OPT_O-NEXT: (block $block (type $4) (result i32 i64 (ref any)) + ;; OPT_O: (func $br_on_non_null-two (type $12) (param $0 i32) (param $1 i64) (param $2 anyref) (result i32 i64 (ref any)) + ;; OPT_O-NEXT: (block $block (type $6) (result i32 i64 (ref any)) ;; OPT_O-NEXT: (tuple.make 3 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (local.get $1) @@ -441,8 +441,8 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $br_on_cast-one (type $3) (param $0 i32) (param $1 anyref) (result i32 eqref) - ;; OPT_O-NEXT: (block $block (type $0) (result i32 eqref) + ;; OPT_O: (func $br_on_cast-one (type $0) (param $0 i32) (param $1 anyref) (result i32 eqref) + ;; OPT_O-NEXT: (block $block (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $block0 (result eqref) @@ -550,7 +550,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPT_O: (func $br_on_cast-two (type $17) (param $0 i32) (param $1 i64) (param $2 anyref) (result i32 i64 eqref) - ;; OPT_O-NEXT: (block $block (type $12) (result i32 i64 eqref) + ;; OPT_O-NEXT: (block $block (type $4) (result i32 i64 eqref) ;; OPT_O-NEXT: (tuple.make 3 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (local.get $1) @@ -644,7 +644,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPT_O: (func $br_on_cast-nn (type $18) (param $0 i32) (param $1 (ref any)) (result i32 (ref eq)) - ;; OPT_O-NEXT: (block $block (type $2) (result i32 (ref eq)) + ;; OPT_O-NEXT: (block $block (type $3) (result i32 (ref eq)) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $block0 (result (ref eq)) @@ -730,7 +730,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPT_O: (func $br_on_cast-to-nn (type $19) (param $0 i32) (param $1 anyref) (result i32 (ref eq)) - ;; OPT_O-NEXT: (block $block (type $2) (result i32 (ref eq)) + ;; OPT_O-NEXT: (block $block (type $3) (result i32 (ref eq)) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $block0 (result (ref eq)) @@ -815,8 +815,8 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $br_on_cast_fail-one (type $7) (param $0 i32) (param $1 anyref) (result i32 (ref any)) - ;; OPT_O-NEXT: (block $block (type $1) (result i32 (ref any)) + ;; OPT_O: (func $br_on_cast_fail-one (type $11) (param $0 i32) (param $1 anyref) (result i32 (ref any)) + ;; OPT_O-NEXT: (block $block (type $7) (result i32 (ref any)) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $block0 (result (ref any)) @@ -923,8 +923,8 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $br_on_cast_fail-two (type $8) (param $0 i32) (param $1 i64) (param $2 anyref) (result i32 i64 (ref any)) - ;; OPT_O-NEXT: (block $block (type $4) (result i32 i64 (ref any)) + ;; OPT_O: (func $br_on_cast_fail-two (type $12) (param $0 i32) (param $1 i64) (param $2 anyref) (result i32 i64 (ref any)) + ;; OPT_O-NEXT: (block $block (type $6) (result i32 i64 (ref any)) ;; OPT_O-NEXT: (tuple.make 3 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (local.get $1) @@ -1018,7 +1018,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPT_O: (func $br_on_cast_fail-nn (type $20) (param $0 i32) (param $1 (ref any)) (result i32 (ref any)) - ;; OPT_O-NEXT: (block $block (type $1) (result i32 (ref any)) + ;; OPT_O-NEXT: (block $block (type $7) (result i32 (ref any)) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $block0 (result (ref any)) @@ -1103,8 +1103,8 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $br_on_cast_fail-to-nn (type $9) (param $0 i32) (param $1 anyref) (result i32 anyref) - ;; OPT_O-NEXT: (block $block (type $13) (result i32 anyref) + ;; OPT_O: (func $br_on_cast_fail-to-nn (type $13) (param $0 i32) (param $1 anyref) (result i32 anyref) + ;; OPT_O-NEXT: (block $block (type $2) (result i32 anyref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $block0 (result anyref) @@ -1187,7 +1187,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $scratch_7) ;; CHECK-NEXT: ) - ;; OPT_O: (func $unreachable-fallthrough (type $6) (param $0 i32) (param $1 anyref) (result i32) + ;; OPT_O: (func $unreachable-fallthrough (type $10) (param $0 i32) (param $1 anyref) (result i32) ;; OPT_O-NEXT: (drop ;; OPT_O-NEXT: (block $l0 (result (ref any)) ;; OPT_O-NEXT: (br_on_non_null $l0 @@ -1294,7 +1294,7 @@ ;; CHECK-NEXT: ) ;; OPT_O: (func $matching-branches (type $21) (param $0 i32) (param $1 anyref) (param $2 i32) (param $3 anyref) (result i32 eqref) ;; OPT_O-NEXT: (local $4 eqref) - ;; OPT_O-NEXT: (block $block (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (block $block (type $5) (result i32 eqref) ;; OPT_O-NEXT: (local.set $4 ;; OPT_O-NEXT: (block $block0 (result eqref) ;; OPT_O-NEXT: (global.set $any @@ -1453,7 +1453,7 @@ ;; CHECK-NEXT: ) ;; OPT_O: (func $different-branches (type $22) (param $0 i32) (param $1 anyref) (param $2 i32) (param $3 eqref) (param $4 anyref) (result i32 eqref) ;; OPT_O-NEXT: (local $5 (tuple i32 eqref)) - ;; OPT_O-NEXT: (block $block (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (block $block (type $5) (result i32 eqref) ;; OPT_O-NEXT: (block $block1 ;; OPT_O-NEXT: (br $block ;; OPT_O-NEXT: (tuple.make 2 @@ -1626,7 +1626,7 @@ ;; CHECK-NEXT: ) ;; OPT_O: (func $different-branches-2 (type $23) (param $0 i32) (param $1 eqref) (param $2 anyref) (param $3 i32) (param $4 anyref) (result i32 eqref) ;; OPT_O-NEXT: (local $5 (tuple i32 eqref)) - ;; OPT_O-NEXT: (block $block (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (block $block (type $5) (result i32 eqref) ;; OPT_O-NEXT: (block $block0 ;; OPT_O-NEXT: (br $block ;; OPT_O-NEXT: (tuple.make 2 @@ -1793,7 +1793,7 @@ ;; OPT_O-NEXT: (block $block10 ;; OPT_O-NEXT: (br $block1 ;; OPT_O-NEXT: (tuple.extract 2 0 - ;; OPT_O-NEXT: (block $block (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (block $block (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $block0 (result eqref) @@ -1896,7 +1896,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPT_O: (func $with-block-param (type $25) (param $0 i64) (param $1 anyref) (result i64 eqref) - ;; OPT_O-NEXT: (block $block (type $14) (result i64 eqref) + ;; OPT_O-NEXT: (block $block (type $1) (result i64 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $block0 (result eqref) @@ -2098,7 +2098,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $loop-results (type $9) (param $0 i32) (param $1 anyref) (result i32 anyref) + ;; OPT_O: (func $loop-results (type $13) (param $0 i32) (param $1 anyref) (result i32 anyref) ;; OPT_O-NEXT: (local $2 (tuple i32 anyref)) ;; OPT_O-NEXT: (local $3 eqref) ;; OPT_O-NEXT: (local.set $2 @@ -2107,12 +2107,12 @@ ;; OPT_O-NEXT: (local.get $1) ;; OPT_O-NEXT: ) ;; OPT_O-NEXT: ) - ;; OPT_O-NEXT: (loop $label2 (type $1) (result i32 (ref any)) - ;; OPT_O-NEXT: (block $label3 (type $1) (result i32 (ref any)) + ;; OPT_O-NEXT: (loop $label2 (type $7) (result i32 (ref any)) + ;; OPT_O-NEXT: (block $label3 (type $7) (result i32 (ref any)) ;; OPT_O-NEXT: (local.set $2 - ;; OPT_O-NEXT: (block $label (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (block $label (type $5) (result i32 eqref) ;; OPT_O-NEXT: (br $label3 - ;; OPT_O-NEXT: (block $label1 (type $1) (result i32 (ref any)) + ;; OPT_O-NEXT: (block $label1 (type $7) (result i32 (ref any)) ;; OPT_O-NEXT: (local.set $3 ;; OPT_O-NEXT: (block $label0 (result eqref) ;; OPT_O-NEXT: (br $label1 @@ -2215,13 +2215,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $if (type $10) (param $0 i32) (param $1 i32) (param $2 anyref) (result i32 eqref) - ;; OPT_O-NEXT: (block $label (type $0) (result i32 eqref) + ;; OPT_O: (func $if (type $14) (param $0 i32) (param $1 i32) (param $2 anyref) (result i32 eqref) + ;; OPT_O-NEXT: (block $label (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $1) ;; OPT_O-NEXT: (block $label0 (result eqref) ;; OPT_O-NEXT: (br $label - ;; OPT_O-NEXT: (if (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (if (type $5) (result i32 eqref) ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (then ;; OPT_O-NEXT: (global.set $any @@ -2327,13 +2327,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $else (type $10) (param $0 i32) (param $1 i32) (param $2 anyref) (result i32 eqref) - ;; OPT_O-NEXT: (block $label (type $0) (result i32 eqref) + ;; OPT_O: (func $else (type $14) (param $0 i32) (param $1 i32) (param $2 anyref) (result i32 eqref) + ;; OPT_O-NEXT: (block $label (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $1) ;; OPT_O-NEXT: (block $label0 (result eqref) ;; OPT_O-NEXT: (br $label - ;; OPT_O-NEXT: (if (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (if (type $5) (result i32 eqref) ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (then ;; OPT_O-NEXT: (tuple.make 2 @@ -2469,12 +2469,12 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPT_O: (func $if-else-params (type $27) (param $0 i32) (param $1 i32) (param $2 anyref) (param $3 anyref) (result i32 eqref) - ;; OPT_O-NEXT: (block $label (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (block $label (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $label0 (result eqref) ;; OPT_O-NEXT: (br $label - ;; OPT_O-NEXT: (if (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (if (type $5) (result i32 eqref) ;; OPT_O-NEXT: (local.get $1) ;; OPT_O-NEXT: (then ;; OPT_O-NEXT: (global.set $any @@ -2573,13 +2573,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $try-catch (type $3) (param $0 i32) (param $1 anyref) (result i32 eqref) - ;; OPT_O-NEXT: (block $label (type $0) (result i32 eqref) + ;; OPT_O: (func $try-catch (type $0) (param $0 i32) (param $1 anyref) (result i32 eqref) + ;; OPT_O-NEXT: (block $label (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $label0 (result eqref) ;; OPT_O-NEXT: (br $label - ;; OPT_O-NEXT: (try (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (try (type $5) (result i32 eqref) ;; OPT_O-NEXT: (do ;; OPT_O-NEXT: (call $use-i32-any ;; OPT_O-NEXT: (local.get $0) @@ -2670,13 +2670,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $try-catch_all (type $3) (param $0 i32) (param $1 anyref) (result i32 eqref) - ;; OPT_O-NEXT: (block $label (type $0) (result i32 eqref) + ;; OPT_O: (func $try-catch_all (type $0) (param $0 i32) (param $1 anyref) (result i32 eqref) + ;; OPT_O-NEXT: (block $label (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $label0 (result eqref) ;; OPT_O-NEXT: (br $label - ;; OPT_O-NEXT: (try (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (try (type $5) (result i32 eqref) ;; OPT_O-NEXT: (do ;; OPT_O-NEXT: (call $use-i32-any ;; OPT_O-NEXT: (local.get $0) @@ -2763,13 +2763,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $try-delegate (type $3) (param $0 i32) (param $1 anyref) (result i32 eqref) - ;; OPT_O-NEXT: (block $label (type $0) (result i32 eqref) + ;; OPT_O: (func $try-delegate (type $0) (param $0 i32) (param $1 anyref) (result i32 eqref) + ;; OPT_O-NEXT: (block $label (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $label0 (result eqref) ;; OPT_O-NEXT: (br $label - ;; OPT_O-NEXT: (try (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (try (type $5) (result i32 eqref) ;; OPT_O-NEXT: (do ;; OPT_O-NEXT: (call $use-i32-any ;; OPT_O-NEXT: (local.get $0) @@ -2869,13 +2869,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $try-everything-params (type $3) (param $0 i32) (param $1 anyref) (result i32 eqref) - ;; OPT_O-NEXT: (block $label (type $0) (result i32 eqref) + ;; OPT_O: (func $try-everything-params (type $0) (param $0 i32) (param $1 anyref) (result i32 eqref) + ;; OPT_O-NEXT: (block $label (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $label0 (result eqref) ;; OPT_O-NEXT: (br $label - ;; OPT_O-NEXT: (try (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (try (type $5) (result i32 eqref) ;; OPT_O-NEXT: (do ;; OPT_O-NEXT: (call $use-i32-any ;; OPT_O-NEXT: (local.get $0) @@ -2975,13 +2975,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $try_table (type $3) (param $0 i32) (param $1 anyref) (result i32 eqref) - ;; OPT_O-NEXT: (block $label (type $0) (result i32 eqref) + ;; OPT_O: (func $try_table (type $0) (param $0 i32) (param $1 anyref) (result i32 eqref) + ;; OPT_O-NEXT: (block $label (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $label0 (result eqref) ;; OPT_O-NEXT: (br $label - ;; OPT_O-NEXT: (try_table (type $0) (result i32 eqref) + ;; OPT_O-NEXT: (try_table (type $5) (result i32 eqref) ;; OPT_O-NEXT: (call $use-i32-any ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (br_on_cast $label0 anyref eqref @@ -3058,13 +3058,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $try_table-params (type $3) (param $0 i32) (param $1 anyref) (result i32 eqref) - ;; OPT_O-NEXT: (block $label (type $0) (result i32 eqref) + ;; OPT_O: (func $try_table-params (type $0) (param $0 i32) (param $1 anyref) (result i32 eqref) + ;; OPT_O-NEXT: (block $label (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $label0 (result eqref) ;; OPT_O-NEXT: (br $label - ;; OPT_O-NEXT: (try_table (type $2) (result i32 (ref eq)) + ;; OPT_O-NEXT: (try_table (type $3) (result i32 (ref eq)) ;; OPT_O-NEXT: (call $use-i32-any ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (br_on_cast $label0 anyref eqref @@ -3143,8 +3143,8 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPT_O: (func $branch-to-func (type $3) (param $0 i32) (param $1 anyref) (result i32 eqref) - ;; OPT_O-NEXT: (block $label (type $0) (result i32 eqref) + ;; OPT_O: (func $branch-to-func (type $0) (param $0 i32) (param $1 anyref) (result i32 eqref) + ;; OPT_O-NEXT: (block $label (type $5) (result i32 eqref) ;; OPT_O-NEXT: (tuple.make 2 ;; OPT_O-NEXT: (local.get $0) ;; OPT_O-NEXT: (block $label0 (result eqref) diff --git a/test/lit/help/wasm-as.test b/test/lit/help/wasm-as.test index 77ae850e4df..f5d57fc46bb 100644 --- a/test/lit/help/wasm-as.test +++ b/test/lit/help/wasm-as.test @@ -134,6 +134,12 @@ ;; CHECK-NEXT: --disable-custom-descriptors Disable custom descriptors (RTTs) and ;; CHECK-NEXT: exact references ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-string-builtins Enable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-string-builtins Disable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-ctor-eval.test b/test/lit/help/wasm-ctor-eval.test index 9a5fbdcda26..60b1c175598 100644 --- a/test/lit/help/wasm-ctor-eval.test +++ b/test/lit/help/wasm-ctor-eval.test @@ -141,6 +141,12 @@ ;; CHECK-NEXT: --disable-custom-descriptors Disable custom descriptors (RTTs) and ;; CHECK-NEXT: exact references ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-string-builtins Enable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-string-builtins Disable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-dis.test b/test/lit/help/wasm-dis.test index a10b41a4f3c..b2ca9cfbc15 100644 --- a/test/lit/help/wasm-dis.test +++ b/test/lit/help/wasm-dis.test @@ -127,6 +127,12 @@ ;; CHECK-NEXT: --disable-custom-descriptors Disable custom descriptors (RTTs) and ;; CHECK-NEXT: exact references ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-string-builtins Enable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-string-builtins Disable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-emscripten-finalize.test b/test/lit/help/wasm-emscripten-finalize.test index 4cb9ef940a0..06f5bc556b2 100644 --- a/test/lit/help/wasm-emscripten-finalize.test +++ b/test/lit/help/wasm-emscripten-finalize.test @@ -169,6 +169,12 @@ ;; CHECK-NEXT: --disable-custom-descriptors Disable custom descriptors (RTTs) and ;; CHECK-NEXT: exact references ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-string-builtins Enable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-string-builtins Disable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-merge.test b/test/lit/help/wasm-merge.test index a8b95194950..25dbc0723ba 100644 --- a/test/lit/help/wasm-merge.test +++ b/test/lit/help/wasm-merge.test @@ -157,6 +157,12 @@ ;; CHECK-NEXT: --disable-custom-descriptors Disable custom descriptors (RTTs) and ;; CHECK-NEXT: exact references ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-string-builtins Enable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-string-builtins Disable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-metadce.test b/test/lit/help/wasm-metadce.test index 5870b5c9d45..c4ba77e67a6 100644 --- a/test/lit/help/wasm-metadce.test +++ b/test/lit/help/wasm-metadce.test @@ -787,6 +787,12 @@ ;; CHECK-NEXT: --disable-custom-descriptors Disable custom descriptors ;; CHECK-NEXT: (RTTs) and exact references ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-string-builtins Enable string builtins (imported +;; CHECK-NEXT: JS strings) +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-string-builtins Disable string builtins +;; CHECK-NEXT: (imported JS strings) +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test index ac98198d2dd..cdc91c15333 100644 --- a/test/lit/help/wasm-opt.test +++ b/test/lit/help/wasm-opt.test @@ -799,6 +799,12 @@ ;; CHECK-NEXT: --disable-custom-descriptors Disable custom descriptors ;; CHECK-NEXT: (RTTs) and exact references ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-string-builtins Enable string builtins (imported +;; CHECK-NEXT: JS strings) +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-string-builtins Disable string builtins +;; CHECK-NEXT: (imported JS strings) +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-reduce.test b/test/lit/help/wasm-reduce.test index 2739394e3ed..739388333c8 100644 --- a/test/lit/help/wasm-reduce.test +++ b/test/lit/help/wasm-reduce.test @@ -217,6 +217,12 @@ ;; CHECK-NEXT: --disable-custom-descriptors Disable custom descriptors (RTTs) and ;; CHECK-NEXT: exact references ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-string-builtins Enable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-string-builtins Disable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm-split.test b/test/lit/help/wasm-split.test index 095c66047ac..abcc9607482 100644 --- a/test/lit/help/wasm-split.test +++ b/test/lit/help/wasm-split.test @@ -266,6 +266,12 @@ ;; CHECK-NEXT: --disable-custom-descriptors Disable custom descriptors (RTTs) and ;; CHECK-NEXT: exact references ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-string-builtins Enable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-string-builtins Disable string builtins (imported JS +;; CHECK-NEXT: strings) +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test index ac68667554b..ec69865fa22 100644 --- a/test/lit/help/wasm2js.test +++ b/test/lit/help/wasm2js.test @@ -751,6 +751,12 @@ ;; CHECK-NEXT: --disable-custom-descriptors Disable custom descriptors ;; CHECK-NEXT: (RTTs) and exact references ;; CHECK-NEXT: +;; CHECK-NEXT: --enable-string-builtins Enable string builtins (imported +;; CHECK-NEXT: JS strings) +;; CHECK-NEXT: +;; CHECK-NEXT: --disable-string-builtins Disable string builtins +;; CHECK-NEXT: (imported JS strings) +;; CHECK-NEXT: ;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag diff --git a/test/lit/passes/O3_stack-switching.wast b/test/lit/passes/O3_stack-switching.wast index d928f6614b2..262f224cd1a 100644 --- a/test/lit/passes/O3_stack-switching.wast +++ b/test/lit/passes/O3_stack-switching.wast @@ -19,9 +19,9 @@ (type $cont (cont $function_1)) ;; CHECK: (type $fiber (struct (field $handlers (ref $handlers)) (field $cont (ref $cont)))) (type $fiber (struct (field $handlers (ref $handlers)) (field $cont (ref $cont)))) - ;; CHECK: (tag $exception (type $8) (param (ref eq))) + ;; CHECK: (tag $exception (type $9) (param (ref eq))) (tag $exception (param (ref eq))) - ;; CHECK: (tag $effect (type $9) (param (ref eq)) (result (ref eq) (ref eq))) + ;; CHECK: (tag $effect (type $8) (param (ref eq)) (result (ref eq) (ref eq))) (tag $effect (param (ref eq)) (result (ref eq) (ref eq))) ;; CHECK: (func $resume (type $10) (param $0 (ref $fiber)) (param $1 (ref $closure)) (param $2 (ref eq)) (result (ref eq)) diff --git a/test/lit/passes/gto_and_cfp_in_O.wast b/test/lit/passes/gto_and_cfp_in_O.wast index 783da3a1982..78ac48d675e 100644 --- a/test/lit/passes/gto_and_cfp_in_O.wast +++ b/test/lit/passes/gto_and_cfp_in_O.wast @@ -8,10 +8,11 @@ ;; open world we do not run them. (module - ;; OPEN_WORLD: (type $struct (sub (struct (field (mut funcref)) (field (mut i32))))) - (type $struct (sub (struct (field (mut funcref)) (field (mut i32))))) + ;; OPEN_WORLD: (rec + ;; OPEN_WORLD-NEXT: (type $0 (func)) - ;; OPEN_WORLD: (type $1 (func)) + ;; OPEN_WORLD: (type $struct (sub (struct (field (mut funcref)) (field (mut i32))))) + (type $struct (sub (struct (field (mut funcref)) (field (mut i32))))) ;; OPEN_WORLD: (type $2 (func (result i32))) @@ -26,7 +27,7 @@ ;; OPEN_WORLD: (export "main" (func $main)) - ;; OPEN_WORLD: (func $by-ref (type $1) + ;; OPEN_WORLD: (func $by-ref (type $0) ;; OPEN_WORLD-NEXT: (struct.set $struct 1 ;; OPEN_WORLD-NEXT: (global.get $glob) ;; OPEN_WORLD-NEXT: (i32.const 200) diff --git a/test/lit/string-builtins.wast b/test/lit/string-builtins.wast new file mode 100644 index 00000000000..126a4c09ea7 --- /dev/null +++ b/test/lit/string-builtins.wast @@ -0,0 +1,58 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; Run normal -O2, which should lift, optimize, and lower strings, if the +;; string builtins feature is enabled (GC is required, as well, as the lowering +;; emits functions using arrays). We optimize identically in the last two here. + +;; RUN: foreach %s %t wasm-opt -O2 -S -o - --enable-reference-types \ +;; RUN: | filecheck %s --check-prefix=MVP + +;; RUN: foreach %s %t wasm-opt -O2 -S -o - -all \ +;; RUN: | filecheck %s --check-prefix=OPT + +;; RUN: foreach %s %t wasm-opt -O2 -S -o - --enable-reference-types \ +;; RUN: --enable-string-builtins --enable-gc \ +;; RUN: | filecheck %s --check-prefix=OPT + +(module + (type $array16 (array (mut i16))) + + ;; MVP: (type $0 (func (param externref externref) (result (ref extern)))) + + ;; MVP: (type $1 (func (result (ref extern)))) + + ;; MVP: (import "\'" "foo" (global $foo (ref extern))) + (import "\'" "foo" (global $foo (ref extern))) + + ;; MVP: (import "\'" "bar" (global $bar (ref extern))) + (import "\'" "bar" (global $bar (ref extern))) + + ;; MVP: (import "wasm:js-string" "concat" (func $concat (param externref externref) (result (ref extern)))) + (import "wasm:js-string" "concat" (func $concat (param externref externref) (result (ref extern)))) + + ;; MVP: (export "string.concat" (func $string.concat)) + + ;; MVP: (func $string.concat (result (ref extern)) + ;; MVP-NEXT: (call $concat + ;; MVP-NEXT: (global.get $foo) + ;; MVP-NEXT: (global.get $bar) + ;; MVP-NEXT: ) + ;; MVP-NEXT: ) + ;; OPT: (type $0 (func (result (ref extern)))) + + ;; OPT: (import "\'" "foobar" (global $"string.const_\"foobar\"" (ref extern))) + + ;; OPT: (export "string.concat" (func $string.concat)) + + ;; OPT: (func $string.concat (type $0) (result (ref extern)) + ;; OPT-NEXT: (global.get $"string.const_\"foobar\"") + ;; OPT-NEXT: ) + (func $string.concat (export "string.concat") (result (ref extern)) + ;; When we optimize, we concatenate "foo" and "bar" here to "foobar". A new + ;; imported global will appear for that, and we will get it here. + (call $concat + (global.get $foo) + (global.get $bar) + ) + ) +) diff --git a/test/passes/strip-target-features_roundtrip_print-features_all-features.txt b/test/passes/strip-target-features_roundtrip_print-features_all-features.txt index 34976434e9d..2f012471e1e 100644 --- a/test/passes/strip-target-features_roundtrip_print-features_all-features.txt +++ b/test/passes/strip-target-features_roundtrip_print-features_all-features.txt @@ -20,6 +20,7 @@ --enable-bulk-memory-opt --enable-call-indirect-overlong --enable-custom-descriptors +--enable-string-builtins (module (type $0 (func (result v128 externref))) (func $foo (type $0) (result v128 externref) diff --git a/test/reduce/gc.wast.txt b/test/reduce/gc.wast.txt index 3af5287ce99..e19d3da34ac 100644 --- a/test/reduce/gc.wast.txt +++ b/test/reduce/gc.wast.txt @@ -1,7 +1,7 @@ (module (type $0 (struct (field (mut i32)) (field funcref))) (type $1 (func (result i32))) - (global $global$0 (ref null $0) (struct.new_default $0)) + (global $global$0 (ref (exact $0)) (struct.new_default $0)) (export "use-global" (func $0)) (func $0 (result i32) (struct.set $0 0 diff --git a/test/unit/test_features.py b/test/unit/test_features.py index 2647ff84717..aede708dc67 100644 --- a/test/unit/test_features.py +++ b/test/unit/test_features.py @@ -453,4 +453,5 @@ def test_emit_all_features(self): '--enable-bulk-memory-opt', '--enable-call-indirect-overlong', '--enable-custom-descriptors', + '--enable-string-builtins', ], p2.stdout.splitlines()) diff --git a/test/unit/test_passes.py b/test/unit/test_passes.py index 838f1d2f73f..ac05419c234 100644 --- a/test/unit/test_passes.py +++ b/test/unit/test_passes.py @@ -61,3 +61,18 @@ def test_O3_O1(self): self.assertNotIn(PASS_IN_O3_ONLY, self.get_passes_run(['-O1'])) self.assertNotIn(PASS_IN_O3_ONLY, self.get_passes_run(['-O1', '-O1'])) + + def test_string_builtins(self): + # When we enable string builtins, we lift early and lower late, and + # only do each once even if there are multiple -O2 operations. + passes = self.get_passes_run(['-O2', '-O2', '-all']) + self.assertEqual(passes.count('string-lifting'), 1) + self.assertEqual(passes.count('string-lowering-magic-imports'), 1) + + # Other passes appear twice, when -O2 is repeated + self.assertEqual(passes.count('directize'), 2) + + # Without the feature, we do not lift or lower. + passes = self.get_passes_run(['-O2', '-O2', '-all', '--disable-string-builtins']) + self.assertEqual(passes.count('string-lifting'), 0) + self.assertEqual(passes.count('string-lowering-magic-imports'), 0)