Skip to content

Commit 83b6311

Browse files
committed
Implement Garbage Collector type system
This patch supports parsing the new GC types - Abstract types - Recursive types - Composite types The patch also improves type comparison.
1 parent bad0cc8 commit 83b6311

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+3809
-1826
lines changed

include/wabt/binary-reader-logging.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,20 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
4444

4545
Result BeginTypeSection(Offset size) override;
4646
Result OnTypeCount(Index count) override;
47+
Result OnRecursiveType(Index first_type_index, Index type_count) override;
4748
Result OnFuncType(Index index,
4849
Index param_count,
4950
Type* param_types,
5051
Index result_count,
51-
Type* result_types) override;
52-
Result OnStructType(Index index, Index field_count, TypeMut* fields) override;
53-
Result OnArrayType(Index index, TypeMut field) override;
52+
Type* result_types,
53+
SupertypesInfo* supertypes) override;
54+
Result OnStructType(Index index,
55+
Index field_count,
56+
TypeMut* fields,
57+
SupertypesInfo* supertypes) override;
58+
Result OnArrayType(Index index,
59+
TypeMut field,
60+
SupertypesInfo* supertypes) override;
5461
Result EndTypeSection() override;
5562

5663
Result BeginImportSection(Offset size) override;
@@ -432,6 +439,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
432439
void LogType(Type type);
433440
void LogTypes(Index type_count, Type* types);
434441
void LogTypes(TypeVector& types);
442+
void LogSupertypesInfo(SupertypesInfo* supertypes);
435443
void LogField(TypeMut field);
436444

437445
Stream* stream_;

include/wabt/binary-reader-nop.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,29 @@ class BinaryReaderNop : public BinaryReaderDelegate {
4545

4646
/* Type section */
4747
Result BeginTypeSection(Offset size) override { return Result::Ok; }
48+
Result OnRecursiveType(Index first_type_index, Index type_count) override {
49+
return Result::Ok;
50+
}
4851
Result OnTypeCount(Index count) override { return Result::Ok; }
4952
Result OnFuncType(Index index,
5053
Index param_count,
5154
Type* param_types,
5255
Index result_count,
53-
Type* result_types) override {
56+
Type* result_types,
57+
SupertypesInfo* supertypes) override {
5458
return Result::Ok;
5559
}
5660
Result OnStructType(Index index,
5761
Index field_count,
58-
TypeMut* fields) override {
62+
TypeMut* fields,
63+
SupertypesInfo* supertypes) override {
64+
return Result::Ok;
65+
}
66+
Result OnArrayType(Index index,
67+
TypeMut field,
68+
SupertypesInfo* supertypes) override {
5969
return Result::Ok;
6070
}
61-
Result OnArrayType(Index index, TypeMut field) override { return Result::Ok; }
6271
Result EndTypeSection() override { return Result::Ok; }
6372

6473
/* Import section */

include/wabt/binary-reader.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,20 @@ struct ReadBinaryOptions {
5252
bool skip_function_bodies = false;
5353
};
5454

55-
// TODO: Move somewhere else?
55+
// TODO: Move both TypeMut and GCTypeInformation somewhere else?
5656
struct TypeMut {
5757
Type type;
5858
bool mutable_;
5959
};
6060
using TypeMutVector = std::vector<TypeMut>;
6161

62+
// Type extension introduced by the Garbage Collector proposal
63+
struct SupertypesInfo {
64+
bool is_final_sub_type;
65+
Index sub_type_count;
66+
Index* sub_types;
67+
};
68+
6269
struct CatchClause {
6370
CatchKind kind;
6471
Index tag;
@@ -104,15 +111,20 @@ class BinaryReaderDelegate {
104111
/* Type section */
105112
virtual Result BeginTypeSection(Offset size) = 0;
106113
virtual Result OnTypeCount(Index count) = 0;
114+
virtual Result OnRecursiveType(Index first_type_index, Index type_count) = 0;
107115
virtual Result OnFuncType(Index index,
108116
Index param_count,
109117
Type* param_types,
110118
Index result_count,
111-
Type* result_types) = 0;
119+
Type* result_types,
120+
SupertypesInfo* supertypes) = 0;
112121
virtual Result OnStructType(Index index,
113122
Index field_count,
114-
TypeMut* fields) = 0;
115-
virtual Result OnArrayType(Index index, TypeMut field) = 0;
123+
TypeMut* fields,
124+
SupertypesInfo* supertypes) = 0;
125+
virtual Result OnArrayType(Index index,
126+
TypeMut field,
127+
SupertypesInfo* supertypes) = 0;
116128
virtual Result EndTypeSection() = 0;
117129

118130
/* Import section */

include/wabt/interp/interp-inl.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,24 @@ inline bool FuncType::classof(const ExternType* type) {
4242
}
4343

4444
inline FuncType::FuncType(ValueTypes params, ValueTypes results)
45-
: ExternType(ExternKind::Func), params(params), results(results), func_types(nullptr) {}
45+
: ExternType(ExternKind::Func),
46+
params(params),
47+
results(results),
48+
func_types(nullptr) {}
49+
50+
inline FuncType::FuncType(TypeKind kind, ValueTypes params, ValueTypes results)
51+
: ExternType(ExternKind::Func),
52+
kind(kind),
53+
canonical_index(kInvalidIndex),
54+
canonical_sub_index(kInvalidIndex),
55+
is_final_sub_type(true),
56+
recursive_start(0),
57+
recursive_count(0),
58+
params(params),
59+
results(results),
60+
func_types(nullptr) {
61+
assert((kind == TypeKind::Struct || kind == TypeKind::Array) && params.size() == results.size());
62+
}
4663

4764
//// TableType ////
4865
// static

include/wabt/interp/interp.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,37 @@ struct FuncType : ExternType {
178178
static const ExternKind skind = ExternKind::Func;
179179
static bool classof(const ExternType* type);
180180

181+
enum class TypeKind {
182+
Func,
183+
Struct,
184+
Array,
185+
};
186+
187+
// To simplify the implementation, FuncType may also represent
188+
// Struct and Array types. In the latter case, the mutability
189+
// is stored in results array, which must have the same size
190+
// as params. This implementation might change in the future.
191+
static const Type::Enum Mutable = Type::I32;
192+
static const Type::Enum Immutable = Type::I64;
193+
181194
explicit FuncType(ValueTypes params, ValueTypes results);
195+
explicit FuncType(TypeKind kind, ValueTypes params, ValueTypes results);
182196

183197
std::unique_ptr<ExternType> Clone() const override;
184198

185199
friend Result Match(const FuncType& expected,
186200
const FuncType& actual,
187201
std::string* out_msg);
188202

203+
TypeKind kind = FuncType::TypeKind::Func;
204+
// These two are needed for fast dynamic type comparison.
205+
Index canonical_index = kInvalidIndex;
206+
Index canonical_sub_index = kInvalidIndex;
207+
// These three are needed for type equality comparisons
208+
// across different modules (import/export validation).
209+
bool is_final_sub_type = true;
210+
Index recursive_start = 0;
211+
Index recursive_count = 0;
189212
ValueTypes params;
190213
ValueTypes results;
191214
// When params or results contain references, the referenced

include/wabt/ir.h

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,19 @@ enum class TypeEntryKind {
297297
Array,
298298
};
299299

300+
struct TypeEntrySupertypesInfo {
301+
TypeEntrySupertypesInfo(bool is_final_sub_type)
302+
: is_final_sub_type(is_final_sub_type) {}
303+
304+
void InitSubTypes(Index* sub_type_list, Index sub_type_count);
305+
306+
bool is_final_sub_type;
307+
// The binary/text format allows any number of subtypes,
308+
// so parsers must handle them. The validator rejects
309+
// lists which size is greater than 1.
310+
VarVector sub_types;
311+
};
312+
300313
class TypeEntry {
301314
public:
302315
WABT_DISALLOW_COPY_AND_ASSIGN(TypeEntry);
@@ -307,12 +320,17 @@ class TypeEntry {
307320

308321
Location loc;
309322
std::string name;
323+
TypeEntrySupertypesInfo supertypes;
310324

311325
protected:
312326
explicit TypeEntry(TypeEntryKind kind,
327+
bool is_final_sub_type,
313328
std::string_view name = std::string_view(),
314329
const Location& loc = Location())
315-
: loc(loc), name(name), kind_(kind) {}
330+
: loc(loc),
331+
name(name),
332+
supertypes(is_final_sub_type),
333+
kind_(kind) {}
316334

317335
TypeEntryKind kind_;
318336
};
@@ -323,8 +341,8 @@ class FuncType : public TypeEntry {
323341
return entry->kind() == TypeEntryKind::Func;
324342
}
325343

326-
explicit FuncType(std::string_view name = std::string_view())
327-
: TypeEntry(TypeEntryKind::Func, name) {}
344+
explicit FuncType(bool is_final_sub_type, std::string_view name = std::string_view())
345+
: TypeEntry(TypeEntryKind::Func, is_final_sub_type, name) {}
328346

329347
Index GetNumParams() const { return sig.GetNumParams(); }
330348
Index GetNumResults() const { return sig.GetNumResults(); }
@@ -353,8 +371,8 @@ class StructType : public TypeEntry {
353371
return entry->kind() == TypeEntryKind::Struct;
354372
}
355373

356-
explicit StructType(std::string_view name = std::string_view())
357-
: TypeEntry(TypeEntryKind::Struct) {}
374+
explicit StructType(bool is_final_sub_type, std::string_view name = std::string_view())
375+
: TypeEntry(TypeEntryKind::Struct, is_final_sub_type, name) {}
358376

359377
std::vector<Field> fields;
360378
};
@@ -365,12 +383,19 @@ class ArrayType : public TypeEntry {
365383
return entry->kind() == TypeEntryKind::Array;
366384
}
367385

368-
explicit ArrayType(std::string_view name = std::string_view())
369-
: TypeEntry(TypeEntryKind::Array) {}
386+
explicit ArrayType(bool is_final_sub_type, std::string_view name = std::string_view())
387+
: TypeEntry(TypeEntryKind::Array, is_final_sub_type, name) {}
370388

371389
Field field;
372390
};
373391

392+
struct RecGroupRange {
393+
Index first_type_index;
394+
Index type_count;
395+
396+
Index EndTypeIndex() const { return first_type_index + type_count; }
397+
};
398+
374399
struct FuncDeclaration {
375400
Index GetNumParams() const { return sig.GetNumParams(); }
376401
Index GetNumResults() const { return sig.GetNumResults(); }
@@ -1319,6 +1344,8 @@ struct Module {
13191344
std::vector<Import*> imports;
13201345
std::vector<Export*> exports;
13211346
std::vector<TypeEntry*> types;
1347+
// Ordered list of recursive group type ranges.
1348+
std::vector<RecGroupRange> rec_group_ranges;
13221349
std::vector<Table*> tables;
13231350
std::vector<ElemSegment*> elem_segments;
13241351
std::vector<Memory*> memories;

include/wabt/shared-validator.h

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
#include "wabt/opcode.h"
3030
#include "wabt/type-checker.h"
3131

32-
#include "wabt/binary-reader.h" // For TypeMut.
33-
3432
namespace wabt {
3533

3634
struct ValidateOptions {
@@ -48,7 +46,11 @@ enum class TableImportStatus {
4846
class SharedValidator {
4947
public:
5048
WABT_DISALLOW_COPY_AND_ASSIGN(SharedValidator);
49+
using TypeEntry = TypeChecker::TypeEntry;
5150
using FuncType = TypeChecker::FuncType;
51+
using StructType = TypeChecker::StructType;
52+
using ArrayType = TypeChecker::ArrayType;
53+
using RecGroup = TypeChecker::RecGroup;
5254
SharedValidator(Errors*, const ValidateOptions& options);
5355

5456
// TODO: Move into SharedValidator?
@@ -68,16 +70,28 @@ class SharedValidator {
6870

6971
Index GetLocalCount() const;
7072

73+
// The canonical index of a type is the index of the first type,
74+
// which is equal to the original type. The canonical index is
75+
// always less or equal than type_index.
76+
Index GetCanonicalTypeIndex(Index type_index);
77+
7178
Result EndModule();
7279

80+
Result OnRecursiveType(Index first_type_index, Index type_count);
7381
Result OnFuncType(const Location&,
7482
Index param_count,
7583
const Type* param_types,
7684
Index result_count,
7785
const Type* result_types,
78-
Index type_index);
79-
Result OnStructType(const Location&, Index field_count, TypeMut* fields);
80-
Result OnArrayType(const Location&, TypeMut field);
86+
Index type_index,
87+
SupertypesInfo* supertypes);
88+
Result OnStructType(const Location&,
89+
Index field_count,
90+
TypeMut* fields,
91+
SupertypesInfo* supertypes);
92+
Result OnArrayType(const Location&,
93+
TypeMut field,
94+
SupertypesInfo* supertypes);
8195

8296
Result OnFunction(const Location&, Var sig_var);
8397
Result OnTable(const Location&, Type elem_type, const Limits&, TableImportStatus import_status, TableInitExprStatus init_provided);
@@ -230,20 +244,6 @@ class SharedValidator {
230244
Result OnUnreachable(const Location&);
231245

232246
private:
233-
struct StructType {
234-
StructType() = default;
235-
StructType(const TypeMutVector& fields) : fields(fields) {}
236-
237-
TypeMutVector fields;
238-
};
239-
240-
struct ArrayType {
241-
ArrayType() = default;
242-
ArrayType(TypeMut field) : field(field) {}
243-
244-
TypeMut field;
245-
};
246-
247247
struct TableType {
248248
TableType() = default;
249249
TableType(Type element, Limits limits) : element(element), limits(limits) {}
@@ -299,7 +299,11 @@ class SharedValidator {
299299
Type actual,
300300
Type expected,
301301
const char* desc);
302-
Result CheckReferenceType(const Location&, Type type, const char* desc);
302+
Result CheckReferenceType(const Location&,
303+
Type type,
304+
Index end_index,
305+
const char* desc);
306+
Result CheckSupertypes(const Location&, SupertypesInfo* supertypes);
303307
Result CheckLimits(const Location&,
304308
const Limits&,
305309
uint64_t absolute_max,
@@ -344,17 +348,16 @@ class SharedValidator {
344348
void RestoreLocalRefs(Result result);
345349
void IgnoreLocalRefs();
346350

351+
Index GetEndIndex();
352+
347353
ValidateOptions options_;
348354
Errors* errors_;
349355
TypeChecker typechecker_; // TODO: Move into SharedValidator.
350356
// Cached for access by OnTypecheckerError.
351357
Location expr_loc_ = Location(kInvalidOffset);
352358
bool in_init_expr_ = false;
353359

354-
Index num_types_ = 0;
355-
std::map<Index, FuncType> func_types_;
356-
std::map<Index, StructType> struct_types_;
357-
std::map<Index, ArrayType> array_types_;
360+
TypeChecker::TypeFields type_fields_;
358361

359362
std::vector<FuncType> funcs_; // Includes imported and defined.
360363
std::vector<TableType> tables_; // Includes imported and defined.
@@ -365,6 +368,9 @@ class SharedValidator {
365368
Index starts_ = 0;
366369
Index num_imported_globals_ = 0;
367370
Index data_segments_ = 0;
371+
Index last_rec_type_end_ = 0;
372+
// Recursive type checks may enter to infinite loop for invalid values.
373+
Result type_validation_result_ = Result::Ok;
368374

369375
// Includes parameters, since this is only used for validating
370376
// local.{get,set,tee} instructions.

0 commit comments

Comments
 (0)