@@ -160,6 +160,19 @@ struct FuncData {
160160 }
161161};
162162
163+ // The data of a (ref exn) literal.
164+ struct ExnData {
165+ // The tag of this exn data.
166+ // TODO: Add self, like in FuncData, to handle the case of a module that is
167+ // instantiated multiple times.
168+ Tag* tag;
169+
170+ // The payload of this exn data.
171+ Literals payload;
172+
173+ ExnData (Tag* tag, Literals payload) : tag(tag), payload(payload) {}
174+ };
175+
163176// Suspend/resume support.
164177//
165178// As we operate directly on our structured IR, we do not have a program counter
@@ -324,7 +337,7 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
324337 }
325338
326339 // Same as makeGCData but for ExnData.
327- Literal makeExnData (Name tag, const Literals& payload) {
340+ Literal makeExnData (Tag* tag, const Literals& payload) {
328341 auto allocation = std::make_shared<ExnData>(tag, payload);
329342#if __has_feature(leak_sanitizer) || __has_feature(address_sanitizer)
330343 __lsan_ignore_object (allocation.get ());
@@ -1890,9 +1903,18 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
18901903 Flow visitTry (Try* curr) { WASM_UNREACHABLE (" unimp" ); }
18911904 Flow visitTryTable (TryTable* curr) { WASM_UNREACHABLE (" unimp" ); }
18921905 Flow visitThrow (Throw* curr) {
1906+ // Single-module implementation. This is used from Precompute, for example.
1907+ // It is overriden in ModuleRunner to add logic for finding the proper
1908+ // imported tag (which single-module cases don't care about).
18931909 Literals arguments;
18941910 VISIT_ARGUMENTS (flow, curr->operands , arguments);
1895- throwException (WasmException{makeExnData (curr->tag , arguments)});
1911+ auto * tag = self ()->getModule ()->getTag (curr->tag );
1912+ if (tag->imported ()) {
1913+ // The same tag can be imported twice, so by looking at only the current
1914+ // module we can't tell if two tags are the same or not.
1915+ return NONCONSTANT_FLOW ;
1916+ }
1917+ throwException (WasmException{self ()->makeExnData (tag, arguments)});
18961918 WASM_UNREACHABLE (" throw" );
18971919 }
18981920 Flow visitRethrow (Rethrow* curr) { WASM_UNREACHABLE (" unimp" ); }
@@ -2908,6 +2930,9 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
29082930 virtual void trap (const char * why) = 0;
29092931 virtual void hostLimit (const char * why) = 0;
29102932 virtual void throwException (const WasmException& exn) = 0;
2933+ // Get the Tag instance for a tag implemented in the host, that is, not
2934+ // among the linked ModuleRunner instances, but imported from the host.
2935+ virtual Tag* getImportedTag (Tag* tag) = 0;
29112936
29122937 // the default impls for load and store switch on the sizes. you can either
29132938 // customize load/store, or the sub-functions which they call
@@ -3194,6 +3219,18 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
31943219 return iter->second ;
31953220 }
31963221
3222+ Tag* getExportedTag (Name name) {
3223+ Export* export_ = wasm.getExportOrNull (name);
3224+ if (!export_ || export_->kind != ExternalKind::Tag) {
3225+ externalInterface->trap (" exported tag not found" );
3226+ }
3227+ auto * tag = wasm.getTag (*export_->getInternalName ());
3228+ if (tag->imported ()) {
3229+ tag = externalInterface->getImportedTag (tag);
3230+ }
3231+ return tag;
3232+ }
3233+
31973234 std::string printFunctionStack () {
31983235 std::string ret = " /== (binaryen interpreter stack trace)\n " ;
31993236 for (int i = int (functionStack.size ()) - 1 ; i >= 0 ; i--) {
@@ -3445,12 +3482,15 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
34453482 Tag* getCanonicalTag (Name name) {
34463483 auto * inst = self ();
34473484 auto * tag = inst->wasm .getTag (name);
3448- while (tag->imported ()) {
3449- inst = inst->linkedInstances .at (tag->module ).get ();
3450- auto * tagExport = inst->wasm .getExport (tag->base );
3451- tag = inst->wasm .getTag (*tagExport->getInternalName ());
3485+ if (!tag->imported ()) {
3486+ return tag;
34523487 }
3453- return tag;
3488+ auto iter = inst->linkedInstances .find (tag->module );
3489+ if (iter == inst->linkedInstances .end ()) {
3490+ return externalInterface->getImportedTag (tag);
3491+ }
3492+ inst = iter->second .get ();
3493+ return inst->getExportedTag (tag->base );
34543494 }
34553495
34563496public:
@@ -4354,7 +4394,8 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
43544394
43554395 auto exnData = e.exn .getExnData ();
43564396 for (size_t i = 0 ; i < curr->catchTags .size (); i++) {
4357- if (curr->catchTags [i] == exnData->tag ) {
4397+ auto * tag = self ()->getCanonicalTag (curr->catchTags [i]);
4398+ if (tag == exnData->tag ) {
43584399 multiValues.push_back (exnData->payload );
43594400 return processCatchBody (curr->catchBodies [i]);
43604401 }
@@ -4377,7 +4418,8 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
43774418 auto exnData = e.exn .getExnData ();
43784419 for (size_t i = 0 ; i < curr->catchTags .size (); i++) {
43794420 auto catchTag = curr->catchTags [i];
4380- if (!catchTag.is () || catchTag == exnData->tag ) {
4421+ if (!catchTag.is () ||
4422+ self ()->getCanonicalTag (catchTag) == exnData->tag ) {
43814423 Flow ret;
43824424 ret.breakTo = curr->catchDests [i];
43834425 if (catchTag.is ()) {
@@ -4395,6 +4437,13 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
43954437 throw ;
43964438 }
43974439 }
4440+ Flow visitThrow (Throw* curr) {
4441+ Literals arguments;
4442+ VISIT_ARGUMENTS (flow, curr->operands , arguments);
4443+ throwException (WasmException{
4444+ self ()->makeExnData (self ()->getCanonicalTag (curr->tag ), arguments)});
4445+ WASM_UNREACHABLE (" throw" );
4446+ }
43984447 Flow visitRethrow (Rethrow* curr) {
43994448 for (int i = exceptionStack.size () - 1 ; i >= 0 ; i--) {
44004449 if (exceptionStack[i].second == curr->target ) {
@@ -4463,9 +4512,8 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
44634512 assert (self ()->restoredValuesMap .empty ());
44644513 // Throw, if we were resumed by resume_throw;
44654514 if (auto * tag = currContinuation->exceptionTag ) {
4466- // XXX tag->name lacks cross-module support
44674515 throwException (WasmException{
4468- self ()->makeExnData (tag-> name , currContinuation->resumeArguments )});
4516+ self ()->makeExnData (tag, currContinuation->resumeArguments )});
44694517 }
44704518 return currContinuation->resumeArguments ;
44714519 }
@@ -4668,9 +4716,8 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
46684716 // set), so resuming is done. (And throw, if resume_throw.)
46694717 self ()->continuationStore ->resuming = false ;
46704718 if (auto * tag = currContinuation->exceptionTag ) {
4671- // XXX tag->name lacks cross-module support
46724719 throwException (WasmException{
4673- self ()->makeExnData (tag-> name , currContinuation->resumeArguments )});
4720+ self ()->makeExnData (tag, currContinuation->resumeArguments )});
46744721 }
46754722 }
46764723 }
0 commit comments