Skip to content

Commit aa7da78

Browse files
author
Zoltan Herczeg
committed
Support table initializers
1 parent 89c1ffb commit aa7da78

Some content is hidden

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

41 files changed

+2080
-93
lines changed

include/wabt/binary-reader-logging.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,13 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
9696

9797
Result BeginTableSection(Offset size) override;
9898
Result OnTableCount(Index count) override;
99-
Result OnTable(Index index,
100-
Type elem_type,
101-
const Limits* elem_limits) override;
99+
Result BeginTable(Index index,
100+
Type elem_type,
101+
const Limits* elem_limits,
102+
bool has_init_expr) override;
103+
Result BeginTableInitExpr(Index index) override;
104+
Result EndTableInitExpr(Index index) override;
105+
Result EndTable(Index index) override;
102106
Result EndTableSection() override;
103107

104108
Result BeginMemorySection(Offset size) override;

include/wabt/binary-reader-nop.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,15 @@ class BinaryReaderNop : public BinaryReaderDelegate {
121121
/* Table section */
122122
Result BeginTableSection(Offset size) override { return Result::Ok; }
123123
Result OnTableCount(Index count) override { return Result::Ok; }
124-
Result OnTable(Index index,
125-
Type elem_type,
126-
const Limits* elem_limits) override {
124+
Result BeginTable(Index index,
125+
Type elem_type,
126+
const Limits* elem_limits,
127+
bool has_init_expr) override {
127128
return Result::Ok;
128129
}
130+
Result BeginTableInitExpr(Index index) override { return Result::Ok; }
131+
Result EndTableInitExpr(Index index) override { return Result::Ok; }
132+
Result EndTable(Index index) override { return Result::Ok; }
129133
Result EndTableSection() override { return Result::Ok; }
130134

131135
/* Memory section */

include/wabt/binary-reader.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,13 @@ class BinaryReaderDelegate {
156156
/* Table section */
157157
virtual Result BeginTableSection(Offset size) = 0;
158158
virtual Result OnTableCount(Index count) = 0;
159-
virtual Result OnTable(Index index,
160-
Type elem_type,
161-
const Limits* elem_limits) = 0;
159+
virtual Result BeginTable(Index index,
160+
Type elem_type,
161+
const Limits* elem_limits,
162+
bool has_init_expr) = 0;
163+
virtual Result BeginTableInitExpr(Index index) = 0;
164+
virtual Result EndTableInitExpr(Index index) = 0;
165+
virtual Result EndTable(Index index) = 0;
162166
virtual Result EndTableSection() = 0;
163167

164168
/* Memory section */

include/wabt/interp/interp-inl.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,16 @@ void RequireType(ValueType type) {
425425
inline bool TypesMatch(ValueType expected, ValueType actual) {
426426
// Currently there is no subtyping, so expected and actual must match
427427
// exactly. In the future this may be expanded.
428-
return expected == actual;
428+
if (expected == actual) {
429+
return true;
430+
}
431+
432+
if (actual == Type(Type::FuncRef, Type::ReferenceNonNull) &&
433+
expected == Type(Type::FuncRef, Type::ReferenceOrNull)) {
434+
return true;
435+
}
436+
437+
return false;
429438
}
430439

431440
//// Value ////
@@ -682,8 +691,8 @@ inline bool Table::classof(const Object* obj) {
682691
}
683692

684693
// static
685-
inline Table::Ptr Table::New(Store& store, TableType type) {
686-
return store.Alloc<Table>(store, type);
694+
inline Table::Ptr Table::New(Store& store, TableType type, Ref init_ref) {
695+
return store.Alloc<Table>(store, type, init_ref);
687696
}
688697

689698
inline const ExternType& Table::extern_type() {

include/wabt/interp/interp.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ struct FuncDesc {
330330

331331
struct TableDesc {
332332
TableType type;
333+
FuncDesc init_func;
333334
};
334335

335336
struct MemoryDesc {
@@ -814,7 +815,7 @@ class Table : public Extern {
814815
static const char* GetTypeName() { return "Table"; }
815816
using Ptr = RefPtr<Table>;
816817

817-
static Table::Ptr New(Store&, TableType);
818+
static Table::Ptr New(Store&, TableType, Ref);
818819

819820
Result Match(Store&, const ImportType&, Trap::Ptr* out_trap) override;
820821

@@ -846,7 +847,7 @@ class Table : public Extern {
846847

847848
private:
848849
friend Store;
849-
explicit Table(Store&, TableType);
850+
explicit Table(Store&, TableType, Ref);
850851
void Mark(Store&) override;
851852

852853
TableType type_;

include/wabt/ir.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,13 +985,14 @@ struct Table {
985985
std::string name;
986986
Limits elem_limits;
987987
Type elem_type;
988+
ExprList init_expr;
988989
};
989990

990991
using ExprListVector = std::vector<ExprList>;
991992

992993
struct ElemSegment {
993994
explicit ElemSegment(std::string_view name) : name(name) {}
994-
uint8_t GetFlags(const Module*) const;
995+
uint8_t GetFlags(const Module*, bool) const;
995996

996997
SegmentKind kind = SegmentKind::Active;
997998
std::string name;

include/wabt/shared-validator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class SharedValidator {
7676
Result EndTypeSection();
7777

7878
Result OnFunction(const Location&, Var sig_var);
79-
Result OnTable(const Location&, Type elem_type, const Limits&);
79+
Result OnTable(const Location&, Type elem_type, const Limits&, bool, bool);
8080
Result OnMemory(const Location&, const Limits&, uint32_t page_size);
8181
Result OnGlobalImport(const Location&, Type type, bool mutable_);
8282
Result OnGlobal(const Location&, Type type, bool mutable_);

src/apply-names.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class NameApplier : public ExprVisitor::DelegateNop {
102102
Result VisitGlobal(Global* global);
103103
Result VisitTag(Tag* tag);
104104
Result VisitExport(Index export_index, Export* export_);
105+
Result VisitTable(Table* table);
105106
Result VisitElemSegment(Index elem_segment_index, ElemSegment* segment);
106107
Result VisitDataSegment(Index data_segment_index, DataSegment* segment);
107108
Result VisitStart(Var* start_var);
@@ -559,6 +560,11 @@ Result NameApplier::VisitExport(Index export_index, Export* export_) {
559560
return Result::Ok;
560561
}
561562

563+
Result NameApplier::VisitTable(Table* table) {
564+
CHECK_RESULT(visitor_.VisitExprList(table->init_expr));
565+
return Result::Ok;
566+
}
567+
562568
Result NameApplier::VisitElemSegment(Index elem_segment_index,
563569
ElemSegment* segment) {
564570
CHECK_RESULT(UseNameForTableVar(&segment->table_var));
@@ -594,6 +600,8 @@ Result NameApplier::VisitModule(Module* module) {
594600
CHECK_RESULT(VisitTag(module->tags[i]));
595601
for (size_t i = 0; i < module->exports.size(); ++i)
596602
CHECK_RESULT(VisitExport(i, module->exports[i]));
603+
for (size_t i = 0; i < module->tables.size(); ++i)
604+
CHECK_RESULT(VisitTable(module->tables[i]));
597605
for (size_t i = 0; i < module->elem_segments.size(); ++i)
598606
CHECK_RESULT(VisitElemSegment(i, module->elem_segments[i]));
599607
for (size_t i = 0; i < module->data_segments.size(); ++i)

src/binary-reader-ir.cc

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,12 @@ class BinaryReaderIR : public BinaryReaderNop {
144144
Result OnFunction(Index index, Index sig_index) override;
145145

146146
Result OnTableCount(Index count) override;
147-
Result OnTable(Index index,
148-
Type elem_type,
149-
const Limits* elem_limits) override;
147+
Result BeginTable(Index index,
148+
Type elem_type,
149+
const Limits* elem_limits,
150+
bool) override;
151+
Result BeginTableInitExpr(Index index) override;
152+
Result EndTableInitExpr(Index index) override;
150153

151154
Result OnMemoryCount(Index count) override;
152155
Result OnMemory(Index index,
@@ -700,9 +703,10 @@ Result BinaryReaderIR::OnTableCount(Index count) {
700703
return Result::Ok;
701704
}
702705

703-
Result BinaryReaderIR::OnTable(Index index,
704-
Type elem_type,
705-
const Limits* elem_limits) {
706+
Result BinaryReaderIR::BeginTable(Index index,
707+
Type elem_type,
708+
const Limits* elem_limits,
709+
bool) {
706710
auto field = std::make_unique<TableModuleField>(GetLocation());
707711
Table& table = field->table;
708712
table.elem_limits = *elem_limits;
@@ -712,6 +716,16 @@ Result BinaryReaderIR::OnTable(Index index,
712716
return Result::Ok;
713717
}
714718

719+
Result BinaryReaderIR::BeginTableInitExpr(Index index) {
720+
assert(index == module_->tables.size() - 1);
721+
Table* table = module_->tables[index];
722+
return BeginInitExpr(&table->init_expr);
723+
}
724+
725+
Result BinaryReaderIR::EndTableInitExpr(Index index) {
726+
return EndInitExpr();
727+
}
728+
715729
Result BinaryReaderIR::OnMemoryCount(Index count) {
716730
WABT_TRY
717731
module_->memories.reserve(module_->num_memory_imports + count);

src/binary-reader-logging.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,15 @@ Result BinaryReaderLogging::OnImportTag(Index import_index,
255255
sig_index);
256256
}
257257

258-
Result BinaryReaderLogging::OnTable(Index index,
259-
Type elem_type,
260-
const Limits* elem_limits) {
258+
Result BinaryReaderLogging::BeginTable(Index index,
259+
Type elem_type,
260+
const Limits* elem_limits,
261+
bool has_init_expr) {
261262
char buf[100];
262263
SPrintLimits(buf, sizeof(buf), elem_limits);
263264
LOGF("OnTable(index: %" PRIindex ", elem_type: %s, %s)\n", index,
264265
elem_type.GetName().c_str(), buf);
265-
return reader_->OnTable(index, elem_type, elem_limits);
266+
return reader_->BeginTable(index, elem_type, elem_limits, has_init_expr);
266267
}
267268

268269
Result BinaryReaderLogging::OnMemory(Index index,
@@ -821,6 +822,9 @@ DEFINE_END(EndFunctionSection)
821822

822823
DEFINE_BEGIN(BeginTableSection)
823824
DEFINE_INDEX(OnTableCount)
825+
DEFINE_INDEX(BeginTableInitExpr)
826+
DEFINE_INDEX(EndTableInitExpr)
827+
DEFINE_INDEX(EndTable)
824828
DEFINE_END(EndTableSection)
825829

826830
DEFINE_BEGIN(BeginMemorySection)

src/binary-reader-objdump.cc

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,9 +1127,10 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
11271127
Result OnFunction(Index index, Index sig_index) override;
11281128

11291129
Result OnTableCount(Index count) override;
1130-
Result OnTable(Index index,
1131-
Type elem_type,
1132-
const Limits* elem_limits) override;
1130+
Result BeginTable(Index index,
1131+
Type elem_type,
1132+
const Limits* elem_limits,
1133+
bool) override;
11331134

11341135
Result OnMemoryCount(Index count) override;
11351136
Result OnMemory(Index index,
@@ -1176,6 +1177,14 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
11761177

11771178
Result EndDataSegmentInitExpr(Index index) override { return EndInitExpr(); }
11781179

1180+
Result BeginTableInitExpr(Index index) override {
1181+
reading_table_init_expr_ = true;
1182+
BeginInitExpr();
1183+
return Result::Ok;
1184+
}
1185+
1186+
Result EndTableInitExpr(Index index) override { return EndInitExpr(); }
1187+
11791188
Result BeginGlobalInitExpr(Index index) override {
11801189
reading_global_init_expr_ = true;
11811190
BeginInitExpr();
@@ -1305,6 +1314,7 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
13051314
Index elem_index_ = 0;
13061315
Index table_index_ = 0;
13071316
Index next_data_reloc_ = 0;
1317+
bool reading_table_init_expr_ = false;
13081318
bool reading_elem_init_expr_ = false;
13091319
bool reading_data_init_expr_ = false;
13101320
bool reading_global_init_expr_ = false;
@@ -1317,8 +1327,9 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
13171327
uint64_t elem_offset_ = 0;
13181328

13191329
bool ReadingInitExpr() {
1320-
return reading_elem_init_expr_ || reading_data_init_expr_ ||
1321-
reading_global_init_expr_ || reading_elem_expr_;
1330+
return reading_table_init_expr_ || reading_elem_init_expr_ ||
1331+
reading_data_init_expr_ || reading_global_init_expr_ ||
1332+
reading_elem_expr_;
13221333
}
13231334
};
13241335

@@ -1697,9 +1708,10 @@ Result BinaryReaderObjdump::OnTableCount(Index count) {
16971708
return OnCount(count);
16981709
}
16991710

1700-
Result BinaryReaderObjdump::OnTable(Index index,
1701-
Type elem_type,
1702-
const Limits* elem_limits) {
1711+
Result BinaryReaderObjdump::BeginTable(Index index,
1712+
Type elem_type,
1713+
const Limits* elem_limits,
1714+
bool) {
17031715
PrintDetails(" - table[%" PRIindex "] type=%s initial=%" PRId64, index,
17041716
elem_type.GetName().c_str(), elem_limits->initial);
17051717
if (elem_limits->has_max) {
@@ -1922,6 +1934,9 @@ Result BinaryReaderObjdump::EndInitExpr() {
19221934
if (reading_data_init_expr_) {
19231935
reading_data_init_expr_ = false;
19241936
InitExprToConstOffset(current_init_expr_, &data_offset_);
1937+
} else if (reading_table_init_expr_) {
1938+
reading_table_init_expr_ = false;
1939+
InitExprToConstOffset(current_init_expr_, &elem_offset_);
19251940
} else if (reading_elem_init_expr_) {
19261941
reading_elem_init_expr_ = false;
19271942
InitExprToConstOffset(current_init_expr_, &elem_offset_);

src/binary-reader.cc

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2794,8 +2794,33 @@ Result BinaryReader::ReadTableSection(Offset section_size) {
27942794
Index table_index = num_table_imports_ + i;
27952795
Type elem_type;
27962796
Limits elem_limits;
2797+
bool has_init_expr = false;
2798+
2799+
if (options_.features.function_references_enabled() &&
2800+
state_.offset < read_end_ &&
2801+
state_.data[state_.offset] == 0x40) {
2802+
state_.offset++;
2803+
has_init_expr = true;
2804+
2805+
uint8_t value;
2806+
CHECK_RESULT(ReadU8(&value, "table init"));
2807+
if (value != 0) {
2808+
PrintError("unsupported table intializer: 0x%x\n",
2809+
static_cast<int>(value));
2810+
return Result::Error;
2811+
}
2812+
}
2813+
27972814
CHECK_RESULT(ReadTable(&elem_type, &elem_limits));
2798-
CALLBACK(OnTable, table_index, elem_type, &elem_limits);
2815+
CALLBACK(BeginTable, table_index, elem_type, &elem_limits, has_init_expr);
2816+
2817+
if (has_init_expr) {
2818+
CALLBACK(BeginTableInitExpr, table_index);
2819+
CHECK_RESULT(ReadInitExpr(table_index));
2820+
CALLBACK(EndTableInitExpr, table_index);
2821+
}
2822+
2823+
CALLBACK(EndTable, table_index);
27992824
}
28002825
CALLBACK0(EndTableSection);
28012826
return Result::Ok;
@@ -2886,6 +2911,11 @@ Result BinaryReader::ReadElemSection(Offset section_size) {
28862911
}
28872912
Type elem_type = Type::FuncRef;
28882913

2914+
if (options_.features.function_references_enabled() &&
2915+
!(flags & SegUseElemExprs)) {
2916+
elem_type = Type(Type::FuncRef, Type::ReferenceNonNull);
2917+
}
2918+
28892919
CALLBACK(BeginElemSegment, i, table_index, flags);
28902920

28912921
if (!(flags & SegPassive)) {
@@ -2904,7 +2934,6 @@ Result BinaryReader::ReadElemSection(Offset section_size) {
29042934
ERROR_UNLESS(kind == ExternalKind::Func,
29052935
"segment elem type must be func (%s)",
29062936
elem_type.GetName().c_str());
2907-
elem_type = Type::FuncRef;
29082937
}
29092938
}
29102939

src/binary-writer.cc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1227,9 +1227,17 @@ void BinaryWriter::WriteFunc(const Func* func) {
12271227
}
12281228

12291229
void BinaryWriter::WriteTable(const Table* table) {
1230+
if (!table->init_expr.empty()) {
1231+
stream_->WriteU8(0x40, "initialized table prefix");
1232+
stream_->WriteU8(0x0, "initialized table prefix");
1233+
}
12301234
WriteType(stream_, table->elem_type);
12311235
WriteLimitsFlags(stream_, ComputeLimitsFlags(&table->elem_limits));
12321236
WriteLimitsData(stream_, &table->elem_limits);
1237+
1238+
if (!table->init_expr.empty()) {
1239+
WriteInitExpr(table->init_expr);
1240+
}
12331241
}
12341242

12351243
void BinaryWriter::WriteMemory(const Memory* memory) {
@@ -1616,7 +1624,8 @@ Result BinaryWriter::WriteModule() {
16161624
ElemSegment* segment = module_->elem_segments[i];
16171625
WriteHeader("elem segment header", i);
16181626
// 1. flags
1619-
uint8_t flags = segment->GetFlags(module_);
1627+
uint8_t flags = segment->GetFlags(
1628+
module_, options_.features.function_references_enabled());
16201629
stream_->WriteU8(flags, "segment flags");
16211630
// 2. optional target table
16221631
if (flags & SegExplicitIndex && segment->kind != SegmentKind::Declared) {

0 commit comments

Comments
 (0)