Skip to content

Commit 89ef773

Browse files
authored
Make IndexedTypeNameGenerator more powerful (#4511)
Allow IndexedTypeNameGenerator to be configured with a custom prefix and also allow it to be parameterized with an explicit fallback generator. This allows multiple IndexedTypeNameGenerators to be composed together, for example.
1 parent 2651ffb commit 89ef773

File tree

4 files changed

+96
-38
lines changed

4 files changed

+96
-38
lines changed

src/tools/wasm-fuzz-types.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ void Fuzzer::printTypes() {
9595
TypeNames getNames(HeapType type) {
9696
Fatal() << "trying to print unknown heap type";
9797
}
98-
};
99-
IndexedTypeNameGenerator<FatalTypeNameGenerator> print(types);
98+
} fatalGenerator;
99+
IndexedTypeNameGenerator<FatalTypeNameGenerator> print(types, fatalGenerator);
100100
std::unordered_map<HeapType, size_t> seen;
101101
std::optional<RecGroup> currRecGroup;
102102
auto inRecGroup = [&]() { return currRecGroup && currRecGroup->size() > 1; };

src/wasm-type-printing.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,23 @@ struct DefaultTypeNameGenerator
6767
template<typename FallbackGenerator = DefaultTypeNameGenerator>
6868
struct IndexedTypeNameGenerator
6969
: TypeNameGeneratorBase<IndexedTypeNameGenerator<FallbackGenerator>> {
70-
FallbackGenerator fallback;
70+
DefaultTypeNameGenerator defaultGenerator;
71+
FallbackGenerator& fallback;
7172
std::unordered_map<HeapType, TypeNames> names;
72-
template<typename T> IndexedTypeNameGenerator(T& types) {
73+
74+
template<typename T>
75+
IndexedTypeNameGenerator(T& types,
76+
FallbackGenerator& fallback,
77+
const std::string& prefix = "")
78+
: fallback(fallback) {
7379
for (size_t i = 0; i < types.size(); ++i) {
74-
names.insert({types[i], {std::to_string(i), {}}});
80+
names.insert({types[i], {prefix + std::to_string(i), {}}});
7581
}
7682
}
83+
template<typename T>
84+
IndexedTypeNameGenerator(T& types, const std::string& prefix = "")
85+
: IndexedTypeNameGenerator(types, defaultGenerator, prefix) {}
86+
7787
TypeNames getNames(HeapType type) {
7888
if (auto it = names.find(type); it != names.end()) {
7989
return it->second;

test/example/type-builder-nominal.cpp

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,31 +30,35 @@ void test_builder() {
3030
Struct struct_({Field(refNullArray, Immutable), Field(rttArray, Mutable)});
3131
Array array(Field(refNullExt, Mutable));
3232

33-
IndexedTypeNameGenerator print(builder);
34-
35-
std::cout << "Before setting heap types:\n";
36-
std::cout << "$sig => " << print(builder[0]) << "\n";
37-
std::cout << "$struct => " << print(builder[1]) << "\n";
38-
std::cout << "$array => " << print(builder[2]) << "\n";
39-
std::cout << "(ref $sig) => " << print(refSig) << "\n";
40-
std::cout << "(ref $struct) => " << print(refStruct) << "\n";
41-
std::cout << "(ref $array) => " << print(refArray) << "\n";
42-
std::cout << "(ref null $array) => " << print(refNullArray) << "\n";
43-
std::cout << "(rtt 0 $array) => " << print(rttArray) << "\n\n";
33+
{
34+
IndexedTypeNameGenerator print(builder);
35+
std::cout << "Before setting heap types:\n";
36+
std::cout << "$sig => " << print(builder[0]) << "\n";
37+
std::cout << "$struct => " << print(builder[1]) << "\n";
38+
std::cout << "$array => " << print(builder[2]) << "\n";
39+
std::cout << "(ref $sig) => " << print(refSig) << "\n";
40+
std::cout << "(ref $struct) => " << print(refStruct) << "\n";
41+
std::cout << "(ref $array) => " << print(refArray) << "\n";
42+
std::cout << "(ref null $array) => " << print(refNullArray) << "\n";
43+
std::cout << "(rtt 0 $array) => " << print(rttArray) << "\n\n";
44+
}
4445

4546
builder[0] = sig;
4647
builder[1] = struct_;
4748
builder[2] = array;
4849

49-
std::cout << "After setting heap types:\n";
50-
std::cout << "$sig => " << print(builder[0]) << "\n";
51-
std::cout << "$struct => " << print(builder[1]) << "\n";
52-
std::cout << "$array => " << print(builder[2]) << "\n";
53-
std::cout << "(ref $sig) => " << print(refSig) << "\n";
54-
std::cout << "(ref $struct) => " << print(refStruct) << "\n";
55-
std::cout << "(ref $array) => " << print(refArray) << "\n";
56-
std::cout << "(ref null $array) => " << print(refNullArray) << "\n";
57-
std::cout << "(rtt 0 $array) => " << print(rttArray) << "\n\n";
50+
{
51+
IndexedTypeNameGenerator print(builder);
52+
std::cout << "After setting heap types:\n";
53+
std::cout << "$sig => " << print(builder[0]) << "\n";
54+
std::cout << "$struct => " << print(builder[1]) << "\n";
55+
std::cout << "$array => " << print(builder[2]) << "\n";
56+
std::cout << "(ref $sig) => " << print(refSig) << "\n";
57+
std::cout << "(ref $struct) => " << print(refStruct) << "\n";
58+
std::cout << "(ref $array) => " << print(refArray) << "\n";
59+
std::cout << "(ref null $array) => " << print(refNullArray) << "\n";
60+
std::cout << "(rtt 0 $array) => " << print(rttArray) << "\n\n";
61+
}
5862

5963
std::vector<HeapType> built = *builder.build();
6064

@@ -64,17 +68,18 @@ void test_builder() {
6468
Type newRefNullArray = Type(built[2], Nullable);
6569
Type newRttArray = Type(Rtt(0, built[2]));
6670

67-
print = IndexedTypeNameGenerator(built);
68-
69-
std::cout << "After building types:\n";
70-
std::cout << "$sig => " << print(built[0]) << "\n";
71-
std::cout << "$struct => " << print(built[1]) << "\n";
72-
std::cout << "$array => " << print(built[2]) << "\n";
73-
std::cout << "(ref $sig) => " << print(newRefSig) << "\n";
74-
std::cout << "(ref $struct) => " << print(newRefStruct) << "\n";
75-
std::cout << "(ref $array) => " << print(newRefArray) << "\n";
76-
std::cout << "(ref null $array) => " << print(newRefNullArray) << "\n";
77-
std::cout << "(rtt 0 $array) => " << print(newRttArray) << "\n\n";
71+
{
72+
IndexedTypeNameGenerator print(built);
73+
std::cout << "After building types:\n";
74+
std::cout << "$sig => " << print(built[0]) << "\n";
75+
std::cout << "$struct => " << print(built[1]) << "\n";
76+
std::cout << "$array => " << print(built[2]) << "\n";
77+
std::cout << "(ref $sig) => " << print(newRefSig) << "\n";
78+
std::cout << "(ref $struct) => " << print(newRefStruct) << "\n";
79+
std::cout << "(ref $array) => " << print(newRefArray) << "\n";
80+
std::cout << "(ref null $array) => " << print(newRefNullArray) << "\n";
81+
std::cout << "(rtt 0 $array) => " << print(newRttArray) << "\n\n";
82+
}
7883
}
7984

8085
// Check that the builder works when there are duplicate definitions

test/gtest/type-builder.cpp

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
#include <gtest/gtest.h>
2-
#include <wasm-type.h>
1+
#include "wasm-type-printing.h"
2+
#include "wasm-type.h"
3+
#include "gtest/gtest.h"
34

45
using namespace wasm;
56

@@ -101,6 +102,48 @@ TEST_F(TypeTest, TypeIterator) {
101102
EXPECT_EQ(reverse, tuple.rend());
102103
}
103104

105+
TEST_F(TypeTest, IndexedTypePrinter) {
106+
TypeBuilder builder(4);
107+
108+
Type refStructA = builder.getTempRefType(builder[0], Nullable);
109+
Type refStructB = builder.getTempRefType(builder[1], Nullable);
110+
Type refArrayA = builder.getTempRefType(builder[2], Nullable);
111+
Type refArrayB = builder.getTempRefType(builder[3], Nullable);
112+
builder[0] = Struct({Field(refArrayB, Immutable)});
113+
builder[1] = Struct({Field(refStructA, Immutable)});
114+
builder[2] = Array(Field(refStructB, Immutable));
115+
builder[3] = Array(Field(refArrayA, Immutable));
116+
117+
auto result = builder.build();
118+
ASSERT_TRUE(result);
119+
auto built = *result;
120+
121+
std::vector<HeapType> structs{built[0], built[1]};
122+
std::vector<HeapType> arrays{built[2], built[3]};
123+
124+
// Check that IndexedTypePrinters configured with fallbacks work correctly.
125+
using ArrayPrinter = IndexedTypeNameGenerator<DefaultTypeNameGenerator>;
126+
ArrayPrinter printArrays(arrays, "array");
127+
using StructPrinter = IndexedTypeNameGenerator<ArrayPrinter>;
128+
StructPrinter print(structs, printArrays, "struct");
129+
130+
std::stringstream stream;
131+
stream << print(built[0]);
132+
EXPECT_EQ(stream.str(), "(struct (field (ref null $array1)))");
133+
134+
stream.str("");
135+
stream << print(built[1]);
136+
EXPECT_EQ(stream.str(), "(struct (field (ref null $struct0)))");
137+
138+
stream.str("");
139+
stream << print(built[2]);
140+
EXPECT_EQ(stream.str(), "(array (ref null $struct1))");
141+
142+
stream.str("");
143+
stream << print(built[3]);
144+
EXPECT_EQ(stream.str(), "(array (ref null $array0))");
145+
}
146+
104147
TEST_F(EquirecursiveTest, Basics) {
105148
// (type $sig (func (param (ref $struct)) (result (ref $array) i32)))
106149
// (type $struct (struct (field (ref null $array) (mut rtt 0 $array))))

0 commit comments

Comments
 (0)