@@ -546,6 +546,22 @@ void TranslateToFuzzReader::setupTables() {
546546 segment->setName (Names::getValidElementSegmentName (wasm, " elem$" ), false );
547547 wasm.addElementSegment (std::move (segment));
548548 }
549+
550+ // When EH is enabled, set up an exnref table.
551+ if (wasm.features .hasExceptionHandling ()) {
552+ Type exnref = Type (HeapType::exn, Nullable);
553+ Address initial = upTo (10 );
554+ Address max = oneIn (2 ) ? initial + upTo (4 ) : Memory::kUnlimitedSize ;
555+ auto tablePtr =
556+ builder.makeTable (Names::getValidTableName (wasm, " exnref_table" ),
557+ exnref,
558+ initial,
559+ max,
560+ Type::i32 ); // TODO: wasm64
561+ tablePtr->hasExplicitName = true ;
562+ table = wasm.addTable (std::move (tablePtr));
563+ exnrefTableName = table->name ;
564+ }
549565}
550566
551567void TranslateToFuzzReader::setupGlobals () {
@@ -1953,6 +1969,14 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
19531969 if (heapType.isBasic ()) {
19541970 options.add (FeatureSet::ReferenceTypes | FeatureSet::GC,
19551971 &Self::makeBasicRef);
1972+ if (type.isNullable () && funcContext) {
1973+ if (heapType == HeapType::func) {
1974+ options.add (FeatureSet::ReferenceTypes, &Self::makeTableGet);
1975+ }
1976+ if (heapType == HeapType::exn) {
1977+ options.add (FeatureSet::ExceptionHandling, &Self::makeTableGet);
1978+ }
1979+ }
19561980 } else {
19571981 options.add (FeatureSet::ReferenceTypes | FeatureSet::GC,
19581982 &Self::makeCompoundRef);
@@ -2000,6 +2024,7 @@ Expression* TranslateToFuzzReader::_makenone() {
20002024 &Self::makeGlobalSet)
20012025 .add (FeatureSet::BulkMemory, &Self::makeBulkMemory)
20022026 .add (FeatureSet::Atomics, &Self::makeAtomic)
2027+ .add (FeatureSet::ReferenceTypes, &Self::makeTableSet)
20032028 .add (FeatureSet::ExceptionHandling, &Self::makeTry)
20042029 .add (FeatureSet::ExceptionHandling, &Self::makeTryTable)
20052030 .add (FeatureSet::ExceptionHandling, &Self::makeImportThrowing)
@@ -4418,6 +4443,58 @@ Expression* TranslateToFuzzReader::makeBulkMemory(Type type) {
44184443 WASM_UNREACHABLE (" invalid value" );
44194444}
44204445
4446+ Expression* TranslateToFuzzReader::makeTableGet (Type type) {
4447+ // Emit a get from the funcref table (which always exists) or the exnref one
4448+ // (which might not, if EH is disabled).
4449+ auto makeTableGet = [&](Name tableName) {
4450+ auto * table = wasm.getTable (tableName);
4451+ // Usually emit in-bounds gets, to avoid trapping, but rarely allow
4452+ // anything.
4453+ Expression* index;
4454+ if (allowOOB && oneIn (10 )) {
4455+ index = make (table->addressType );
4456+ } else {
4457+ index = builder.makeConst (
4458+ Literal::makeFromInt32 (upTo (table->initial ), table->addressType ));
4459+ }
4460+ return builder.makeTableGet (tableName, index, table->type );
4461+ };
4462+ if (type.getHeapType () == HeapType::exn) {
4463+ return makeTableGet (exnrefTableName);
4464+ } else if (type.getHeapType () == HeapType::func) {
4465+ return makeTableGet (funcrefTableName);
4466+ } else {
4467+ WASM_UNREACHABLE (" bad TableGet type" );
4468+ }
4469+ }
4470+
4471+ Expression* TranslateToFuzzReader::makeTableSet (Type type) {
4472+ assert (type == Type::none);
4473+
4474+ // Emit a set to either the funcref table (which always exists) or the exnref
4475+ // one (which might not, if EH is disabled).
4476+ auto makeTableSet = [&](Name tableName) {
4477+ auto * table = wasm.getTable (tableName);
4478+ // Usually emit in-bounds sets, to avoid trapping, but rarely allow
4479+ // anything.
4480+ Expression* index;
4481+ if (allowOOB && oneIn (10 )) {
4482+ index = make (table->addressType );
4483+ } else {
4484+ index = builder.makeConst (
4485+ Literal::makeFromInt32 (upTo (table->initial ), table->addressType ));
4486+ }
4487+ auto * value = make (table->type );
4488+ return builder.makeTableSet (tableName, index, value);
4489+ };
4490+ if (exnrefTableName && oneIn (2 )) {
4491+ return makeTableSet (exnrefTableName);
4492+ } else {
4493+ assert (funcrefTableName);
4494+ return makeTableSet (funcrefTableName);
4495+ }
4496+ }
4497+
44214498Expression* TranslateToFuzzReader::makeRefIsNull (Type type) {
44224499 assert (type == Type::i32 );
44234500 assert (wasm.features .hasReferenceTypes ());
@@ -4922,8 +4999,8 @@ Type TranslateToFuzzReader::getSingleConcreteType() {
49224999 auto nullability = getNullability ();
49235000 return Type (heapType, nullability);
49245001 }
4925- // Skip (ref func), (ref extern), and (ref i31) for now
4926- // because there is no way to create them in globals. TODO.
5002+ // Skip (ref func|extern|i31|exn) because there is no way to create them in
5003+ // globals. TODO
49275004 using WeightedOption = FeatureOptions<Type>::WeightedOption;
49285005 return pick (FeatureOptions<Type>()
49295006 .add (FeatureSet::MVP,
@@ -4935,6 +5012,9 @@ Type TranslateToFuzzReader::getSingleConcreteType() {
49355012 .add (FeatureSet::ReferenceTypes,
49365013 Type (HeapType::func, Nullable),
49375014 Type (HeapType::ext, Nullable))
5015+ .add (FeatureSet::ExceptionHandling,
5016+ // Type(HeapType::exn, NonNullable),
5017+ Type (HeapType::exn, Nullable))
49385018 .add (FeatureSet::ReferenceTypes | FeatureSet::GC,
49395019 // Type(HeapType::func, NonNullable),
49405020 // Type(HeapType::ext, NonNullable),
0 commit comments