diff options
-rw-r--r-- | src/wasm-binary.h | 4 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 61 | ||||
-rw-r--r-- | test/binaryen.js/kitchen-sink.js.txt | 2 | ||||
-rw-r--r-- | test/exception-handling.wast.fromBinary | 68 | ||||
-rw-r--r-- | test/lit/passes/stack-ir-roundtrip-eh.wast | 5 | ||||
-rw-r--r-- | test/reference-types.wast.fromBinary | 10 | ||||
-rw-r--r-- | test/tags.wast.fromBinary | 16 |
7 files changed, 112 insertions, 54 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h index f6924aa14..a00a1df46 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -454,6 +454,7 @@ enum Subsection { NameData = 9, // see: https://github.com/WebAssembly/gc/issues/193 NameField = 10, + NameTag = 11, DylinkMemInfo = 1, DylinkNeeded = 2, @@ -1552,6 +1553,9 @@ public: // at index i we have all refs to the global i std::map<Index, std::vector<Name*>> globalRefs; + // at index i we have all refs to the tag i + std::map<Index, std::vector<Name*>> tagRefs; + // Throws a parsing error if we are not in a function context void requireFunctionContext(const char* error); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 685da0bf1..1fb43c884 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1070,6 +1070,30 @@ void WasmBinaryWriter::writeNames() { } } + // tag names + if (!wasm->tags.empty()) { + Index count = 0; + for (auto& tag : wasm->tags) { + if (tag->hasExplicitName) { + count++; + } + } + + if (count) { + auto substart = + startSubsection(BinaryConsts::UserSections::Subsection::NameTag); + o << U32LEB(count); + for (Index i = 0; i < wasm->tags.size(); i++) { + auto& tag = wasm->tags[i]; + if (tag->hasExplicitName) { + o << U32LEB(i); + writeEscapedName(tag->name.str); + } + } + finishSubsection(substart); + } + } + finishSection(start); } @@ -3012,24 +3036,26 @@ void WasmBinaryBuilder::processNames() { *ref = getFunctionName(index); } } - for (auto& [index, refs] : tableRefs) { for (auto* ref : refs) { *ref = getTableName(index); } } - for (auto& [index, refs] : memoryRefs) { for (auto ref : refs) { *ref = getMemoryName(index); } } - for (auto& [index, refs] : globalRefs) { for (auto* ref : refs) { *ref = getGlobalName(index); } } + for (auto& [index, refs] : tagRefs) { + for (auto* ref : refs) { + *ref = getTagName(index); + } + } // Everything now has its proper name. @@ -3455,6 +3481,22 @@ void WasmBinaryBuilder::readNames(size_t payloadLen) { } } } + } else if (nameType == BinaryConsts::UserSections::Subsection::NameTag) { + auto num = getU32LEB(); + NameProcessor processor; + for (size_t i = 0; i < num; i++) { + auto index = getU32LEB(); + auto rawName = getInlineString(); + auto name = processor.process(rawName); + if (index < wasm.tags.size()) { + wasm.tags[index]->setExplicitName(name); + } else { + std::cerr << "warning: tag index out of bounds in name section, " + "tag subsection: " + << std::string(rawName.str) << " at index " + << std::to_string(index) << std::endl; + } + } } else { std::cerr << "warning: unknown name subsection with id " << std::to_string(nameType) << " at " << pos << std::endl; @@ -6652,6 +6694,11 @@ void WasmBinaryBuilder::visitTryOrTryInBlock(Expression*& out) { } }; + // We cannot immediately update tagRefs in the loop below, as catchTags is + // being grown, an so references would get invalidated. Store the indexes + // here, then do that later. + std::vector<Index> tagIndexes; + while (lastSeparator == BinaryConsts::Catch || lastSeparator == BinaryConsts::CatchAll) { if (lastSeparator == BinaryConsts::Catch) { @@ -6659,10 +6706,10 @@ void WasmBinaryBuilder::visitTryOrTryInBlock(Expression*& out) { if (index >= wasm.tags.size()) { throwError("bad tag index"); } + tagIndexes.push_back(index); auto* tag = wasm.tags[index].get(); curr->catchTags.push_back(tag->name); readCatchBody(tag->sig.params); - } else { // catch_all if (curr->hasCatchAll()) { throwError("there should be at most one 'catch_all' clause per try"); @@ -6672,6 +6719,11 @@ void WasmBinaryBuilder::visitTryOrTryInBlock(Expression*& out) { } breakStack.pop_back(); + for (Index i = 0; i < tagIndexes.size(); i++) { + // We don't know the final name yet. + tagRefs[tagIndexes[i]].push_back(&curr->catchTags[i]); + } + if (lastSeparator == BinaryConsts::Delegate) { curr->delegateTarget = getExceptionTargetName(getU32LEB()); } @@ -6768,6 +6820,7 @@ void WasmBinaryBuilder::visitThrow(Throw* curr) { } auto* tag = wasm.tags[index].get(); curr->tag = tag->name; + tagRefs[index].push_back(&curr->tag); // we don't know the final name yet size_t num = tag->sig.params.size(); curr->operands.resize(num); for (size_t i = 0; i < num; i++) { diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index de3510545..f92ceeb4a 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -4797,7 +4797,7 @@ module loaded from binary form: (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (global $a-global i32 (i32.const 3)) - (tag $tag$0 (param i32 i32)) + (tag $a-tag (param i32 i32)) (func $adder (param $0 i32) (param $1 i32) (result i32) (i32.add (local.get $0) diff --git a/test/exception-handling.wast.fromBinary b/test/exception-handling.wast.fromBinary index 74e8f4d4a..73a4ae975 100644 --- a/test/exception-handling.wast.fromBinary +++ b/test/exception-handling.wast.fromBinary @@ -4,11 +4,11 @@ (type $i64_=>_none (func (param i64))) (type $i32_i64_=>_none (func (param i32 i64))) (type $eqref_=>_none (func (param eqref))) - (tag $tag$0 (param i32)) - (tag $tag$1 (param i64)) - (tag $tag$2 (param i32 i64)) - (tag $tag$3 (param eqref)) - (tag $tag$4 (param)) + (tag $e-i32 (param i32)) + (tag $e-i64 (param i64)) + (tag $e-i32-i64 (param i32 i64)) + (tag $e-eqref (param eqref)) + (tag $e-empty (param)) (func $foo (nop) ) @@ -23,11 +23,11 @@ (local $4 i32) (try $label$3 (do - (throw $tag$0 + (throw $e-i32 (i32.const 0) ) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -35,12 +35,12 @@ ) (try $label$6 (do - (throw $tag$2 + (throw $e-i32-i64 (i32.const 0) (i64.const 0) ) ) - (catch $tag$2 + (catch $e-i32-i64 (local.set $2 (pop i32 i64) ) @@ -77,7 +77,7 @@ (do (br $label$7) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -89,7 +89,7 @@ (do (nop) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -100,7 +100,7 @@ (call $foo) (call $bar) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -110,16 +110,16 @@ ) (try $label$19 (do - (throw $tag$0 + (throw $e-i32 (i32.const 0) ) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) ) - (catch $tag$1 + (catch $e-i64 (drop (pop i64) ) @@ -127,7 +127,7 @@ ) (try $label$22 (do - (throw $tag$0 + (throw $e-i32 (i32.const 0) ) ) @@ -137,16 +137,16 @@ ) (try $label$25 (do - (throw $tag$0 + (throw $e-i32 (i32.const 0) ) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) ) - (catch $tag$1 + (catch $e-i64 (drop (pop i64) ) @@ -160,11 +160,11 @@ (do (try $label$29 (do - (throw $tag$0 + (throw $e-i32 (i32.const 0) ) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -174,7 +174,7 @@ ) ) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -182,11 +182,11 @@ (catch_all (try $label$33 (do - (throw $tag$0 + (throw $e-i32 (i32.const 0) ) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -199,7 +199,7 @@ ) (try $label$37 (do - (throw $tag$0 + (throw $e-i32 (i32.const 0) ) ) @@ -271,7 +271,7 @@ (do (nop) ) - (catch $tag$4 + (catch $e-empty (nop) ) ) @@ -281,7 +281,7 @@ (do (call $foo) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -296,7 +296,7 @@ (do (call $foo) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -316,7 +316,7 @@ (do (call $foo) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -337,7 +337,7 @@ (do (call $foo) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -387,8 +387,8 @@ (do (nop) ) - (catch $tag$0 - (throw $tag$0 + (catch $e-i32 + (throw $e-i32 (if (result i32) (pop i32) (i32.const 0) @@ -401,7 +401,7 @@ (do (nop) ) - (catch $tag$3 + (catch $e-eqref (drop (pop eqref) ) @@ -414,7 +414,7 @@ (block $label$1 (try $label$4 (do - (throw $tag$0 + (throw $e-i32 (i32.const 0) ) ) diff --git a/test/lit/passes/stack-ir-roundtrip-eh.wast b/test/lit/passes/stack-ir-roundtrip-eh.wast index df68d3f8a..790462cb9 100644 --- a/test/lit/passes/stack-ir-roundtrip-eh.wast +++ b/test/lit/passes/stack-ir-roundtrip-eh.wast @@ -2,6 +2,7 @@ ;; RUN: wasm-opt %s --generate-stack-ir --roundtrip -all -S -o - | filecheck %s (module + ;; CHECK: (tag $tag (param i32)) (tag $tag (param i32)) ;; CHECK: (func $delegate-child ;; CHECK-NEXT: (try $label$9 @@ -10,7 +11,7 @@ ;; CHECK-NEXT: (do ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $tag$0 + ;; CHECK-NEXT: (catch $tag ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (pop i32) ;; CHECK-NEXT: ) @@ -23,7 +24,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $tag$0 + ;; CHECK-NEXT: (catch $tag ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (pop i32) ;; CHECK-NEXT: ) diff --git a/test/reference-types.wast.fromBinary b/test/reference-types.wast.fromBinary index 01523cab8..80d85fd26 100644 --- a/test/reference-types.wast.fromBinary +++ b/test/reference-types.wast.fromBinary @@ -18,7 +18,7 @@ (table $0 3 3 funcref) (elem (i32.const 0) $take_eqref $take_funcref $take_anyref) (elem declare func $foo $ref-taken-but-not-in-table) - (tag $tag$0 (param i32)) + (tag $e-i32 (param i32)) (export "export_func" (func $import_func)) (export "export_global" (global $import_global)) (func $take_eqref (param $0 eqref) @@ -416,7 +416,7 @@ (do (local.get $local_eqref) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -429,7 +429,7 @@ (do (ref.func $foo) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -442,7 +442,7 @@ (do (local.get $local_eqref) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) @@ -455,7 +455,7 @@ (do (ref.null eq) ) - (catch $tag$0 + (catch $e-i32 (drop (pop i32) ) diff --git a/test/tags.wast.fromBinary b/test/tags.wast.fromBinary index 81043d682..5528068c0 100644 --- a/test/tags.wast.fromBinary +++ b/test/tags.wast.fromBinary @@ -2,15 +2,15 @@ (type $i32_f32_=>_none (func (param i32 f32))) (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) - (import "env" "im0" (tag $eimport$0 (param i32))) + (import "env" "im0" (tag $e-import (param i32))) (import "env" "im1" (tag $eimport$1 (param i32 f32))) (tag $tag$0 (param i32)) - (tag $tag$1 (param i32 f32)) - (tag $tag$2 (param)) - (tag $tag$3 (param i32 f32)) - (tag $tag$4 (param i32 f32)) - (tag $tag$5 (param i32)) - (export "ex0" (tag $tag$5)) - (export "ex1" (tag $tag$1)) + (tag $e (param i32 f32)) + (tag $empty (param)) + (tag $e-params0 (param i32 f32)) + (tag $e-params1 (param i32 f32)) + (tag $e-export (param i32)) + (export "ex0" (tag $e-export)) + (export "ex1" (tag $e)) ) |