summaryrefslogtreecommitdiff
path: root/src/binary-writer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/binary-writer.cc')
-rw-r--r--src/binary-writer.cc107
1 files changed, 85 insertions, 22 deletions
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();