Skip to content

Commit 0719fc8

Browse files
author
Zoltan Herczeg
committed
Add support for function references proposal
Support named references for globals, locals, tables, elems Support named references for call_ref, ref_null Extend Var variables with an optional type field
1 parent 6d4abfd commit 0719fc8

Some content is hidden

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

55 files changed

+1823
-551
lines changed

include/wabt/binary-reader-logging.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
181181
Result OnCatchExpr(Index tag_index) override;
182182
Result OnCatchAllExpr() override;
183183
Result OnCallIndirectExpr(Index sig_index, Index table_index) override;
184-
Result OnCallRefExpr() override;
184+
Result OnCallRefExpr(Type sig_type) override;
185185
Result OnCompareExpr(Opcode opcode) override;
186186
Result OnConvertExpr(Opcode opcode) override;
187187
Result OnDelegateExpr(Index depth) override;

include/wabt/binary-reader-nop.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
250250
Result OnCallIndirectExpr(Index sig_index, Index table_index) override {
251251
return Result::Ok;
252252
}
253-
Result OnCallRefExpr() override { return Result::Ok; }
253+
Result OnCallRefExpr(Type sig_type) override { return Result::Ok; }
254254
Result OnCatchExpr(Index tag_index) override { return Result::Ok; }
255255
Result OnCatchAllExpr() override { return Result::Ok; }
256256
Result OnCompareExpr(Opcode opcode) override { return Result::Ok; }

include/wabt/binary-reader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ class BinaryReaderDelegate {
255255
Index default_target_depth) = 0;
256256
virtual Result OnCallExpr(Index func_index) = 0;
257257
virtual Result OnCallIndirectExpr(Index sig_index, Index table_index) = 0;
258-
virtual Result OnCallRefExpr() = 0;
258+
virtual Result OnCallRefExpr(Type sig_type) = 0;
259259
virtual Result OnCatchExpr(Index tag_index) = 0;
260260
virtual Result OnCatchAllExpr() = 0;
261261
virtual Result OnCompareExpr(Opcode opcode) = 0;

include/wabt/interp/interp-inl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ 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) {}
45+
: ExternType(ExternKind::Func), params(params), results(results), func_types(nullptr) {}
4646

4747
//// TableType ////
4848
// static

include/wabt/interp/interp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ struct FuncType : ExternType {
184184

185185
ValueTypes params;
186186
ValueTypes results;
187+
// When params or results contain references, the referenced
188+
// types are also needed for type equality comparisons.
189+
// An example for these comparisons is import validation.
190+
std::vector<FuncType>* func_types;
187191
};
188192

189193
struct TableType : ExternType {

include/wabt/ir.h

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,43 @@ namespace wabt {
3636

3737
struct Module;
3838

39-
enum class VarType {
39+
// VarType (16 bit) and the opt_type_ (16 bit)
40+
// fields of Var forms a 32 bit field.
41+
enum class VarType : uint16_t {
4042
Index,
4143
Name,
4244
};
4345

4446
struct Var {
47+
// Var can represent variables or types.
48+
49+
// Represent a variable:
50+
// has_opt_type() is false
51+
// Only used by wast-parser
52+
53+
// Represent a type:
54+
// has_opt_type() is true, is_index() is true
55+
// type can be get by to_type()
56+
// Binary reader only constructs this variant
57+
58+
// Represent both a variable and a type:
59+
// has_opt_type() is true, is_name() is true
60+
// A reference, which index is unknown
61+
// Only used by wast-parser
62+
4563
explicit Var();
4664
explicit Var(Index index, const Location& loc);
4765
explicit Var(std::string_view name, const Location& loc);
66+
explicit Var(Type type, const Location& loc);
4867
Var(Var&&);
4968
Var(const Var&);
5069
Var& operator=(const Var&);
5170
Var& operator=(Var&&);
5271
~Var();
5372

54-
VarType type() const { return type_; }
5573
bool is_index() const { return type_ == VarType::Index; }
5674
bool is_name() const { return type_ == VarType::Name; }
75+
bool has_opt_type() const { return opt_type_ < 0; }
5776

5877
Index index() const {
5978
assert(is_index());
@@ -63,17 +82,25 @@ struct Var {
6382
assert(is_name());
6483
return name_;
6584
}
85+
Type::Enum opt_type() const {
86+
assert(has_opt_type());
87+
return static_cast<Type::Enum>(opt_type_);
88+
}
6689

6790
void set_index(Index);
6891
void set_name(std::string&&);
6992
void set_name(std::string_view);
93+
void set_opt_type(Type::Enum);
94+
Type to_type() const;
7095

7196
Location loc;
7297

7398
private:
7499
void Destroy();
75100

76101
VarType type_;
102+
// Can be set to Type::Enum types, Type::Any represent no optional type.
103+
int16_t opt_type_;
77104
union {
78105
Index index_;
79106
std::string name_;
@@ -155,6 +182,7 @@ struct Const {
155182
}
156183
void set_funcref() { From<uintptr_t>(Type::FuncRef, 0); }
157184
void set_externref(uintptr_t x) { From(Type::ExternRef, x); }
185+
void set_extern(uintptr_t x) { From(Type(Type::ExternRef, Type::ReferenceNonNull), x); }
158186
void set_null(Type type) { From<uintptr_t>(type, kRefNullBits); }
159187

160188
bool is_expected_nan(int lane = 0) const {
@@ -537,10 +565,10 @@ using MemoryCopyExpr = MemoryBinaryExpr<ExprType::MemoryCopy>;
537565
template <ExprType TypeEnum>
538566
class RefTypeExpr : public ExprMixin<TypeEnum> {
539567
public:
540-
RefTypeExpr(Type type, const Location& loc = Location())
568+
RefTypeExpr(Var type, const Location& loc = Location())
541569
: ExprMixin<TypeEnum>(loc), type(type) {}
542570

543-
Type type;
571+
Var type;
544572
};
545573

546574
using RefNullExpr = RefTypeExpr<ExprType::RefNull>;
@@ -662,8 +690,8 @@ using MemoryInitExpr = MemoryVarExpr<ExprType::MemoryInit>;
662690

663691
class SelectExpr : public ExprMixin<ExprType::Select> {
664692
public:
665-
SelectExpr(TypeVector type, const Location& loc = Location())
666-
: ExprMixin<ExprType::Select>(loc), result_type(type) {}
693+
SelectExpr(const Location& loc = Location())
694+
: ExprMixin<ExprType::Select>(loc) {}
667695
TypeVector result_type;
668696
};
669697

@@ -727,9 +755,7 @@ class CallRefExpr : public ExprMixin<ExprType::CallRef> {
727755
explicit CallRefExpr(const Location& loc = Location())
728756
: ExprMixin<ExprType::CallRef>(loc) {}
729757

730-
// This field is setup only during Validate phase,
731-
// so keep that in mind when you use it.
732-
Var function_type_index;
758+
Var sig_type;
733759
};
734760

735761
template <ExprType TypeEnum>

include/wabt/leb128.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ void WriteS32Leb128(Stream* stream, T value, const char* desc) {
6363
size_t ReadU32Leb128(const uint8_t* p, const uint8_t* end, uint32_t* out_value);
6464
size_t ReadU64Leb128(const uint8_t* p, const uint8_t* end, uint64_t* out_value);
6565
size_t ReadS32Leb128(const uint8_t* p, const uint8_t* end, uint32_t* out_value);
66+
size_t ReadS33Leb128(const uint8_t* p, const uint8_t* end, uint64_t* out_value);
6667
size_t ReadS64Leb128(const uint8_t* p, const uint8_t* end, uint64_t* out_value);
6768

6869
} // namespace wabt

include/wabt/shared-validator.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct ValidateOptions {
4343
class SharedValidator {
4444
public:
4545
WABT_DISALLOW_COPY_AND_ASSIGN(SharedValidator);
46+
using FuncType = TypeChecker::FuncType;
4647
SharedValidator(Errors*, const ValidateOptions& options);
4748

4849
// TODO: Move into SharedValidator?
@@ -72,7 +73,6 @@ class SharedValidator {
7273
Index type_index);
7374
Result OnStructType(const Location&, Index field_count, TypeMut* fields);
7475
Result OnArrayType(const Location&, TypeMut field);
75-
Result EndTypeSection();
7676

7777
Result OnFunction(const Location&, Var sig_var);
7878
Result OnTable(const Location&, Type elem_type, const Limits&);
@@ -141,7 +141,7 @@ class SharedValidator {
141141
Result EndBrTable(const Location&);
142142
Result OnCall(const Location&, Var func_var);
143143
Result OnCallIndirect(const Location&, Var sig_var, Var table_var);
144-
Result OnCallRef(const Location&, Index* function_type_index);
144+
Result OnCallRef(const Location&, Var function_type_var);
145145
Result OnCatch(const Location&, Var tag_var, bool is_catch_all);
146146
Result OnCompare(const Location&, Opcode);
147147
Result OnConst(const Location&, Type);
@@ -178,7 +178,7 @@ class SharedValidator {
178178
Result OnNop(const Location&);
179179
Result OnRefFunc(const Location&, Var func_var);
180180
Result OnRefIsNull(const Location&);
181-
Result OnRefNull(const Location&, Type type);
181+
Result OnRefNull(const Location&, Var func_type_var);
182182
Result OnRethrow(const Location&, Var depth);
183183
Result OnReturnCall(const Location&, Var func_var);
184184
Result OnReturnCallIndirect(const Location&, Var sig_var, Var table_var);
@@ -221,18 +221,6 @@ class SharedValidator {
221221
Result OnUnreachable(const Location&);
222222

223223
private:
224-
struct FuncType {
225-
FuncType() = default;
226-
FuncType(const TypeVector& params,
227-
const TypeVector& results,
228-
Index type_index)
229-
: params(params), results(results), type_index(type_index) {}
230-
231-
TypeVector params;
232-
TypeVector results;
233-
Index type_index;
234-
};
235-
236224
struct StructType {
237225
StructType() = default;
238226
StructType(const TypeMutVector& fields) : fields(fields) {}
@@ -289,6 +277,11 @@ class SharedValidator {
289277
Index end;
290278
};
291279

280+
struct LocalReferenceMap {
281+
Type type;
282+
Index bit_index;
283+
};
284+
292285
bool ValidInitOpcode(Opcode opcode) const;
293286
Result CheckInstr(Opcode opcode, const Location& loc);
294287
Result CheckType(const Location&,
@@ -336,6 +329,10 @@ class SharedValidator {
336329

337330
TypeVector ToTypeVector(Index count, const Type* types);
338331

332+
void SaveLocalRefs();
333+
void RestoreLocalRefs(Result result);
334+
void IgnoreLocalRefs();
335+
339336
ValidateOptions options_;
340337
Errors* errors_;
341338
TypeChecker typechecker_; // TODO: Move into SharedValidator.
@@ -361,6 +358,8 @@ class SharedValidator {
361358
// Includes parameters, since this is only used for validating
362359
// local.{get,set,tee} instructions.
363360
std::vector<LocalDecl> locals_;
361+
std::map<Index, LocalReferenceMap> local_refs_map_;
362+
std::vector<bool> local_ref_is_set_;
364363

365364
std::set<std::string> export_names_; // Used to check for duplicates.
366365
std::set<Index> declared_funcs_; // TODO: optimize?

include/wabt/token.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ WABT_TOKEN(Module, "module")
5555
WABT_TOKEN(Mut, "mut")
5656
WABT_TOKEN(NanArithmetic, "nan:arithmetic")
5757
WABT_TOKEN(NanCanonical, "nan:canonical")
58+
WABT_TOKEN(Null, "null")
5859
WABT_TOKEN(Offset, "offset")
5960
WABT_TOKEN(Output, "output")
6061
WABT_TOKEN(PageSize, "pagesize")

include/wabt/type-checker.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <functional>
2121
#include <type_traits>
2222
#include <vector>
23+
#include <map>
2324

2425
#include "wabt/common.h"
2526
#include "wabt/feature.h"
@@ -31,6 +32,18 @@ class TypeChecker {
3132
public:
3233
using ErrorCallback = std::function<void(const char* msg)>;
3334

35+
struct FuncType {
36+
FuncType() = default;
37+
FuncType(const TypeVector& params,
38+
const TypeVector& results,
39+
Index type_index)
40+
: params(params), results(results), type_index(type_index) {}
41+
42+
TypeVector params;
43+
TypeVector results;
44+
Index type_index;
45+
};
46+
3447
struct Label {
3548
Label(LabelType,
3649
const TypeVector& param_types,
@@ -46,9 +59,11 @@ class TypeChecker {
4659
TypeVector result_types;
4760
size_t type_stack_limit;
4861
bool unreachable;
62+
std::vector<bool> local_ref_is_set_;
4963
};
5064

51-
explicit TypeChecker(const Features& features) : features_(features) {}
65+
explicit TypeChecker(const Features& features, std::map<Index, FuncType>& func_types)
66+
: features_(features), func_types_(func_types) {}
5267

5368
void set_error_callback(const ErrorCallback& error_callback) {
5469
error_callback_ = error_callback;
@@ -80,7 +95,7 @@ class TypeChecker {
8095
Result OnCallIndirect(const TypeVector& param_types,
8196
const TypeVector& result_types,
8297
const Limits& table_limits);
83-
Result OnIndexedFuncRef(Index* out_index);
98+
Result OnCallRef(Type);
8499
Result OnReturnCall(const TypeVector& param_types,
85100
const TypeVector& result_types);
86101
Result OnReturnCallIndirect(const TypeVector& param_types,
@@ -115,7 +130,7 @@ class TypeChecker {
115130
Result OnTableGrow(Type elem_type, const Limits& limits);
116131
Result OnTableSize(const Limits& limits);
117132
Result OnTableFill(Type elem_type, const Limits& limits);
118-
Result OnRefFuncExpr(Index func_type, bool force_generic_funcref);
133+
Result OnRefFuncExpr(Index func_type);
119134
Result OnRefNullExpr(Type type);
120135
Result OnRefIsNullExpr();
121136
Result OnRethrow(Index depth);
@@ -141,7 +156,7 @@ class TypeChecker {
141156
Result BeginInitExpr(Type type);
142157
Result EndInitExpr();
143158

144-
static Result CheckType(Type actual, Type expected);
159+
Result CheckType(Type actual, Type expected);
145160

146161
private:
147162
void WABT_PRINTF_FORMAT(2, 3) PrintError(const char* fmt, ...);
@@ -210,6 +225,7 @@ class TypeChecker {
210225
// to represent "any".
211226
TypeVector* br_table_sig_ = nullptr;
212227
Features features_;
228+
std::map<Index, FuncType>& func_types_;
213229
};
214230

215231
} // namespace wabt

0 commit comments

Comments
 (0)