summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndy Wingo <wingo@igalia.com>2020-10-01 17:30:58 +0200
committerGitHub <noreply@github.com>2020-10-01 08:30:58 -0700
commitee87440dedb4335d5ca8ec25e86b36c27a5b3368 (patch)
tree522ec9766d5da42fd8b8ba6efa0c6e74fc370748 /src
parentcd63243c5b3b2fa938f365edab30139f74549b51 (diff)
downloadwabt-ee87440dedb4335d5ca8ec25e86b36c27a5b3368.tar.gz
wabt-ee87440dedb4335d5ca8ec25e86b36c27a5b3368.tar.bz2
wabt-ee87440dedb4335d5ca8ec25e86b36c27a5b3368.zip
Add --relocatable support for tables (#1549) (#1549)
We add relocations for table numbers on each place where we reify a table number (call_indirect, table.get, table.set...), but only if reference types are enabled. Also, fix symbol table generation with unnamed definitions, to allow for relocating references to anonymous functions or tables. As tests, add variants of the relocations and symbol-tables dump tests, with and without all features enabled. Enabling reference types causes relocs to be emitted. We also add --details to the relocations dump tests, so that we can see the target symbols for the relocations.
Diffstat (limited to 'src')
-rw-r--r--src/binary-reader-ir.cc19
-rw-r--r--src/binary-reader-logging.cc10
-rw-r--r--src/binary-reader-logging.h4
-rw-r--r--src/binary-reader-nop.h6
-rw-r--r--src/binary-reader-objdump.cc42
-rw-r--r--src/binary-reader-objdump.h1
-rw-r--r--src/binary-reader.cc7
-rw-r--r--src/binary-reader.h4
-rw-r--r--src/binary-writer.cc107
-rw-r--r--src/common.cc1
-rw-r--r--src/common.h6
11 files changed, 182 insertions, 25 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc
index 3678438e..58636e88 100644
--- a/src/binary-reader-ir.cc
+++ b/src/binary-reader-ir.cc
@@ -260,6 +260,8 @@ class BinaryReaderIR : public BinaryReaderNop {
Index section_index) override;
Result OnEventSymbol(Index index, uint32_t flags, string_view name,
Index event_index) override;
+ Result OnTableSymbol(Index index, uint32_t flags, string_view name,
+ Index table_index) override;
private:
Location GetLocation() const;
@@ -1349,6 +1351,23 @@ Result BinaryReaderIR::OnEventSymbol(Index index, uint32_t flags,
return Result::Ok;
}
+Result BinaryReaderIR::OnTableSymbol(Index index, uint32_t flags,
+ string_view name, Index table_index) {
+ if (name.empty()) {
+ return Result::Ok;
+ }
+ if (table_index >= module_->tables.size()) {
+ PrintError("invalid table index: %" PRIindex, table_index);
+ return Result::Error;
+ }
+ Table* table = module_->tables[table_index];
+ std::string dollar_name =
+ GetUniqueName(&module_->table_bindings, MakeDollarName(name));
+ table->name = dollar_name;
+ module_->table_bindings.emplace(dollar_name, Binding(table_index));
+ return Result::Ok;
+}
+
} // end anonymous namespace
Result ReadBinaryIr(const char* filename,
diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc
index b74dcf43..9c83a049 100644
--- a/src/binary-reader-logging.cc
+++ b/src/binary-reader-logging.cc
@@ -603,6 +603,16 @@ Result BinaryReaderLogging::OnEventSymbol(Index index,
return reader_->OnEventSymbol(index, flags, name, event_index);
}
+Result BinaryReaderLogging::OnTableSymbol(Index index,
+ uint32_t flags,
+ string_view name,
+ Index table_index) {
+ LOGF("OnTableSymbol(name: " PRIstringview " flags: 0x%x index: %" PRIindex
+ ")\n",
+ WABT_PRINTF_STRING_VIEW_ARG(name), flags, table_index);
+ return reader_->OnTableSymbol(index, flags, name, table_index);
+}
+
Result BinaryReaderLogging::OnSegmentInfo(Index index,
string_view name,
Address alignment,
diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h
index a461572b..5936dad6 100644
--- a/src/binary-reader-logging.h
+++ b/src/binary-reader-logging.h
@@ -327,6 +327,10 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
uint32_t flags,
string_view name,
Index event_index) override;
+ Result OnTableSymbol(Index index,
+ uint32_t flags,
+ string_view name,
+ Index event_index) override;
Result OnSegmentInfoCount(Index count) override;
Result OnSegmentInfo(Index index,
string_view name,
diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h
index 492687bd..b49883b9 100644
--- a/src/binary-reader-nop.h
+++ b/src/binary-reader-nop.h
@@ -472,6 +472,12 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Index event_index) override {
return Result::Ok;
}
+ Result OnTableSymbol(Index index,
+ uint32_t flags,
+ string_view name,
+ Index table_index) override {
+ return Result::Ok;
+ }
Result OnSegmentInfoCount(Index count) override { return Result::Ok; }
Result OnSegmentInfo(Index index,
string_view name,
diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc
index 649358d6..0d3d1188 100644
--- a/src/binary-reader-objdump.cc
+++ b/src/binary-reader-objdump.cc
@@ -58,6 +58,7 @@ class BinaryReaderObjdumpBase : public BinaryReaderNop {
string_view GetEventName(Index index) const;
string_view GetSymbolName(Index index) const;
string_view GetSegmentName(Index index) const;
+ string_view GetTableName(Index index) const;
void PrintRelocation(const Reloc& reloc, Offset offset) const;
Offset GetSectionStart(BinarySection section_code) const {
return section_starts_[static_cast<size_t>(section_code)];
@@ -152,6 +153,10 @@ string_view BinaryReaderObjdumpBase::GetSegmentName(Index index) const {
return objdump_state_->segment_names.Get(index);
}
+string_view BinaryReaderObjdumpBase::GetTableName(Index index) const {
+ return objdump_state_->table_names.Get(index);
+}
+
string_view BinaryReaderObjdumpBase::GetSymbolName(Index symbol_index) const {
if (symbol_index >= objdump_state_->symtab.size())
return "<illegal_symbol_index>";
@@ -167,6 +172,8 @@ string_view BinaryReaderObjdumpBase::GetSymbolName(Index symbol_index) const {
return GetSectionName(sym.index);
case SymbolType::Event:
return GetEventName(sym.index);
+ case SymbolType::Table:
+ return GetTableName(sym.index);
}
WABT_UNREACHABLE;
}
@@ -283,6 +290,18 @@ class BinaryReaderObjdumpPrepass : public BinaryReaderObjdumpBase {
return Result::Ok;
}
+ Result OnTableSymbol(Index index,
+ uint32_t flags,
+ string_view name,
+ Index table_index) override {
+ if (!name.empty()) {
+ SetTableName(table_index, name);
+ }
+ objdump_state_->symtab[index] = {SymbolType::Table, name.to_string(),
+ table_index};
+ return Result::Ok;
+ }
+
Result OnImportFunc(Index import_index,
string_view module_name,
string_view field_name,
@@ -351,6 +370,7 @@ class BinaryReaderObjdumpPrepass : public BinaryReaderObjdumpBase {
void SetFunctionName(Index index, string_view name);
void SetGlobalName(Index index, string_view name);
void SetEventName(Index index, string_view name);
+ void SetTableName(Index index, string_view name);
void SetSegmentName(Index index, string_view name);
};
@@ -367,6 +387,10 @@ void BinaryReaderObjdumpPrepass::SetEventName(Index index, string_view name) {
objdump_state_->event_names.Set(index, name);
}
+void BinaryReaderObjdumpPrepass::SetTableName(Index index, string_view name) {
+ objdump_state_->table_names.Set(index, name);
+}
+
void BinaryReaderObjdumpPrepass::SetSegmentName(Index index, string_view name) {
objdump_state_->segment_names.Set(index, name);
}
@@ -891,6 +915,10 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
uint32_t flags,
string_view name,
Index event_index) override;
+ Result OnTableSymbol(Index index,
+ uint32_t flags,
+ string_view name,
+ Index table_index) override;
Result OnSegmentInfoCount(Index count) override;
Result OnSegmentInfo(Index index,
string_view name,
@@ -1781,11 +1809,23 @@ Result BinaryReaderObjdump::OnEventSymbol(Index index,
if (name.empty()) {
name = GetEventName(event_index);
}
- PrintDetails(" - [%d] E <" PRIstringview "> event=%" PRIindex, index,
+ PrintDetails(" - %d: E <" PRIstringview "> event=%" PRIindex, index,
WABT_PRINTF_STRING_VIEW_ARG(name), event_index);
return PrintSymbolFlags(flags);
}
+Result BinaryReaderObjdump::OnTableSymbol(Index index,
+ uint32_t flags,
+ string_view name,
+ Index table_index) {
+ if (name.empty()) {
+ name = GetTableName(table_index);
+ }
+ PrintDetails(" - %d: T <" PRIstringview "> table=%" PRIindex, index,
+ WABT_PRINTF_STRING_VIEW_ARG(name), table_index);
+ return PrintSymbolFlags(flags);
+}
+
Result BinaryReaderObjdump::OnSegmentInfoCount(Index count) {
PrintDetails(" - segment info [count=%d]\n", count);
return Result::Ok;
diff --git a/src/binary-reader-objdump.h b/src/binary-reader-objdump.h
index b1e24f81..b2874dac 100644
--- a/src/binary-reader-objdump.h
+++ b/src/binary-reader-objdump.h
@@ -73,6 +73,7 @@ struct ObjdumpState {
ObjdumpNames section_names;
ObjdumpNames event_names;
ObjdumpNames segment_names;
+ ObjdumpNames table_names;
std::vector<ObjdumpSymbol> symtab;
};
diff --git a/src/binary-reader.cc b/src/binary-reader.cc
index a28a0ad9..e44b8ca7 100644
--- a/src/binary-reader.cc
+++ b/src/binary-reader.cc
@@ -1784,6 +1784,7 @@ Result BinaryReader::ReadRelocSection(Offset section_size) {
case RelocType::GlobalIndexI32:
case RelocType::EventIndexLEB:
case RelocType::TableIndexRelSLEB:
+ case RelocType::TableNumberLEB:
break;
default:
@@ -1854,7 +1855,8 @@ Result BinaryReader::ReadLinkingSection(Offset section_size) {
switch (sym_type) {
case SymbolType::Function:
case SymbolType::Global:
- case SymbolType::Event: {
+ case SymbolType::Event:
+ case SymbolType::Table: {
uint32_t index = 0;
CHECK_RESULT(ReadU32Leb128(&index, "index"));
if ((flags & WABT_SYMBOL_FLAG_UNDEFINED) == 0 ||
@@ -1870,6 +1872,9 @@ Result BinaryReader::ReadLinkingSection(Offset section_size) {
case SymbolType::Event:
CALLBACK(OnEventSymbol, i, flags, name, index);
break;
+ case SymbolType::Table:
+ CALLBACK(OnTableSymbol, i, flags, name, index);
+ break;
default:
WABT_UNREACHABLE;
}
diff --git a/src/binary-reader.h b/src/binary-reader.h
index 1c3fcf12..8e5e3dd6 100644
--- a/src/binary-reader.h
+++ b/src/binary-reader.h
@@ -401,6 +401,10 @@ class BinaryReaderDelegate {
uint32_t flags,
string_view name,
Index event_index) = 0;
+ virtual Result OnTableSymbol(Index index,
+ uint32_t flags,
+ string_view name,
+ Index table_index) = 0;
virtual Result OnSegmentInfoCount(Index count) = 0;
virtual Result OnSegmentInfo(Index index,
string_view name,
diff --git a/src/binary-writer.cc b/src/binary-writer.cc
index c628b108..b5732533 100644
--- a/src/binary-writer.cc
+++ b/src/binary-writer.cc
@@ -122,6 +122,10 @@ class Symbol {
static const SymbolType type = SymbolType::Event;
Index index;
};
+ struct Table {
+ static const SymbolType type = SymbolType::Table;
+ Index index;
+ };
private:
SymbolType type_;
@@ -133,6 +137,7 @@ class Symbol {
Global global_;
Section section_;
Event event_;
+ Table table_;
};
public:
@@ -146,6 +151,8 @@ class Symbol {
: type_(Section::type), name_(name), flags_(flags), section_(s) {}
Symbol(const string_view& name, uint8_t flags, const Event& e)
: type_(Event::type), name_(name), flags_(flags), event_(e) {}
+ Symbol(const string_view& name, uint8_t flags, const Table& t)
+ : type_(Table::type), name_(name), flags_(flags), table_(t) {}
SymbolType type() const { return type_; }
const string_view& name() const { return name_; }
@@ -168,6 +175,7 @@ class Symbol {
bool IsGlobal() const { return type() == Global::type; }
bool IsSection() const { return type() == Section::type; }
bool IsEvent() const { return type() == Event::type; }
+ bool IsTable() const { return type() == Table::type; }
const Function& AsFunction() const {
assert(IsFunction());
@@ -189,6 +197,10 @@ class Symbol {
assert(IsEvent());
return event_;
}
+ const Table& AsTable() const {
+ assert(IsTable());
+ return table_;
+ }
};
class SymbolTable {
@@ -197,6 +209,7 @@ class SymbolTable {
std::vector<Symbol> symbols_;
std::vector<Index> functions_;
+ std::vector<Index> tables_;
std::vector<Index> globals_;
std::set<string_view> seen_names_;
@@ -222,17 +235,17 @@ class SymbolTable {
// name fabricated by wabt.
name = string_view();
} else {
- // Functions defined in this module without a name don't go in the symbol
- // table.
if (name.empty()) {
- return Result::Ok;
+ // Definitions without a name are local.
+ flags |= uint8_t(SymbolBinding::Local);
+ flags |= uint8_t(SymbolVisibility::Hidden);
+ } else {
+ // Otherwise, strip the dollar off the name; a definition $foo is
+ // available for linking as "foo".
+ assert(name[0] == '$');
+ name.remove_prefix(1);
}
- // Otherwise, strip the dollar off the name; a function $foo is available
- // for linking as "foo".
- assert(name[0] == '$');
- name.remove_prefix(1);
-
if (exported) {
CHECK_RESULT(EnsureUnique(name));
flags |= uint8_t(SymbolVisibility::Hidden);
@@ -248,6 +261,13 @@ class SymbolTable {
return Result::Ok;
};
+ Index SymbolIndex(const std::vector<Index>& table, Index index) const {
+ // For well-formed modules, an index into (e.g.) functions_ will always be
+ // within bounds; the out-of-bounds case here is just to allow --relocatable
+ // to write known-invalid modules.
+ return index < table.size() ? table[index] : kInvalidIndex;
+ }
+
public:
SymbolTable() {}
@@ -276,8 +296,8 @@ class SymbolTable {
}
}
- // We currently only create symbol table entries for function and global
- // symbols.
+ // We currently only create symbol table entries for function, table, and
+ // global symbols.
for (size_t i = 0; i < module->funcs.size(); ++i) {
const Func* func = module->funcs[i];
bool imported = i < module->num_func_imports;
@@ -286,6 +306,14 @@ class SymbolTable {
Symbol::Function{Index(i)}));
}
+ for (size_t i = 0; i < module->tables.size(); ++i) {
+ const Table* table = module->tables[i];
+ bool imported = i < module->num_table_imports;
+ bool exported = exported_tables.count(i);
+ CHECK_RESULT(AddSymbol(&tables_, table->name, imported, exported,
+ Symbol::Table{Index(i)}));
+ }
+
for (size_t i = 0; i < module->globals.size(); ++i) {
const Global* global = module->globals[i];
bool imported = i < module->num_global_imports;
@@ -298,8 +326,15 @@ class SymbolTable {
}
const std::vector<Symbol>& symbols() const { return symbols_; }
- Index FunctionSymbolIndex(Index index) const { return functions_[index]; }
- Index GlobalSymbolIndex(Index index) const { return globals_[index]; }
+ Index FunctionSymbolIndex(Index index) const {
+ return SymbolIndex(functions_, index);
+ }
+ Index TableSymbolIndex(Index index) const {
+ return SymbolIndex(tables_, index);
+ }
+ Index GlobalSymbolIndex(Index index) const {
+ return SymbolIndex(globals_, index);
+ }
};
class BinaryWriter {
@@ -336,6 +371,7 @@ class BinaryWriter {
void WriteS32Leb128WithReloc(int32_t value,
const char* desc,
RelocType reloc_type);
+ void WriteTableNumberWithReloc(Index table_number, const char* desc);
template <typename T>
void WriteLoadStoreExpr(const Func* func, const Expr* expr, const char* desc);
void WriteExpr(const Func* func, const Expr* expr);
@@ -513,6 +549,8 @@ Index BinaryWriter::GetSymbolIndex(RelocType reloc_type, Index index) {
switch (reloc_type) {
case RelocType::FuncIndexLEB:
return symtab_.FunctionSymbolIndex(index);
+ case RelocType::TableNumberLEB:
+ return symtab_.TableSymbolIndex(index);
case RelocType::GlobalIndexLEB:
return symtab_.GlobalSymbolIndex(index);
case RelocType::TypeIndexLEB:
@@ -537,6 +575,12 @@ void BinaryWriter::AddReloc(RelocType reloc_type, Index index) {
// Add a new relocation to the curent reloc section
size_t offset = stream_->offset() - last_section_payload_offset_;
Index symbol_index = GetSymbolIndex(reloc_type, index);
+ if (symbol_index == kInvalidIndex) {
+ // The file is invalid, for example a reference to function 42 where only 10
+ // functions are defined. The user must have already passed --no-check, so
+ // no extra warning here is needed.
+ return;
+ }
current_reloc_section_->relocations.emplace_back(reloc_type, offset,
symbol_index);
}
@@ -563,6 +607,18 @@ void BinaryWriter::WriteS32Leb128WithReloc(int32_t value,
}
}
+void BinaryWriter::WriteTableNumberWithReloc(Index value,
+ const char* desc) {
+ // Unless reference types are enabled, all references to tables refer to table
+ // 0, so no relocs need be emitted when making relocatable binaries.
+ if (options_.relocatable && options_.features.reference_types_enabled()) {
+ AddReloc(RelocType::TableNumberLEB, value);
+ WriteFixedS32Leb128(stream_, value, desc);
+ } else {
+ WriteS32Leb128(stream_, value, desc);
+ }
+}
+
Index BinaryWriter::GetLocalIndex(const Func* func, const Var& var) {
// func can be nullptr when using local.get/local.set/local.tee in an
// init_expr.
@@ -674,7 +730,7 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
module_->GetTableIndex(cast<CallIndirectExpr>(expr)->table);
WriteOpcode(stream_, Opcode::CallIndirect);
WriteU32Leb128WithReloc(sig_index, "signature index", RelocType::TypeIndexLEB);
- WriteU32Leb128(stream_, table_index, "table index");
+ WriteTableNumberWithReloc(table_index, "table index");
break;
}
case ExprType::ReturnCallIndirect: {
@@ -684,7 +740,7 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
module_->GetTableIndex(cast<ReturnCallIndirectExpr>(expr)->table);
WriteOpcode(stream_, Opcode::ReturnCallIndirect);
WriteU32Leb128WithReloc(sig_index, "signature index", RelocType::TypeIndexLEB);
- WriteU32Leb128(stream_, table_index, "table index");
+ WriteTableNumberWithReloc(table_index, "table index");
break;
}
case ExprType::Compare:
@@ -815,8 +871,8 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
Index dst = module_->GetTableIndex(copy_expr->dst_table);
Index src = module_->GetTableIndex(copy_expr->src_table);
WriteOpcode(stream_, Opcode::TableCopy);
- WriteU32Leb128(stream_, dst, "table.copy dst_table");
- WriteU32Leb128(stream_, src, "table.copy src_table");
+ WriteTableNumberWithReloc(dst, "table.copy dst_table");
+ WriteTableNumberWithReloc(src, "table.copy src_table");
break;
}
case ExprType::ElemDrop: {
@@ -833,42 +889,42 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
module_->GetElemSegmentIndex(init_expr->segment_index);
WriteOpcode(stream_, Opcode::TableInit);
WriteU32Leb128(stream_, segment_index, "table.init segment");
- WriteU32Leb128(stream_, table_index, "table.init table");
+ WriteTableNumberWithReloc(table_index, "table.init table");
break;
}
case ExprType::TableGet: {
Index index =
module_->GetTableIndex(cast<TableGetExpr>(expr)->var);
WriteOpcode(stream_, Opcode::TableGet);
- WriteU32Leb128(stream_, index, "table.get table index");
+ WriteTableNumberWithReloc(index, "table.get table index");
break;
}
case ExprType::TableSet: {
Index index =
module_->GetTableIndex(cast<TableSetExpr>(expr)->var);
WriteOpcode(stream_, Opcode::TableSet);
- WriteU32Leb128(stream_, index, "table.set table index");
+ WriteTableNumberWithReloc(index, "table.set table index");
break;
}
case ExprType::TableGrow: {
Index index =
module_->GetTableIndex(cast<TableGrowExpr>(expr)->var);
WriteOpcode(stream_, Opcode::TableGrow);
- WriteU32Leb128(stream_, index, "table.grow table index");
+ WriteTableNumberWithReloc(index, "table.grow table index");
break;
}
case ExprType::TableSize: {
Index index =
module_->GetTableIndex(cast<TableSizeExpr>(expr)->var);
WriteOpcode(stream_, Opcode::TableSize);
- WriteU32Leb128(stream_, index, "table.size table index");
+ WriteTableNumberWithReloc(index, "table.size table index");
break;
}
case ExprType::TableFill: {
Index index =
module_->GetTableIndex(cast<TableFillExpr>(expr)->var);
WriteOpcode(stream_, Opcode::TableFill);
- WriteU32Leb128(stream_, index, "table.fill table index");
+ WriteTableNumberWithReloc(index, "table.fill table index");
break;
}
case ExprType::RefFunc: {
@@ -1042,6 +1098,7 @@ void BinaryWriter::WriteRelocSection(const RelocSection* reloc_section) {
case RelocType::GlobalIndexLEB:
case RelocType::EventIndexLEB:
case RelocType::TableIndexRelSLEB:
+ case RelocType::TableNumberLEB:
break;
default:
fprintf(stderr, "warning: unsupported relocation type: %s\n",
@@ -1094,6 +1151,12 @@ void BinaryWriter::WriteLinkingSection() {
WriteStr(stream_, sym.name(), "event name", PrintChars::Yes);
}
break;
+ case SymbolType::Table:
+ WriteU32Leb128(stream_, sym.AsTable().index, "table index");
+ if (sym.defined() || sym.explicit_name()) {
+ WriteStr(stream_, sym.name(), "table name", PrintChars::Yes);
+ }
+ break;
}
}
EndSubsection();
diff --git a/src/common.cc b/src/common.cc
index 875f71ae..0de9cf93 100644
--- a/src/common.cc
+++ b/src/common.cc
@@ -53,6 +53,7 @@ const char* g_reloc_type_name[] = {
"R_WASM_MEMORY_ADDR_LEB64", "R_WASM_MEMORY_ADDR_SLEB64",
"R_WASM_MEMORY_ADDR_I64", "R_WASM_MEMORY_ADDR_REL_SLEB64",
"R_WASM_TABLE_INDEX_SLEB64", "R_WASM_TABLE_INDEX_I64",
+ "R_WASM_TABLE_NUMBER_LEB",
};
WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(g_reloc_type_name) == kRelocTypeCount);
diff --git a/src/common.h b/src/common.h
index 40f79f49..d900619d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -294,9 +294,10 @@ enum class RelocType {
MemoryAddressRelSLEB64 = 17, // Memory64: Like MemoryAddressRelSLEB
TableIndexSLEB64 = 18, // Memory64: Like TableIndexSLEB
TableIndexI64 = 19, // Memory64: Like TableIndexI32
+ TableNumberLEB = 20, // e.g. Immediate of table.get
First = FuncIndexLEB,
- Last = TableIndexI64,
+ Last = TableNumberLEB,
};
static const int kRelocTypeCount = WABT_ENUM_COUNT(RelocType);
@@ -322,6 +323,7 @@ enum class SymbolType {
Global = 2,
Section = 3,
Event = 4,
+ Table = 5,
};
enum class ComdatType {
@@ -422,6 +424,8 @@ static WABT_INLINE const char* GetSymbolTypeName(SymbolType type) {
return "section";
case SymbolType::Event:
return "event";
+ case SymbolType::Table:
+ return "table";
default:
return "<error_symbol_type>";
}