Skip to content

Commit c804a98

Browse files
author
Zoltan Herczeg
committed
Implement changes of function reference proposal
1 parent 5e81f6a commit c804a98

22 files changed

+288
-147
lines changed

include/wabt/ir.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace wabt {
3636

3737
struct Module;
3838

39-
enum class VarType {
39+
enum class VarType : uint16_t {
4040
Index,
4141
Name,
4242
};
@@ -45,6 +45,7 @@ struct Var {
4545
explicit Var();
4646
explicit Var(Index index, const Location& loc);
4747
explicit Var(std::string_view name, const Location& loc);
48+
explicit Var(Type type, const Location& loc);
4849
Var(Var&&);
4950
Var(const Var&);
5051
Var& operator=(const Var&);
@@ -54,6 +55,7 @@ struct Var {
5455
VarType type() const { return type_; }
5556
bool is_index() const { return type_ == VarType::Index; }
5657
bool is_name() const { return type_ == VarType::Name; }
58+
bool has_opt_type() const { return opt_type_ < 0; }
5759

5860
Index index() const {
5961
assert(is_index());
@@ -63,17 +65,24 @@ struct Var {
6365
assert(is_name());
6466
return name_;
6567
}
68+
Type::Enum opt_type() const {
69+
assert(has_opt_type());
70+
return static_cast<Type::Enum>(opt_type_);
71+
}
6672

6773
void set_index(Index);
6874
void set_name(std::string&&);
6975
void set_name(std::string_view);
76+
void set_opt_type(Type::Enum);
7077

7178
Location loc;
7279

7380
private:
7481
void Destroy();
7582

7683
VarType type_;
84+
// Can be set to Type::Enum types, 0 represent no optional type.
85+
int16_t opt_type_;
7786
union {
7887
Index index_;
7988
std::string name_;
@@ -544,10 +553,10 @@ using MemoryCopyExpr = MemoryBinaryExpr<ExprType::MemoryCopy>;
544553
template <ExprType TypeEnum>
545554
class RefTypeExpr : public ExprMixin<TypeEnum> {
546555
public:
547-
RefTypeExpr(Type type, const Location& loc = Location())
556+
RefTypeExpr(Var type, const Location& loc = Location())
548557
: ExprMixin<TypeEnum>(loc), type(type) {}
549558

550-
Type type;
559+
Var type;
551560
};
552561

553562
using RefNullExpr = RefTypeExpr<ExprType::RefNull>;
@@ -734,9 +743,7 @@ class CallRefExpr : public ExprMixin<ExprType::CallRef> {
734743
explicit CallRefExpr(const Location& loc = Location())
735744
: ExprMixin<ExprType::CallRef>(loc) {}
736745

737-
// This field is setup only during Validate phase,
738-
// so keep that in mind when you use it.
739-
Var function_type_index;
746+
Var function_type;
740747
};
741748

742749
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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class SharedValidator {
140140
Result EndBrTable(const Location&);
141141
Result OnCall(const Location&, Var func_var);
142142
Result OnCallIndirect(const Location&, Var sig_var, Var table_var);
143-
Result OnCallRef(const Location&, Index* function_type_index);
143+
Result OnCallRef(const Location&, Var function_type_var);
144144
Result OnCatch(const Location&, Var tag_var, bool is_catch_all);
145145
Result OnCompare(const Location&, Opcode);
146146
Result OnConst(const Location&, Type);
@@ -177,7 +177,7 @@ class SharedValidator {
177177
Result OnNop(const Location&);
178178
Result OnRefFunc(const Location&, Var func_var);
179179
Result OnRefIsNull(const Location&);
180-
Result OnRefNull(const Location&, Type type);
180+
Result OnRefNull(const Location&, Var func_type_var);
181181
Result OnRethrow(const Location&, Var depth);
182182
Result OnReturnCall(const Location&, Var func_var);
183183
Result OnReturnCallIndirect(const Location&, Var sig_var, Var table_var);

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.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class Type {
4646
FuncRef = -0x10, // 0x70
4747
ExternRef = -0x11, // 0x6f
4848
Reference = -0x15, // 0x6b
49+
HeapRef = -0x1c, // 0x64
50+
HeapNullRef = -0x1d, // 0x63
4951
Func = -0x20, // 0x60
5052
Struct = -0x21, // 0x5f
5153
Array = -0x22, // 0x5e
@@ -63,20 +65,24 @@ class Type {
6365
: enum_(static_cast<Enum>(code)), type_index_(kInvalidIndex) {}
6466
Type(Enum e) : enum_(e), type_index_(kInvalidIndex) {}
6567
Type(Enum e, Index type_index) : enum_(e), type_index_(type_index) {
66-
assert(e == Enum::Reference);
68+
assert(e == Enum::Reference || e == Enum::HeapRef ||
69+
e == Enum::HeapNullRef || type_index == kInvalidIndex);
6770
}
6871
constexpr operator Enum() const { return enum_; }
6972

70-
bool IsRef() const {
73+
bool IsNullableRef() const {
7174
return enum_ == Type::ExternRef || enum_ == Type::FuncRef ||
72-
enum_ == Type::Reference || enum_ == Type::ExnRef;
75+
enum_ == Type::Reference || enum_ == Type::ExnRef ||
76+
enum_ == Type::HeapNullRef;
7377
}
7478

75-
bool IsReferenceWithIndex() const { return enum_ == Type::Reference; }
79+
bool IsRef() const {
80+
return IsNullableRef() || enum_ == Type::HeapRef;
81+
}
7682

77-
bool IsNullableRef() const {
78-
// Currently all reftypes are nullable
79-
return IsRef();
83+
bool IsReferenceWithIndex() const {
84+
return enum_ == Type::Reference || enum_ == Type::HeapRef ||
85+
enum_ == Type::HeapNullRef;
8086
}
8187

8288
std::string GetName() const {
@@ -95,6 +101,8 @@ class Type {
95101
case Type::Any: return "any";
96102
case Type::ExternRef: return "externref";
97103
case Type::Reference:
104+
case Type::HeapRef:
105+
case Type::HeapNullRef:
98106
return StringPrintf("(ref %d)", type_index_);
99107
default:
100108
return StringPrintf("<type_index[%d]>", enum_);
@@ -132,7 +140,7 @@ class Type {
132140
}
133141

134142
Index GetReferenceIndex() const {
135-
assert(enum_ == Enum::Reference);
143+
assert(IsReferenceWithIndex());
136144
return type_index_;
137145
}
138146

@@ -151,6 +159,8 @@ class Type {
151159
case Type::ExnRef:
152160
case Type::ExternRef:
153161
case Type::Reference:
162+
case Type::HeapRef:
163+
case Type::HeapNullRef:
154164
return TypeVector(this, this + 1);
155165

156166
default:

include/wabt/wast-parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class WastParser {
138138
Result ParseValueTypeList(
139139
TypeVector* out_type_list,
140140
std::unordered_map<uint32_t, std::string>* type_names);
141-
Result ParseRefKind(Type* out_type);
141+
Result ParseRefKind(Var* out_type);
142142
Result ParseRefType(Type* out_type);
143143
bool ParseRefTypeOpt(Type* out_type);
144144
Result ParseQuotedText(std::string* text, bool check_utf8 = true);

src/binary-reader-ir.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1153,7 +1153,7 @@ Result BinaryReaderIR::OnRefFuncExpr(Index func_index) {
11531153

11541154
Result BinaryReaderIR::OnRefNullExpr(Type type) {
11551155
module_->features_used.exceptions |= (type == Type::ExnRef);
1156-
return AppendExpr(std::make_unique<RefNullExpr>(type));
1156+
return AppendExpr(std::make_unique<RefNullExpr>(Var(type, GetLocation())));
11571157
}
11581158

11591159
Result BinaryReaderIR::OnRefIsNullExpr() {

src/binary-reader-logging.cc

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -720,9 +720,19 @@ Result BinaryReaderLogging::OnGenericCustomSection(std::string_view name,
720720
}
721721

722722
#define DEFINE_TYPE(name) \
723-
Result BinaryReaderLogging::name(Type type) { \
724-
LOGF(#name "(%s)\n", type.GetName().c_str()); \
725-
return reader_->name(type); \
723+
Result BinaryReaderLogging::name(Type type) { \
724+
if (!type.IsReferenceWithIndex()) { \
725+
LOGF(#name "(%s)\n", type.GetName().c_str()); \
726+
} else { \
727+
LOGF(#name "(%s %" PRIindex ")\n", \
728+
type.GetName().c_str(), type.GetReferenceIndex()); \
729+
} \
730+
return reader_->name(type); \
731+
}
732+
733+
#define DEFINE_HEAP_TYPE(name) \
734+
Result BinaryReaderLogging::name(Type type, Index func_type_index) { \
735+
return reader_->name(type, func_type_index); \
726736
}
727737

728738
#define DEFINE_INDEX_DESC(name, desc) \

src/binary-reader.cc

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class BinaryReader {
113113
[[nodiscard]] Result ReadU32Leb128(uint32_t* out_value, const char* desc);
114114
[[nodiscard]] Result ReadU64Leb128(uint64_t* out_value, const char* desc);
115115
[[nodiscard]] Result ReadS32Leb128(uint32_t* out_value, const char* desc);
116+
[[nodiscard]] Result ReadS33Leb128(uint64_t* out_value, const char* desc);
116117
[[nodiscard]] Result ReadS64Leb128(uint64_t* out_value, const char* desc);
117118
[[nodiscard]] Result ReadType(Type* out_value, const char* desc);
118119
[[nodiscard]] Result ReadRefType(Type* out_value, const char* desc);
@@ -353,6 +354,15 @@ Result BinaryReader::ReadS32Leb128(uint32_t* out_value, const char* desc) {
353354
return Result::Ok;
354355
}
355356

357+
Result BinaryReader::ReadS33Leb128(uint64_t* out_value, const char* desc) {
358+
const uint8_t* p = state_.data + state_.offset;
359+
const uint8_t* end = state_.data + read_end_;
360+
size_t bytes_read = wabt::ReadS33Leb128(p, end, out_value);
361+
ERROR_UNLESS(bytes_read > 0, "unable to read i33 leb128: %s", desc);
362+
state_.offset += bytes_read;
363+
return Result::Ok;
364+
}
365+
356366
Result BinaryReader::ReadS64Leb128(uint64_t* out_value, const char* desc) {
357367
const uint8_t* p = state_.data + state_.offset;
358368
const uint8_t* end = state_.data + read_end_;
@@ -1913,8 +1923,16 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) {
19131923
}
19141924

19151925
case Opcode::RefNull: {
1926+
uint64_t heap_type;
19161927
Type type;
1917-
CHECK_RESULT(ReadRefType(&type, "ref.null type"));
1928+
CHECK_RESULT(ReadS33Leb128(&heap_type, "ref.null type"));
1929+
1930+
if (static_cast<int64_t>(heap_type) < 0) {
1931+
type = Type(static_cast<int32_t>(heap_type));
1932+
} else {
1933+
type = Type(Type::HeapNullRef, static_cast<Index>(heap_type));
1934+
}
1935+
19181936
CALLBACK(OnRefNullExpr, type);
19191937
CALLBACK(OnOpcodeType, type);
19201938
break;

src/binary-writer.cc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,16 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
10111011
}
10121012
case ExprType::RefNull: {
10131013
WriteOpcode(stream_, Opcode::RefNull);
1014-
WriteType(stream_, cast<RefNullExpr>(expr)->type, "ref.null type");
1014+
const RefNullExpr* ref_null_expr = cast<RefNullExpr>(expr);
1015+
Type type = ref_null_expr->type.opt_type();
1016+
1017+
if (type == Type::HeapNullRef) {
1018+
WriteType(stream_, type, "ref.null type");
1019+
break;
1020+
}
1021+
1022+
Index index = module_->GetFuncTypeIndex(ref_null_expr->type);
1023+
WriteU32Leb128WithReloc(index, "heap type index", RelocType::FuncIndexLEB);
10151024
break;
10161025
}
10171026
case ExprType::RefIsNull:

0 commit comments

Comments
 (0)