Skip to content

Commit 68fe37e

Browse files
author
Zoltan Herczeg
committed
Implement GC basics
1 parent 5ee89f2 commit 68fe37e

30 files changed

+2550
-1609
lines changed

include/wabt/binary-reader-logging.h

Lines changed: 10 additions & 2 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 OnRecursiveRange(Index start_index, Index type_count) override;
4748
Result OnFuncType(Index index,
49+
GCTypeExtension* gc_ext,
4850
Index param_count,
4951
Type* param_types,
5052
Index result_count,
5153
Type* result_types) override;
52-
Result OnStructType(Index index, Index field_count, TypeMut* fields) override;
53-
Result OnArrayType(Index index, TypeMut field) override;
54+
Result OnStructType(Index index,
55+
GCTypeExtension* gc_ext,
56+
Index field_count,
57+
TypeMut* fields) override;
58+
Result OnArrayType(Index index,
59+
GCTypeExtension* gc_ext,
60+
TypeMut field) 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 LogGCInfo(GCTypeExtension* gc_ext);
435443
void LogField(TypeMut field);
436444

437445
Stream* stream_;

include/wabt/binary-reader-nop.h

Lines changed: 10 additions & 1 deletion
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 OnRecursiveRange(Index start_index, Index type_count) override {
49+
return Result::Ok;
50+
}
4851
Result OnTypeCount(Index count) override { return Result::Ok; }
4952
Result OnFuncType(Index index,
53+
GCTypeExtension* gc_ext,
5054
Index param_count,
5155
Type* param_types,
5256
Index result_count,
5357
Type* result_types) override {
5458
return Result::Ok;
5559
}
5660
Result OnStructType(Index index,
61+
GCTypeExtension* gc_ext,
5762
Index field_count,
5863
TypeMut* fields) override {
5964
return Result::Ok;
6065
}
61-
Result OnArrayType(Index index, TypeMut field) override { return Result::Ok; }
66+
Result OnArrayType(Index index,
67+
GCTypeExtension* gc_ext,
68+
TypeMut field) override {
69+
return Result::Ok;
70+
}
6271
Result EndTypeSection() override { return Result::Ok; }
6372

6473
/* Import section */

include/wabt/binary-reader.h

Lines changed: 14 additions & 2 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+
// Garbage Collector specific type information
63+
struct GCTypeExtension {
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;
@@ -99,15 +106,20 @@ class BinaryReaderDelegate {
99106
/* Type section */
100107
virtual Result BeginTypeSection(Offset size) = 0;
101108
virtual Result OnTypeCount(Index count) = 0;
109+
virtual Result OnRecursiveRange(Index start_index, Index type_count) = 0;
102110
virtual Result OnFuncType(Index index,
111+
GCTypeExtension* gc_ext,
103112
Index param_count,
104113
Type* param_types,
105114
Index result_count,
106115
Type* result_types) = 0;
107116
virtual Result OnStructType(Index index,
117+
GCTypeExtension* gc_ext,
108118
Index field_count,
109119
TypeMut* fields) = 0;
110-
virtual Result OnArrayType(Index index, TypeMut field) = 0;
120+
virtual Result OnArrayType(Index index,
121+
GCTypeExtension* gc_ext,
122+
TypeMut field) = 0;
111123
virtual Result EndTypeSection() = 0;
112124

113125
/* Import section */

include/wabt/interp/interp-inl.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ 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), kind(FuncType::TypeKind::Func), params(params), results(results), func_types(nullptr) {}
46+
47+
inline FuncType::FuncType(TypeKind kind, ValueTypes params, ValueTypes results)
48+
: ExternType(ExternKind::Func), kind(kind), params(params), results(results), func_types(nullptr) {
49+
assert((kind == TypeKind::Struct || kind == TypeKind::Array) && params.size() == results.size());
50+
}
4651

4752
//// TableType ////
4853
// static

include/wabt/interp/interp.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,29 @@ 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+
static const Type::Enum Mutable = Type::I32;
188+
static const Type::Enum Immutable = Type::I64;
189+
181190
explicit FuncType(ValueTypes params, ValueTypes results);
191+
explicit FuncType(TypeKind kind, ValueTypes params, ValueTypes results);
182192

183193
std::unique_ptr<ExternType> Clone() const override;
184194

185195
friend Result Match(const FuncType& expected,
186196
const FuncType& actual,
187197
std::string* out_msg);
188198

199+
// To simplify the implementation, FuncType may also represent
200+
// Struct and Array types. To do this, the mutability is stored
201+
// in results, which must have the same size as params.
202+
// This implementation might change in the future.
203+
TypeKind kind;
189204
ValueTypes params;
190205
ValueTypes results;
191206
// When params or results contain references, the referenced

include/wabt/ir.h

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

300+
struct TypeEntryGCTypeExtension {
301+
TypeEntryGCTypeExtension(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 format allows more subtypes, although
308+
// the validator limits the list to maximum 1 value.
309+
// Furthermore the text parser must allow future
310+
// references although the validator also disallows this.
311+
std::vector<Var> sub_types;
312+
};
313+
300314
class TypeEntry {
301315
public:
302316
WABT_DISALLOW_COPY_AND_ASSIGN(TypeEntry);
@@ -307,12 +321,17 @@ class TypeEntry {
307321

308322
Location loc;
309323
std::string name;
324+
TypeEntryGCTypeExtension gc_ext;
310325

311326
protected:
312327
explicit TypeEntry(TypeEntryKind kind,
328+
bool is_final_sub_type,
313329
std::string_view name = std::string_view(),
314330
const Location& loc = Location())
315-
: loc(loc), name(name), kind_(kind) {}
331+
: loc(loc),
332+
name(name),
333+
gc_ext(is_final_sub_type),
334+
kind_(kind) {}
316335

317336
TypeEntryKind kind_;
318337
};
@@ -323,8 +342,8 @@ class FuncType : public TypeEntry {
323342
return entry->kind() == TypeEntryKind::Func;
324343
}
325344

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

329348
Index GetNumParams() const { return sig.GetNumParams(); }
330349
Index GetNumResults() const { return sig.GetNumResults(); }
@@ -353,8 +372,8 @@ class StructType : public TypeEntry {
353372
return entry->kind() == TypeEntryKind::Struct;
354373
}
355374

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

359378
std::vector<Field> fields;
360379
};
@@ -365,12 +384,17 @@ class ArrayType : public TypeEntry {
365384
return entry->kind() == TypeEntryKind::Array;
366385
}
367386

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

371390
Field field;
372391
};
373392

393+
struct RecursiveRange {
394+
Index start_index;
395+
Index type_count;
396+
};
397+
374398
struct FuncDeclaration {
375399
Index GetNumParams() const { return sig.GetNumParams(); }
376400
Index GetNumResults() const { return sig.GetNumResults(); }
@@ -1319,6 +1343,8 @@ struct Module {
13191343
std::vector<Import*> imports;
13201344
std::vector<Export*> exports;
13211345
std::vector<TypeEntry*> types;
1346+
// Ordered list of recursive ranges. Needed for binary search.
1347+
std::vector<RecursiveRange> recursive_ranges;
13221348
std::vector<Table*> tables;
13231349
std::vector<ElemSegment*> elem_segments;
13241350
std::vector<Memory*> memories;

include/wabt/shared-validator.h

Lines changed: 19 additions & 22 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 {
@@ -43,7 +41,11 @@ struct ValidateOptions {
4341
class SharedValidator {
4442
public:
4543
WABT_DISALLOW_COPY_AND_ASSIGN(SharedValidator);
44+
using TypeEntry = TypeChecker::TypeEntry;
4645
using FuncType = TypeChecker::FuncType;
46+
using StructType = TypeChecker::StructType;
47+
using ArrayType = TypeChecker::ArrayType;
48+
using RecursiveRange = TypeChecker::RecursiveRange;
4749
SharedValidator(Errors*, const ValidateOptions& options);
4850

4951
// TODO: Move into SharedValidator?
@@ -65,14 +67,21 @@ class SharedValidator {
6567

6668
Result EndModule();
6769

70+
Result OnRecursiveRange(Index start_index, Index type_count);
6871
Result OnFuncType(const Location&,
72+
GCTypeExtension* gc_ext,
6973
Index param_count,
7074
const Type* param_types,
7175
Index result_count,
7276
const Type* result_types,
7377
Index type_index);
74-
Result OnStructType(const Location&, Index field_count, TypeMut* fields);
75-
Result OnArrayType(const Location&, TypeMut field);
78+
Result OnStructType(const Location&,
79+
GCTypeExtension* gc_ext,
80+
Index field_count,
81+
TypeMut* fields);
82+
Result OnArrayType(const Location&,
83+
GCTypeExtension* gc_ext,
84+
TypeMut field);
7685

7786
Result OnFunction(const Location&, Var sig_var);
7887
Result OnTable(const Location&, Type elem_type, const Limits&, bool, bool);
@@ -225,20 +234,6 @@ class SharedValidator {
225234
Result OnUnreachable(const Location&);
226235

227236
private:
228-
struct StructType {
229-
StructType() = default;
230-
StructType(const TypeMutVector& fields) : fields(fields) {}
231-
232-
TypeMutVector fields;
233-
};
234-
235-
struct ArrayType {
236-
ArrayType() = default;
237-
ArrayType(TypeMut field) : field(field) {}
238-
239-
TypeMut field;
240-
};
241-
242237
struct TableType {
243238
TableType() = default;
244239
TableType(Type element, Limits limits) : element(element), limits(limits) {}
@@ -293,6 +288,11 @@ class SharedValidator {
293288
Type expected,
294289
const char* desc);
295290
Result CheckReferenceType(const Location&, Type type, const char* desc);
291+
Result CheckRecursiveReferenceType(const Location&,
292+
Type type,
293+
Index max_index,
294+
const char* desc);
295+
Result CheckGCInfo(const Location&, GCTypeExtension* gc_ext);
296296
Result CheckLimits(const Location&,
297297
const Limits&,
298298
uint64_t absolute_max,
@@ -344,10 +344,7 @@ class SharedValidator {
344344
Location expr_loc_ = Location(kInvalidOffset);
345345
bool in_init_expr_ = false;
346346

347-
Index num_types_ = 0;
348-
std::map<Index, FuncType> func_types_;
349-
std::map<Index, StructType> struct_types_;
350-
std::map<Index, ArrayType> array_types_;
347+
TypeChecker::TypeFields type_fields_;
351348

352349
std::vector<FuncType> funcs_; // Includes imported and defined.
353350
std::vector<TableType> tables_; // Includes imported and defined.

include/wabt/token.def

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
/* Tokens with no additional data (i.e. bare). */
2222
WABT_TOKEN(Invalid, "Invalid")
2323
WABT_TOKEN(After, "after")
24-
WABT_TOKEN(Array, "array")
2524
WABT_TOKEN(AssertException, "assert_exception")
2625
WABT_TOKEN(AssertExhaustion, "assert_exhaustion")
2726
WABT_TOKEN(AssertInvalid, "assert_invalid")
@@ -42,6 +41,7 @@ WABT_TOKEN(Eof, "EOF")
4241
WABT_TOKEN(Tag, "tag")
4342
WABT_TOKEN(Export, "export")
4443
WABT_TOKEN(Field, "field")
44+
WABT_TOKEN(Final, "final")
4545
WABT_TOKEN(Function, "function")
4646
WABT_TOKEN(Get, "get")
4747
WABT_TOKEN(Global, "global")
@@ -62,12 +62,13 @@ WABT_TOKEN(PageSize, "pagesize")
6262
WABT_TOKEN(Param, "param")
6363
WABT_TOKEN(Ref, "ref")
6464
WABT_TOKEN(Quote, "quote")
65+
WABT_TOKEN(Rec, "rec")
6566
WABT_TOKEN(Register, "register")
6667
WABT_TOKEN(Result, "result")
6768
WABT_TOKEN(Rpar, ")")
6869
WABT_TOKEN(Shared, "shared")
6970
WABT_TOKEN(Start, "start")
70-
WABT_TOKEN(Struct, "struct")
71+
WABT_TOKEN(Sub, "sub")
7172
WABT_TOKEN(Table, "table")
7273
WABT_TOKEN(Then, "then")
7374
WABT_TOKEN(Type, "type")
@@ -182,8 +183,16 @@ WABT_TOKEN_FIRST(Type, ValueType)
182183
WABT_TOKEN_LAST(Type, ValueType)
183184

184185
/* Tokens with Type data, but are reference kinds. */
186+
WABT_TOKEN(Any, "any")
187+
WABT_TOKEN(Array, "array")
185188
WABT_TOKEN(Func, "func")
189+
WABT_TOKEN(Eq, "eq")
186190
WABT_TOKEN(Extern, "extern")
187191
WABT_TOKEN(Exn, "exn")
188-
WABT_TOKEN_FIRST(RefKind, Func)
189-
WABT_TOKEN_LAST(RefKind, Exn)
192+
WABT_TOKEN(I31, "i31")
193+
WABT_TOKEN(NoExtern, "noextern")
194+
WABT_TOKEN(NoFunc, "nofunc")
195+
WABT_TOKEN(None, "none")
196+
WABT_TOKEN(Struct, "struct")
197+
WABT_TOKEN_FIRST(RefKind, Any)
198+
WABT_TOKEN_LAST(RefKind, Struct)

0 commit comments

Comments
 (0)