Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement table.init #6827

Merged
merged 38 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions scripts/gen-s-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -554,9 +554,7 @@
("table.grow", "makeTableGrow()"),
("table.fill", "makeTableFill()"),
("table.copy", "makeTableCopy()"),
# TODO:
# table.init
#
("table.init", "makeTableInit()"),
# exception handling instructions
("try", "makeTry()"),
("try_table", "makeTryTable()"),
Expand Down
6 changes: 6 additions & 0 deletions src/gen-s-parser.inc
Original file line number Diff line number Diff line change
Expand Up @@ -4885,6 +4885,12 @@ switch (buf[0]) {
default: goto parse_error;
}
}
case 'i':
if (op == "table.init"sv) {
CHECK_ERR(makeTableInit(ctx, pos, annotations));
return Ok{};
}
goto parse_error;
case 's': {
switch (buf[7]) {
case 'e':
Expand Down
1 change: 1 addition & 0 deletions src/ir/ReFinalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ void ReFinalize::visitTableSize(TableSize* curr) { curr->finalize(); }
void ReFinalize::visitTableGrow(TableGrow* curr) { curr->finalize(); }
void ReFinalize::visitTableFill(TableFill* curr) { curr->finalize(); }
void ReFinalize::visitTableCopy(TableCopy* curr) { curr->finalize(); }
void ReFinalize::visitTableInit(TableInit* curr) { curr->finalize(); }
void ReFinalize::visitTry(Try* curr) { curr->finalize(); }
void ReFinalize::visitTryTable(TryTable* curr) { curr->finalize(); }
void ReFinalize::visitThrow(Throw* curr) { curr->finalize(); }
Expand Down
6 changes: 6 additions & 0 deletions src/ir/child-typer.h
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,12 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> {
note(&curr->size, Type::i32);
}

void visitTableInit(TableInit* curr) {
note(&curr->dest, wasm.getTable(curr->table)->indexType);
note(&curr->offset, Type::i32);
note(&curr->size, Type::i32);
}

void visitTry(Try* curr) {
note(&curr->body, curr->type);
for (auto& expr : curr->catchBodies) {
Expand Down
3 changes: 3 additions & 0 deletions src/ir/cost.h
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,9 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> {
CostType visitTableCopy(TableCopy* curr) {
return 6 + visit(curr->dest) + visit(curr->source) + visit(curr->size);
}
CostType visitTableInit(TableInit* curr) {
return 6 + visit(curr->dest) + visit(curr->offset) + visit(curr->size);
}
CostType visitTry(Try* curr) {
// We assume no exception will be thrown in most cases
return visit(curr->body);
Expand Down
4 changes: 4 additions & 0 deletions src/ir/effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,10 @@ class EffectAnalyzer {
parent.writesTable = true;
parent.implicitTrap = true;
}
void visitTableInit(TableInit* curr) {
parent.writesTable = true;
parent.implicitTrap = true;
}
void visitTry(Try* curr) {
if (curr->delegateTarget.is()) {
parent.delegateTargets.insert(curr->delegateTarget);
Expand Down
1 change: 1 addition & 0 deletions src/ir/possible-contents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,7 @@ struct InfoCollector
void visitTableGrow(TableGrow* curr) { addRoot(curr); }
void visitTableFill(TableFill* curr) { addRoot(curr); }
void visitTableCopy(TableCopy* curr) { addRoot(curr); }
void visitTableInit(TableInit* curr) {}

void visitNop(Nop* curr) {}
void visitUnreachable(Unreachable* curr) {}
Expand Down
5 changes: 5 additions & 0 deletions src/ir/subtype-exprs.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
self()->noteSubtype(self()->getModule()->getTable(curr->sourceTable)->type,
self()->getModule()->getTable(curr->destTable)->type);
}
void visitTableInit(TableInit* curr) {
auto* seg = self()->getModule()->getElementSegment(curr->segment);
self()->noteSubtype(seg->type,
self()->getModule()->getTable(curr->table)->type);
}
void visitTry(Try* curr) {
self()->noteSubtype(curr->body, curr);
for (auto* body : curr->catchBodies) {
Expand Down
13 changes: 13 additions & 0 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,10 @@ struct NullInstrParserCtx {
makeTableCopy(Index, const std::vector<Annotation>&, TableIdxT*, TableIdxT*) {
return Ok{};
}
Result<>
makeTableInit(Index, const std::vector<Annotation>&, TableIdxT*, ElemIdxT) {
return Ok{};
}
Result<> makeThrow(Index, const std::vector<Annotation>&, TagIdxT) {
return Ok{};
}
Expand Down Expand Up @@ -2325,6 +2329,15 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return withLoc(pos, irBuilder.makeTableCopy(*dest, *src));
}

Result<> makeTableInit(Index pos,
const std::vector<Annotation>& annotations,
Name* table,
Name elem) {
auto t = getTable(pos, table);
CHECK_ERR(t);
return withLoc(pos, irBuilder.makeTableInit(elem, *t));
}

Result<>
makeThrow(Index pos, const std::vector<Annotation>& annotations, Name tag) {
return withLoc(pos, irBuilder.makeThrow(tag));
Expand Down
12 changes: 12 additions & 0 deletions src/parser/parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ Result<> makeTableFill(Ctx&, Index, const std::vector<Annotation>&);
template<typename Ctx>
Result<> makeTableCopy(Ctx&, Index, const std::vector<Annotation>&);
template<typename Ctx>
Result<> makeTableInit(Ctx&, Index, const std::vector<Annotation>&);
template<typename Ctx>
Result<> makeThrow(Ctx&, Index, const std::vector<Annotation>&);
template<typename Ctx>
Result<> makeRethrow(Ctx&, Index, const std::vector<Annotation>&);
Expand Down Expand Up @@ -2067,6 +2069,16 @@ makeTableCopy(Ctx& ctx, Index pos, const std::vector<Annotation>& annotations) {
pos, annotations, destTable.getPtr(), srcTable.getPtr());
}

template<typename Ctx>
Result<>
makeTableInit(Ctx& ctx, Index pos, const std::vector<Annotation>& annotations) {
auto table = maybeTableidx(ctx);
CHECK_ERR(table);
auto elem = elemidx(ctx);
CHECK_ERR(elem);
return ctx.makeTableInit(pos, annotations, table.getPtr(), *elem);
}

template<typename Ctx>
Result<>
makeThrow(Ctx& ctx, Index pos, const std::vector<Annotation>& annotations) {
Expand Down
3 changes: 3 additions & 0 deletions src/passes/Directize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,9 @@ struct Directize : public Pass {
void visitTableCopy(TableCopy* curr) {
tablesWithSet.insert(curr->destTable);
}
void visitTableInit(TableInit* curr) {
tablesWithSet.insert(curr->table);
}
};

Finder(tablesWithSet).walkFunction(func);
Expand Down
6 changes: 6 additions & 0 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2037,6 +2037,12 @@ struct PrintExpressionContents
o << ' ';
curr->sourceTable.print(o);
}
void visitTableInit(TableInit* curr) {
printMedium(o, "table.init ");
curr->table.print(o);
o << ' ';
curr->segment.print(o);
}
void visitTry(Try* curr) {
printMedium(o, "try");
if (curr->name.is()) {
Expand Down
4 changes: 4 additions & 0 deletions src/passes/Table64Lowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ struct Table64Lowering : public WalkerPass<PostWalker<Table64Lowering>> {
wrapAddress64(curr->size, curr->destTable);
}

void visitTableInit(TableInit* curr) {
wrapAddress64(curr->dest, curr->table);
}

void visitCallIndirect(CallIndirect* curr) {
wrapAddress64(curr->target, curr->table);
}
Expand Down
2 changes: 2 additions & 0 deletions src/passes/TypeGeneralizing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,8 @@ struct TransferFn : OverriddenVisitor<TransferFn> {
// Cannot generalize table types yet.
}

void visitTableInit(TableInit* curr) {}

void visitTry(Try* curr) { WASM_UNREACHABLE("TODO"); }
void visitTryTable(TryTable* curr) { WASM_UNREACHABLE("TODO"); }
void visitThrow(Throw* curr) { WASM_UNREACHABLE("TODO"); }
Expand Down
24 changes: 15 additions & 9 deletions src/tools/wasm-ctor-eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,6 @@ class EvallingModuleRunner : public ModuleRunnerBase<EvallingModuleRunner> {

return ModuleRunnerBase<EvallingModuleRunner>::visitGlobalGet(curr);
}

Flow visitTableSet(TableSet* curr) {
// TODO: Full dynamic table support. For now we stop evalling when we see a
// table.set. (To support this we need to track sets and add code to
// serialize them.)
throw FailToEvalException("table.set: TODO");
}
};

// Build an artificial `env` module based on a module's imports, so that the
Expand Down Expand Up @@ -174,6 +167,9 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface {
// not yet been re-added are a blind spot for it).
std::unordered_set<Name> usedGlobalNames;

// Set to true after we create the instance.
bool instanceInitialized = false;

CtorEvalExternalInterface(
std::map<Name, std::shared_ptr<EvallingModuleRunner>> linkedInstances_ =
{}) {
Expand Down Expand Up @@ -363,15 +359,24 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface {
}

Index tableSize(Name tableName) override {
throw FailToEvalException("table size");
// See callTable above, we assume the table is not modified FIXME
return wasm->getTableOrNull(tableName)->initial;
}

Literal tableLoad(Name tableName, Index index) override {
throw FailToEvalException("table.get: TODO");
}

// called during initialization
void tableStore(Name tableName, Index index, const Literal& value) override {}
void tableStore(Name tableName, Index index, const Literal& value) override {
// We allow stores to the table during initialization, but not after, as we
// assume the table does not change at runtime.
// TODO: Allow table changes by updating the table later like we do with the
// memory, by tracking and serializing them.
if (instanceInitialized) {
throw FailToEvalException("tableStore after init: TODO");
}
}

int8_t load8s(Address addr, Name memoryName) override {
return doLoad<int8_t>(addr, memoryName);
Expand Down Expand Up @@ -1294,6 +1299,7 @@ void evalCtors(Module& wasm,
try {
// create an instance for evalling
EvallingModuleRunner instance(wasm, &interface, linkedInstances);
interface.instanceInitialized = true;
// go one by one, in order, until we fail
// TODO: if we knew priorities, we could reorder?
for (auto& ctor : ctors) {
Expand Down
2 changes: 2 additions & 0 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,7 @@ enum ASTNodes {
TableSize = 0x10,
TableFill = 0x11,
TableCopy = 0x0e,
TableInit = 0x0c,
RefNull = 0xd0,
RefIsNull = 0xd1,
RefFunc = 0xd2,
Expand Down Expand Up @@ -1745,6 +1746,7 @@ class WasmBinaryReader {
bool maybeVisitTableGrow(Expression*& out, uint32_t code);
bool maybeVisitTableFill(Expression*& out, uint32_t code);
bool maybeVisitTableCopy(Expression*& out, uint32_t code);
bool maybeVisitTableInit(Expression*& out, uint32_t code);
bool maybeVisitRefI31(Expression*& out, uint32_t code);
bool maybeVisitI31Get(Expression*& out, uint32_t code);
bool maybeVisitRefTest(Expression*& out, uint32_t code);
Expand Down
14 changes: 14 additions & 0 deletions src/wasm-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,20 @@ class Builder {
ret->finalize();
return ret;
}
TableInit* makeTableInit(Name segment,
Expression* dest,
Expression* offset,
Expression* size,
Name table) {
auto* ret = wasm.allocator.alloc<TableInit>();
ret->segment = segment;
ret->dest = dest;
ret->offset = offset;
ret->size = size;
ret->table = table;
ret->finalize();
return ret;
}

private:
Try* makeTry(Name name,
Expand Down
8 changes: 8 additions & 0 deletions src/wasm-delegations-fields.def
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,14 @@ DELEGATE_FIELD_NAME_KIND(TableCopy, sourceTable, ModuleItemKind::Table)
DELEGATE_FIELD_NAME_KIND(TableCopy, destTable, ModuleItemKind::Table)
DELEGATE_FIELD_CASE_END(TableCopy)

DELEGATE_FIELD_CASE_START(TableInit)
DELEGATE_FIELD_CHILD(TableInit, size)
DELEGATE_FIELD_CHILD(TableInit, offset)
DELEGATE_FIELD_CHILD(TableInit, dest)
DELEGATE_FIELD_NAME_KIND(TableInit, segment, ModuleItemKind::ElementSegment)
DELEGATE_FIELD_NAME_KIND(TableInit, table, ModuleItemKind::Table)
DELEGATE_FIELD_CASE_END(TableInit)

DELEGATE_FIELD_CASE_START(Try)
DELEGATE_FIELD_SCOPE_NAME_USE(Try, delegateTarget)
DELEGATE_FIELD_CHILD_VECTOR(Try, catchBodies)
Expand Down
1 change: 1 addition & 0 deletions src/wasm-delegations.def
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ DELEGATE(TableSize);
DELEGATE(TableGrow);
DELEGATE(TableFill);
DELEGATE(TableCopy);
DELEGATE(TableInit);
DELEGATE(Try);
DELEGATE(TryTable);
DELEGATE(Throw);
Expand Down
Loading
Loading