@@ -1366,6 +1366,7 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
13661366 &Self::makeCall,
13671367 &Self::makeCallIndirect)
13681368 .add (FeatureSet::ExceptionHandling, &Self::makeTry)
1369+ .add (FeatureSet::ExceptionHandling, &Self::makeTryTable)
13691370 .add (FeatureSet::GC | FeatureSet::ReferenceTypes, &Self::makeCallRef);
13701371 }
13711372 if (type.isSingle ()) {
@@ -1451,6 +1452,8 @@ Expression* TranslateToFuzzReader::_makenone() {
14511452 &Self::makeGlobalSet)
14521453 .add (FeatureSet::BulkMemory, &Self::makeBulkMemory)
14531454 .add (FeatureSet::Atomics, &Self::makeAtomic)
1455+ .add (FeatureSet::ExceptionHandling, &Self::makeTry)
1456+ .add (FeatureSet::ExceptionHandling, &Self::makeTryTable)
14541457 .add (FeatureSet::GC | FeatureSet::ReferenceTypes, &Self::makeCallRef)
14551458 .add (FeatureSet::GC | FeatureSet::ReferenceTypes, &Self::makeStructSet)
14561459 .add (FeatureSet::GC | FeatureSet::ReferenceTypes, &Self::makeArraySet)
@@ -1688,6 +1691,71 @@ Expression* TranslateToFuzzReader::makeTry(Type type) {
16881691 return builder.makeTry (body, catchTags, catchBodies);
16891692}
16901693
1694+ Expression* TranslateToFuzzReader::makeTryTable (Type type) {
1695+ auto * body = make (type);
1696+
1697+ if (funcContext->breakableStack .empty ()) {
1698+ // Nothing to break to, emit a trivial TryTable.
1699+ // TODO: Perhaps generate a block wrapping us?
1700+ return builder.makeTryTable (body, {}, {}, {});
1701+ }
1702+
1703+ if (wasm.tags .empty ()) {
1704+ addTag ();
1705+ }
1706+
1707+ // Add catches of specific tags, and possibly a catch_all at the end. We use
1708+ // the last iteration of the loop for that.
1709+ std::vector<Name> catchTags;
1710+ std::vector<Name> catchDests;
1711+ std::vector<bool > catchRefs;
1712+ auto numCatches = upTo (MAX_TRY_CATCHES);
1713+ for (Index i = 0 ; i <= numCatches; i++) {
1714+ Name tagName;
1715+ Type tagType;
1716+ if (i < numCatches) {
1717+ // Look for a specific tag.
1718+ auto & tag = pick (wasm.tags );
1719+ tagName = tag->name ;
1720+ tagType = tag->sig .params ;
1721+ } else {
1722+ // Add a catch_all at the end, some of the time (but all of the time if we
1723+ // have nothing else).
1724+ if (!catchTags.empty () && oneIn (2 )) {
1725+ break ;
1726+ }
1727+ tagType = Type::none;
1728+ }
1729+
1730+ // We need to find a proper target to break to, which means a target that
1731+ // has the type of the tag, or the tag + an exnref at the end.
1732+ std::vector<Type> vec (tagType.begin (), tagType.end ());
1733+ // Use a non-nullable exnref here, and then the subtyping check below will
1734+ // also accept a target that is nullable.
1735+ vec.push_back (Type (HeapType::exn, NonNullable));
1736+ auto tagTypeWithExn = Type (vec);
1737+ int tries = TRIES;
1738+ while (tries-- > 0 ) {
1739+ auto * target = pick (funcContext->breakableStack );
1740+ auto dest = getTargetName (target);
1741+ auto valueType = getTargetType (target);
1742+ auto subOfTagType = Type::isSubType (tagType, valueType);
1743+ auto subOfTagTypeWithExn = Type::isSubType (tagTypeWithExn, valueType);
1744+ if (subOfTagType || subOfTagTypeWithExn) {
1745+ catchTags.push_back (tagName);
1746+ catchDests.push_back (dest);
1747+ catchRefs.push_back (subOfTagTypeWithExn);
1748+ break ;
1749+ }
1750+ }
1751+ // TODO: Perhaps generate a block wrapping us, if we fail to find a target?
1752+ // TODO: It takes a bit of luck to find a target with an exnref - perhaps
1753+ // generate those?
1754+ }
1755+
1756+ return builder.makeTryTable (body, catchTags, catchDests, catchRefs);
1757+ }
1758+
16911759Expression* TranslateToFuzzReader::makeBreak (Type type) {
16921760 if (funcContext->breakableStack .empty ()) {
16931761 return makeTrivial (type);
0 commit comments