summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-08-15 14:29:57 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-08-15 15:03:36 -0700
commit113efcaa1e814304662ccc56312d8c59014a3a6c (patch)
tree5639a4a9d834947c9fc190e5916b9961e545cfba
parent086c4c0f89bbe626f4c98ae95716084db0541b0d (diff)
downloadbinaryen-113efcaa1e814304662ccc56312d8c59014a3a6c.tar.gz
binaryen-113efcaa1e814304662ccc56312d8c59014a3a6c.tar.bz2
binaryen-113efcaa1e814304662ccc56312d8c59014a3a6c.zip
offset support in table
-rw-r--r--src/asm2wasm.h10
-rw-r--r--src/binaryen-c.cpp6
-rw-r--r--src/passes/DuplicateFunctionElimination.cpp10
-rw-r--r--src/passes/Print.cpp15
-rw-r--r--src/passes/RemoveUnusedFunctions.cpp6
-rw-r--r--src/passes/ReorderFunctions.cpp6
-rw-r--r--src/shell-interface.h24
-rw-r--r--src/wasm-binary.h37
-rw-r--r--src/wasm-interpreter.h21
-rw-r--r--src/wasm-js.cpp68
-rw-r--r--src/wasm-linker.cpp31
-rw-r--r--src/wasm-linker.h4
-rw-r--r--src/wasm-s-parser.h18
-rw-r--r--src/wasm.h14
-rw-r--r--test/dot_s/alias.wast2
-rw-r--r--test/dot_s/basics.wast2
-rw-r--r--test/dot_s/bcp-1.wast2
-rw-r--r--test/dot_s/dyncall.wast2
-rw-r--r--test/dot_s/indidx.wast2
-rw-r--r--test/dot_s/indirect-import.wast2
-rw-r--r--test/dot_s/invoke_wrapper.wast2
-rw-r--r--test/emcc_O2_hello_world.fromasm2
-rw-r--r--test/emcc_O2_hello_world.fromasm.imprecise2
-rw-r--r--test/emcc_O2_hello_world.fromasm.imprecise.no-opts2
-rw-r--r--test/emcc_O2_hello_world.fromasm.no-opts2
-rw-r--r--test/emcc_hello_world.fromasm2
-rw-r--r--test/emcc_hello_world.fromasm.imprecise2
-rw-r--r--test/emcc_hello_world.fromasm.imprecise.no-opts2
-rw-r--r--test/emcc_hello_world.fromasm.no-opts2
-rw-r--r--test/example/c-api-kitchen-sink.txt4
-rw-r--r--test/example/c-api-kitchen-sink.txt.txt2
-rw-r--r--test/memorygrowth.fromasm2
-rw-r--r--test/memorygrowth.fromasm.imprecise2
-rw-r--r--test/memorygrowth.fromasm.imprecise.no-opts2
-rw-r--r--test/memorygrowth.fromasm.no-opts2
-rw-r--r--test/passes/dce.txt2
-rw-r--r--test/passes/duplicate-function-elimination.txt8
-rw-r--r--test/passes/remove-unused-functions.txt2
-rw-r--r--test/passes/remove-unused-names_merge-blocks.txt2
-rw-r--r--test/unit.fromasm2
-rw-r--r--test/unit.fromasm.imprecise2
-rw-r--r--test/unit.fromasm.imprecise.no-opts2
-rw-r--r--test/unit.fromasm.no-opts2
-rw-r--r--test/unit.wast2
-rw-r--r--test/unit.wast.fromBinary4
45 files changed, 240 insertions, 102 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 868aa31d3..a5754f725 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -660,13 +660,17 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
// TODO: when not using aliasing function pointers, we could merge them by noticing that
// index 0 in each table is the null func, and each other index should only have one
// non-null func. However, that breaks down when function pointer casts are emulated.
- functionTableStarts[name] = wasm.table.names.size(); // this table starts here
+ if (wasm.table.segments.size() == 0) {
+ wasm.table.segments.emplace_back(wasm.allocator.alloc<Const>()->set(Literal(uint32_t(0))));
+ }
+ auto& segment = wasm.table.segments[0];
+ functionTableStarts[name] = segment.data.size(); // this table starts here
Ref contents = value[1];
for (unsigned k = 0; k < contents->size(); k++) {
IString curr = contents[k][1]->getIString();
- wasm.table.names.push_back(curr);
+ segment.data.push_back(curr);
}
- wasm.table.initial = wasm.table.max = wasm.table.names.size();
+ wasm.table.initial = wasm.table.max = segment.data.size();
} else {
abort_on("invalid var element", pair);
}
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index d7f866663..83c626eb1 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -729,10 +729,12 @@ void BinaryenSetFunctionTable(BinaryenModuleRef module, BinaryenFunctionRef* fun
}
auto* wasm = (Module*)module;
+ Table::Segment segment(wasm->allocator.alloc<Const>()->set(Literal(int32_t(0))));
for (BinaryenIndex i = 0; i < numFuncs; i++) {
- wasm->table.names.push_back(((Function*)funcs[i])->name);
+ segment.data.push_back(((Function*)funcs[i])->name);
}
- wasm->table.initial = wasm->table.max = wasm->table.names.size();
+ wasm->table.segments.push_back(segment);
+ wasm->table.initial = wasm->table.max = numFuncs;
}
// Memory. One per module
diff --git a/src/passes/DuplicateFunctionElimination.cpp b/src/passes/DuplicateFunctionElimination.cpp
index 961d26ba5..2b8e69b54 100644
--- a/src/passes/DuplicateFunctionElimination.cpp
+++ b/src/passes/DuplicateFunctionElimination.cpp
@@ -123,10 +123,12 @@ struct DuplicateFunctionElimination : public Pass {
replacerRunner.add<FunctionReplacer>(&replacements);
replacerRunner.run();
// replace in table
- for (auto& name : module->table.names) {
- auto iter = replacements.find(name);
- if (iter != replacements.end()) {
- name = iter->second;
+ for (auto& segment : module->table.segments) {
+ for (auto& name : segment.data) {
+ auto iter = replacements.find(name);
+ if (iter != replacements.end()) {
+ name = iter->second;
+ }
}
}
// replace in start
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 711cc8a84..5eea38bdc 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -579,12 +579,15 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
if (curr->max && curr->max != Table::kMaxSize) o << ' ' << curr->max;
o << " anyfunc)\n";
doIndent(o, indent);
- printOpening(o, "elem", true);
- for (auto name : curr->names) {
- o << ' ';
- printName(name);
+ for (auto& segment : curr->segments) {
+ printOpening(o, "elem ", true);
+ visit(segment.offset);
+ for (auto name : segment.data) {
+ o << ' ';
+ printName(name);
+ }
+ o << ')';
}
- o << ')';
}
void visitModule(Module *curr) {
currModule = curr;
@@ -652,7 +655,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
visitGlobal(child.get());
o << maybeNewLine;
}
- if (curr->table.names.size() > 0) {
+ if (curr->table.segments.size() > 0 || curr->table.initial > 0 || curr->table.max != Table::kMaxSize) {
doIndent(o, indent);
visitTable(&curr->table);
o << maybeNewLine;
diff --git a/src/passes/RemoveUnusedFunctions.cpp b/src/passes/RemoveUnusedFunctions.cpp
index a2941aff6..78b0f0ffc 100644
--- a/src/passes/RemoveUnusedFunctions.cpp
+++ b/src/passes/RemoveUnusedFunctions.cpp
@@ -39,8 +39,10 @@ struct RemoveUnusedFunctions : public Pass {
root.push_back(module->getFunction(curr->value));
}
// For now, all functions that can be called indirectly are marked as roots.
- for (auto& curr : module->table.names) {
- root.push_back(module->getFunction(curr));
+ for (auto& segment : module->table.segments) {
+ for (auto& curr : segment.data) {
+ root.push_back(module->getFunction(curr));
+ }
}
// Compute function reachability starting from the root set.
DirectCallGraphAnalyzer analyzer(module, root);
diff --git a/src/passes/ReorderFunctions.cpp b/src/passes/ReorderFunctions.cpp
index 38ef98afb..679fedb61 100644
--- a/src/passes/ReorderFunctions.cpp
+++ b/src/passes/ReorderFunctions.cpp
@@ -38,8 +38,10 @@ struct ReorderFunctions : public WalkerPass<PostWalker<ReorderFunctions, Visitor
for (auto& curr : module->exports) {
counts[curr->value]++;
}
- for (auto& curr : module->table.names) {
- counts[curr]++;
+ for (auto& segment : module->table.segments) {
+ for (auto& curr : segment.data) {
+ counts[curr]++;
+ }
}
std::sort(module->functions.begin(), module->functions.end(), [this](
const std::unique_ptr<Function>& a,
diff --git a/src/shell-interface.h b/src/shell-interface.h
index 55f9b2a0b..f332307ad 100644
--- a/src/shell-interface.h
+++ b/src/shell-interface.h
@@ -86,6 +86,8 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
}
} memory;
+ std::vector<Name> table;
+
ShellExternalInterface() : memory() {}
void init(Module& wasm) override {
@@ -98,6 +100,15 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
memory.set(offset + i, segment.data[i]);
}
}
+
+ table.resize(wasm.table.initial);
+ for (auto& segment : wasm.table.segments) {
+ Address offset = ConstantExpressionRunner().visit(segment.offset).value.geti32();
+ assert(offset + segment.data.size() <= wasm.table.initial);
+ for (size_t i = 0; i != segment.data.size(); ++i) {
+ table[offset + i] = segment.data[i];
+ }
+ }
}
Literal callImport(Import *import, LiteralList& arguments) override {
@@ -115,6 +126,19 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
abort();
}
+ Literal callTable(Index index, Name type, LiteralList& arguments, ModuleInstance& instance) override {
+ if (index >= table.size()) trap("callTable overflow");
+ auto* func = instance.wasm.getFunction(table[index]);
+ if (func->type.is() && func->type != type) trap("callIndirect: bad type");
+ if (func->params.size() != arguments.size()) trap("callIndirect: bad # of arguments");
+ for (size_t i = 0; i < func->params.size(); i++) {
+ if (func->params[i] != arguments[i].type) {
+ trap("callIndirect: bad argument type");
+ }
+ }
+ return instance.callFunctionInternal(func->name, arguments);
+ }
+
Literal load(Load* load, Address addr) override {
switch (load->type) {
case i32: {
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index d405c91dc..04bebddc5 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -740,12 +740,19 @@ public:
}
void writeFunctionTable() {
- if (wasm->table.names.size() == 0) return;
+ if (wasm->table.segments.size() == 0) return;
if (debug) std::cerr << "== writeFunctionTable" << std::endl;
auto start = startSection(BinaryConsts::Section::FunctionTable);
- o << U32LEB(wasm->table.names.size());
- for (auto name : wasm->table.names) {
- o << U32LEB(getFunctionIndex(name));
+ o << U32LEB(wasm->table.initial);
+ o << U32LEB(wasm->table.max);
+ o << U32LEB(wasm->table.segments.size());
+ for (auto& segment : wasm->table.segments) {
+ writeExpression(segment.offset);
+ o << int8_t(BinaryConsts::End);
+ o << U32LEB(segment.data.size());
+ for (auto name : segment.data) {
+ o << U32LEB(getFunctionIndex(name));
+ }
}
finishSection(start);
}
@@ -1644,11 +1651,13 @@ public:
}
}
- for (size_t index : functionTable) {
- assert(index < wasm.functions.size());
- wasm.table.names.push_back(wasm.functions[index]->name);
+ for (auto& pair : functionTable) {
+ auto i = pair.first;
+ auto& indexes = pair.second;
+ for (auto j : indexes) {
+ wasm.table.segments[i].data.push_back(wasm.functions[j]->name);
+ }
}
- wasm.table.initial = wasm.table.max = wasm.table.names.size();
}
void readDataSegments() {
@@ -1667,14 +1676,20 @@ public:
}
}
- std::vector<size_t> functionTable;
+ std::map<Index, std::vector<Index>> functionTable;
void readFunctionTable() {
if (debug) std::cerr << "== readFunctionTable" << std::endl;
+ wasm.table.initial = getU32LEB();
+ wasm.table.max = getU32LEB();
auto num = getU32LEB();
for (size_t i = 0; i < num; i++) {
- auto index = getU32LEB();
- functionTable.push_back(index);
+ wasm.table.segments.emplace_back(readExpression());
+ auto& temporary = functionTable[i];
+ auto size = getU32LEB();
+ for (Index j = 0; j < size; j++) {
+ temporary.push_back(getU32LEB());
+ }
}
}
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 0be36a677..f2deed039 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -533,6 +533,7 @@ public:
struct ExternalInterface {
virtual void init(Module& wasm) {}
virtual Literal callImport(Import* import, LiteralList& arguments) = 0;
+ virtual Literal callTable(Index index, Name type, LiteralList& arguments, ModuleInstance& instance) = 0;
virtual Literal load(Load* load, Address addr) = 0;
virtual void store(Store* store, Address addr, Literal value) = 0;
virtual void growMemory(Address oldSize, Address newSize) = 0;
@@ -591,8 +592,8 @@ private:
return callFunctionInternal(name, arguments);
}
-private:
- // Internal function call.
+public:
+ // Internal function call. Must be public so that callTable implementations can use it (refactor?)
Literal callFunctionInternal(IString name, LiteralList& arguments) {
class FunctionScope {
@@ -672,18 +673,8 @@ private:
LiteralList arguments;
Flow flow = generateArguments(curr->operands, arguments);
if (flow.breaking()) return flow;
- size_t index = target.value.geti32();
- if (index >= instance.wasm.table.names.size()) trap("callIndirect: overflow");
- Name name = instance.wasm.table.names[index];
- Function *func = instance.wasm.getFunction(name);
- if (func->type.is() && func->type != curr->fullType) trap("callIndirect: bad type");
- if (func->params.size() != arguments.size()) trap("callIndirect: bad # of arguments");
- for (size_t i = 0; i < func->params.size(); i++) {
- if (func->params[i] != arguments[i].type) {
- trap("callIndirect: bad argument type");
- }
- }
- return instance.callFunctionInternal(name, arguments);
+ Index index = target.value.geti32();
+ return instance.externalInterface->callTable(index, curr->fullType, arguments, instance);
}
Flow visitGetLocal(GetLocal *curr) {
@@ -802,6 +793,8 @@ private:
return ret;
}
+private:
+
Address memorySize; // in pages
template <class LS>
diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp
index 2aacd94d4..83956e47e 100644
--- a/src/wasm-js.cpp
+++ b/src/wasm-js.cpp
@@ -195,10 +195,23 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() {
target.set(source, $0);
}, ConstantExpressionRunner().visit(segment.offset).value.geti32(), &segment.data[0], segment.data.size());
}
+ // Table support is in a JS array. If the entry is a number, it's a function pointer. If not, it's a JS method to be called directly
+ // TODO: make them all JS methods, wrapping a dynCall where necessary?
+ EM_ASM_({
+ Module['outside']['wasmTable'] = new Array($0);
+ }, wasm.table.initial);
+ for (auto segment : wasm.table.segments) {
+ Address offset = ConstantExpressionRunner().visit(segment.offset).value.geti32();
+ assert(offset + segment.data.size() <= wasm.table.initial);
+ for (size_t i = 0; i != segment.data.size(); ++i) {
+ EM_ASM_({
+ Module['outside']['wasmTable'][$0] = $1;
+ }, offset + i, wasm.getFunction(segment.data[i]));
+ }
+ }
}
- Literal callImport(Import *import, LiteralList& arguments) override {
- if (wasmJSDebug) std::cout << "calling import " << import->name.str << '\n';
+ void prepareTempArgments(LiteralList& arguments) {
EM_ASM({
Module['tempArguments'] = [];
});
@@ -213,6 +226,21 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() {
abort();
}
}
+ }
+
+ Literal getResultFromJS(double ret, WasmType type) {
+ switch (type) {
+ case none: return Literal(0);
+ case i32: return Literal((int32_t)ret);
+ case f32: return Literal((float)ret);
+ case f64: return Literal((double)ret);
+ default: abort();
+ }
+ }
+
+ Literal callImport(Import *import, LiteralList& arguments) override {
+ if (wasmJSDebug) std::cout << "calling import " << import->name.str << '\n';
+ prepareTempArgments(arguments);
double ret = EM_ASM_DOUBLE({
var mod = Pointer_stringify($0);
var base = Pointer_stringify($1);
@@ -224,12 +252,36 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() {
if (wasmJSDebug) std::cout << "calling import returning " << ret << '\n';
- switch (import->type->result) {
- case none: return Literal(0);
- case i32: return Literal((int32_t)ret);
- case f32: return Literal((float)ret);
- case f64: return Literal((double)ret);
- default: abort();
+ return getResultFromJS(ret, import->type->result);
+ }
+
+ Literal callTable(Index index, Name type, LiteralList& arguments, ModuleInstance& instance) override {
+ void* ptr = (void*)EM_ASM_INT({
+ var value = Module['outside']['wasmTable'][$0];
+ return typeof value === "number" ? value : -1;
+ }, index);
+ if (ptr == nullptr) trap("callTable overflow");
+ if (ptr != (void*)-1) {
+ // a Function we can call
+ Function* func = (Function*)ptr;
+ if (func->type.is() && func->type != type) trap("callIndirect: bad type");
+ if (func->params.size() != arguments.size()) trap("callIndirect: bad # of arguments");
+ for (size_t i = 0; i < func->params.size(); i++) {
+ if (func->params[i] != arguments[i].type) {
+ trap("callIndirect: bad argument type");
+ }
+ }
+ return instance.callFunctionInternal(func->name, arguments);
+ } else {
+ // A JS function JS can call
+ prepareTempArgments(arguments);
+ double ret = EM_ASM_DOUBLE({
+ var func = Module['outside']['wasmTable'][$0];
+ var tempArguments = Module['tempArguments'];
+ Module['tempArguments'] = null;
+ return func.apply(null, tempArguments);
+ }, index);
+ return getResultFromJS(ret, instance.wasm.getFunctionType(type)->result);
}
}
diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp
index 29f439bfb..2c9a4cd4d 100644
--- a/src/wasm-linker.cpp
+++ b/src/wasm-linker.cpp
@@ -132,7 +132,7 @@ void Linker::layout() {
// Emit the pre-assigned function names in sorted order
for (const auto& P : functionNames) {
- out.wasm.table.names.push_back(P.second);
+ getTableSegment().data.push_back(P.second);
}
for (auto& relocation : out.relocations) {
@@ -206,9 +206,11 @@ void Linker::layout() {
}
// ensure an explicit function type for indirect call targets
- for (auto& name : out.wasm.table.names) {
- auto* func = out.wasm.getFunction(name);
- func->type = ensureFunctionType(getSig(func), &out.wasm)->name;
+ for (auto& segment : out.wasm.table.segments) {
+ for (auto& name : segment.data) {
+ auto* func = out.wasm.getFunction(name);
+ func->type = ensureFunctionType(getSig(func), &out.wasm)->name;
+ }
}
// Export malloc and free whenever availble. JavsScript version of malloc has
@@ -225,7 +227,9 @@ void Linker::layout() {
}
// finalize function table
- out.wasm.table.initial = out.wasm.table.max = out.wasm.table.names.size();
+ if (out.wasm.table.segments.size() > 0) {
+ out.wasm.table.initial = out.wasm.table.max = getTableSegment().data.size();
+ }
}
bool Linker::linkObject(S2WasmBuilder& builder) {
@@ -385,10 +389,19 @@ void Linker::emscriptenGlue(std::ostream& o) {
o << " }\n";
}
+Table::Segment& Linker::getTableSegment() {
+ if (out.wasm.table.segments.size() == 0) {
+ out.wasm.table.segments.emplace_back(out.wasm.allocator.alloc<Const>()->set(Literal(uint32_t(0))));
+ } else {
+ assert(out.wasm.table.segments.size() == 1);
+ }
+ return out.wasm.table.segments[0];
+}
+
Index Linker::getFunctionIndex(Name name) {
if (!functionIndexes.count(name)) {
- functionIndexes[name] = out.wasm.table.names.size();
- out.wasm.table.names.push_back(name);
+ functionIndexes[name] = getTableSegment().data.size();
+ getTableSegment().data.push_back(name);
if (debug) {
std::cerr << "function index: " << name << ": "
<< functionIndexes[name] << '\n';
@@ -406,7 +419,6 @@ bool hasI64ResultOrParam(FunctionType* ft) {
}
void Linker::makeDummyFunction() {
- assert(out.wasm.table.names.empty());
bool create = false;
// Check if there are address-taken functions
for (auto& relocation : out.relocations) {
@@ -424,9 +436,10 @@ void Linker::makeDummyFunction() {
}
void Linker::makeDynCallThunks() {
+ if (out.wasm.table.segments.size() == 0) return;
std::unordered_set<std::string> sigs;
wasm::Builder wasmBuilder(out.wasm);
- for (const auto& indirectFunc : out.wasm.table.names) {
+ for (const auto& indirectFunc : getTableSegment().data) {
// Skip generating thunks for the dummy function
if (indirectFunc == dummyFunction) continue;
std::string sig(getSig(out.wasm.getFunction(indirectFunc)));
diff --git a/src/wasm-linker.h b/src/wasm-linker.h
index bf76a8f94..a6f5d319a 100644
--- a/src/wasm-linker.h
+++ b/src/wasm-linker.h
@@ -282,6 +282,10 @@ class Linker {
void ensureImport(Name target, std::string signature);
+ // Makes sure the table has a single segment, with offset 0,
+ // to which we can add content.
+ Table::Segment& getTableSegment();
+
// Retrieves (and assigns) an entry index in the indirect function table for
// a given function.
Index getFunctionIndex(Name name);
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 7f652da5a..b70f70b4e 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -1430,7 +1430,7 @@ private:
if (s[1]->str() == ANYFUNC) {
// (table type (elem ..))
parseElem(*s[2]);
- wasm.table.initial = wasm.table.max = wasm.table.names.size();
+ wasm.table.initial = wasm.table.max = wasm.table.segments[0].data.size();
return;
}
// first element isn't dollared, and isn't anyfunc. this could be old syntax for (table 0 1) which means function 0 and 1, or it could be (table initial max? type), look for type
@@ -1443,13 +1443,23 @@ private:
}
// old notation (table func1 func2 ..)
parseElem(s);
- wasm.table.initial = wasm.table.max = wasm.table.names.size();
+ wasm.table.initial = wasm.table.max = wasm.table.segments[0].data.size();
}
void parseElem(Element& s) {
- for (Index i = 1; i < s.size(); i++) {
- wasm.table.names.push_back(getFunctionName(*s[i]));
+ Index i = 1;
+ Expression* offset;
+ if (s[i]->isList()) {
+ // there is an init expression
+ offset = parseExpression(s[i++]);
+ } else {
+ offset = allocator.alloc<Const>()->set(Literal(int32_t(0)));
+ }
+ Table::Segment segment(offset);
+ for (; i < s.size(); i++) {
+ segment.data.push_back(getFunctionName(*s[i]));
}
+ wasm.table.segments.push_back(segment);
}
void parseType(Element& s) {
diff --git a/src/wasm.h b/src/wasm.h
index 82933bda0..68558033d 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1434,8 +1434,19 @@ class Table {
public:
static const Index kMaxSize = Index(-1);
+ struct Segment {
+ Expression* offset;
+ std::vector<Name> data;
+ Segment() {}
+ Segment(Expression* offset) : offset(offset) {
+ }
+ Segment(Expression* offset, std::vector<Name>& init) : offset(offset) {
+ data.swap(init);
+ }
+ };
+
Address initial, max;
- std::vector<Name> names;
+ std::vector<Segment> segments;
Table() : initial(0), max(kMaxSize) {}
};
@@ -1445,6 +1456,7 @@ public:
static const Address::address_t kPageSize = 64 * 1024;
static const Address::address_t kMaxSize = ~Address::address_t(0) / kPageSize;
static const Address::address_t kPageMask = ~(kPageSize - 1);
+
struct Segment {
Expression* offset;
std::vector<char> data; // TODO: optimize
diff --git a/test/dot_s/alias.wast b/test/dot_s/alias.wast
index ab52137a1..8ba469564 100644
--- a/test/dot_s/alias.wast
+++ b/test/dot_s/alias.wast
@@ -7,7 +7,7 @@
(export "__needs_exit" $__needs_exit)
(export "dynCall_v" $dynCall_v)
(table 2 2 anyfunc)
- (elem $__wasm_nullptr $__exit)
+ (elem (i32.const 0) $__wasm_nullptr $__exit)
(func $__exit (type $FUNCSIG$v)
(return
(i32.add
diff --git a/test/dot_s/basics.wast b/test/dot_s/basics.wast
index e4cd73251..3562140fb 100644
--- a/test/dot_s/basics.wast
+++ b/test/dot_s/basics.wast
@@ -11,7 +11,7 @@
(export "main" $main)
(export "dynCall_iii" $dynCall_iii)
(table 2 2 anyfunc)
- (elem $__wasm_nullptr $main)
+ (elem (i32.const 0) $__wasm_nullptr $main)
(func $main (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(call_import $puts
(i32.const 16)
diff --git a/test/dot_s/bcp-1.wast b/test/dot_s/bcp-1.wast
index a5a63d750..1b76a98af 100644
--- a/test/dot_s/bcp-1.wast
+++ b/test/dot_s/bcp-1.wast
@@ -35,7 +35,7 @@
(export "dynCall_i" $dynCall_i)
(export "dynCall_ii" $dynCall_ii)
(table 18 18 anyfunc)
- (elem $__wasm_nullptr $bad0 $bad1 $bad5 $bad7 $bad8 $bad10 $bad2 $bad3 $bad6 $bad4 $bad9 $good0 $good1 $good2 $opt0 $opt1 $opt2)
+ (elem (i32.const 0) $__wasm_nullptr $bad0 $bad1 $bad5 $bad7 $bad8 $bad10 $bad2 $bad3 $bad6 $bad4 $bad9 $good0 $good1 $good2 $opt0 $opt1 $opt2)
(func $bad0 (type $FUNCSIG$i) (result i32)
(return
(i32.const 0)
diff --git a/test/dot_s/dyncall.wast b/test/dot_s/dyncall.wast
index f349bce7f..c6dae687a 100644
--- a/test/dot_s/dyncall.wast
+++ b/test/dot_s/dyncall.wast
@@ -16,7 +16,7 @@
(export "dynCall_if" $dynCall_if)
(export "dynCall_vd" $dynCall_vd)
(table 6 6 anyfunc)
- (elem $__wasm_nullptr $i $i_f $vd $ffjjdi $vd2)
+ (elem (i32.const 0) $__wasm_nullptr $i $i_f $vd $ffjjdi $vd2)
(func $i (type $FUNCSIG$i) (result i32)
(i32.const 0)
)
diff --git a/test/dot_s/indidx.wast b/test/dot_s/indidx.wast
index 797183b04..6cdb6c4ce 100644
--- a/test/dot_s/indidx.wast
+++ b/test/dot_s/indidx.wast
@@ -8,7 +8,7 @@
(export "main" $main)
(export "dynCall_i" $dynCall_i)
(table 5 5 anyfunc)
- (elem $__wasm_nullptr $c $b $d $a)
+ (elem (i32.const 0) $__wasm_nullptr $c $b $d $a)
(func $a (type $FUNCSIG$i) (result i32)
(i32.const 0)
)
diff --git a/test/dot_s/indirect-import.wast b/test/dot_s/indirect-import.wast
index 8c8c3e01c..86c8ded00 100644
--- a/test/dot_s/indirect-import.wast
+++ b/test/dot_s/indirect-import.wast
@@ -18,7 +18,7 @@
(export "dynCall_v" $dynCall_v)
(export "dynCall_vi" $dynCall_vi)
(table 7 7 anyfunc)
- (elem $__wasm_nullptr $__importThunk_extern_fd $__importThunk_extern_vj $__importThunk_extern_v $__importThunk_extern_ijidf $__importThunk_extern_struct $__importThunk_extern_sret)
+ (elem (i32.const 0) $__wasm_nullptr $__importThunk_extern_fd $__importThunk_extern_vj $__importThunk_extern_v $__importThunk_extern_ijidf $__importThunk_extern_struct $__importThunk_extern_sret)
(func $bar (result i32)
(local $0 i32)
(local $1 i32)
diff --git a/test/dot_s/invoke_wrapper.wast b/test/dot_s/invoke_wrapper.wast
index c4a6d5931..d54e94d03 100644
--- a/test/dot_s/invoke_wrapper.wast
+++ b/test/dot_s/invoke_wrapper.wast
@@ -18,7 +18,7 @@
(export "dynCall_ffd" $dynCall_ffd)
(export "dynCall_iii" $dynCall_iii)
(table 5 5 anyfunc)
- (elem $__wasm_nullptr $_Z5func1v $_Z5func2iii $_Z5func3fd $_Z5func4P8mystructS_)
+ (elem (i32.const 0) $__wasm_nullptr $_Z5func1v $_Z5func2iii $_Z5func3fd $_Z5func4P8mystructS_)
(func $_Z5func1v (type $FUNCSIG$v)
)
(func $_Z5func2iii (type $FUNCSIG$iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
diff --git a/test/emcc_O2_hello_world.fromasm b/test/emcc_O2_hello_world.fromasm
index a324f42ba..49d63fa8c 100644
--- a/test/emcc_O2_hello_world.fromasm
+++ b/test/emcc_O2_hello_world.fromasm
@@ -43,7 +43,7 @@
(export "dynCall_iiii" $dynCall_iiii)
(export "dynCall_vi" $dynCall_vi)
(table 18 18 anyfunc)
- (elem $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2)
+ (elem (i32.const 0) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2)
(func $_malloc (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
diff --git a/test/emcc_O2_hello_world.fromasm.imprecise b/test/emcc_O2_hello_world.fromasm.imprecise
index 127b7f77f..4f0513d28 100644
--- a/test/emcc_O2_hello_world.fromasm.imprecise
+++ b/test/emcc_O2_hello_world.fromasm.imprecise
@@ -42,7 +42,7 @@
(export "dynCall_iiii" $dynCall_iiii)
(export "dynCall_vi" $dynCall_vi)
(table 18 18 anyfunc)
- (elem $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2)
+ (elem (i32.const 0) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2)
(func $_malloc (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
diff --git a/test/emcc_O2_hello_world.fromasm.imprecise.no-opts b/test/emcc_O2_hello_world.fromasm.imprecise.no-opts
index 6822928b3..494915489 100644
--- a/test/emcc_O2_hello_world.fromasm.imprecise.no-opts
+++ b/test/emcc_O2_hello_world.fromasm.imprecise.no-opts
@@ -42,7 +42,7 @@
(export "dynCall_iiii" $dynCall_iiii)
(export "dynCall_vi" $dynCall_vi)
(table 18 18 anyfunc)
- (elem $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2)
+ (elem (i32.const 0) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2)
(func $_malloc (param $i1 i32) (result i32)
(local $i2 i32)
(local $i3 i32)
diff --git a/test/emcc_O2_hello_world.fromasm.no-opts b/test/emcc_O2_hello_world.fromasm.no-opts
index 6c6ad73c7..e75c5e4b2 100644
--- a/test/emcc_O2_hello_world.fromasm.no-opts
+++ b/test/emcc_O2_hello_world.fromasm.no-opts
@@ -43,7 +43,7 @@
(export "dynCall_iiii" $dynCall_iiii)
(export "dynCall_vi" $dynCall_vi)
(table 18 18 anyfunc)
- (elem $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2)
+ (elem (i32.const 0) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2)
(func $_malloc (param $i1 i32) (result i32)
(local $i2 i32)
(local $i3 i32)
diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm
index 9d4993ec3..1ef3b9017 100644
--- a/test/emcc_hello_world.fromasm
+++ b/test/emcc_hello_world.fromasm
@@ -56,7 +56,7 @@
(export "dynCall_vi" $dynCall_vi)
(export "___udivmoddi4" $___udivmoddi4)
(table 18 18 anyfunc)
- (elem $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2)
+ (elem (i32.const 0) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2)
(func $stackAlloc (param $0 i32) (result i32)
(local $1 i32)
(set_local $1
diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise
index 6c9047895..13c8baec6 100644
--- a/test/emcc_hello_world.fromasm.imprecise
+++ b/test/emcc_hello_world.fromasm.imprecise
@@ -50,7 +50,7 @@
(export "dynCall_vi" $dynCall_vi)
(export "___udivmoddi4" $___udivmoddi4)
(table 18 18 anyfunc)
- (elem $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2)
+ (elem (i32.const 0) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2)
(func $stackAlloc (param $0 i32) (result i32)
(local $1 i32)
(set_local $1
diff --git a/test/emcc_hello_world.fromasm.imprecise.no-opts b/test/emcc_hello_world.fromasm.imprecise.no-opts
index 35e23d120..d8b887891 100644
--- a/test/emcc_hello_world.fromasm.imprecise.no-opts
+++ b/test/emcc_hello_world.fromasm.imprecise.no-opts
@@ -50,7 +50,7 @@
(export "dynCall_vi" $dynCall_vi)
(export "___udivmoddi4" $___udivmoddi4)
(table 18 18 anyfunc)
- (elem $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2)
+ (elem (i32.const 0) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2)
(func $stackAlloc (param $size i32) (result i32)
(local $ret i32)
(set_local $ret
diff --git a/test/emcc_hello_world.fromasm.no-opts b/test/emcc_hello_world.fromasm.no-opts
index 27409fe49..efa2de849 100644
--- a/test/emcc_hello_world.fromasm.no-opts
+++ b/test/emcc_hello_world.fromasm.no-opts
@@ -56,7 +56,7 @@
(export "dynCall_vi" $dynCall_vi)
(export "___udivmoddi4" $___udivmoddi4)
(table 18 18 anyfunc)
- (elem $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2)
+ (elem (i32.const 0) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2)
(func $stackAlloc (param $size i32) (result i32)
(local $ret i32)
(set_local $ret
diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt
index 6b766f173..42a5bfee1 100644
--- a/test/example/c-api-kitchen-sink.txt
+++ b/test/example/c-api-kitchen-sink.txt
@@ -18,7 +18,7 @@ BinaryenFloat64: 4
(import $an-imported "module" "base" (param i32 f64) (result f32))
(export "kitchen_sinker" "$kitchen()sinker")
(table 1 1 anyfunc)
- (elem "$kitchen()sinker")
+ (elem (i32.const 0) "$kitchen()sinker")
(func "$kitchen()sinker" (type $iiIfF) (param $0 i32) (param $1 i64) (param $2 f32) (param $3 f64) (result i32)
(local $4 i32)
(block $the-body
@@ -1411,7 +1411,7 @@ int main() {
(import $an-imported "module" "base" (param i32 f64) (result f32))
(export "kitchen_sinker" "$kitchen()sinker")
(table 1 1 anyfunc)
- (elem "$kitchen()sinker")
+ (elem (i32.const 0) "$kitchen()sinker")
(func "$kitchen()sinker" (type $iiIfF) (param $0 i32) (param $1 i64) (param $2 f32) (param $3 f64) (result i32)
(local $4 i32)
(block $the-body
diff --git a/test/example/c-api-kitchen-sink.txt.txt b/test/example/c-api-kitchen-sink.txt.txt
index feae7152c..7e32ba431 100644
--- a/test/example/c-api-kitchen-sink.txt.txt
+++ b/test/example/c-api-kitchen-sink.txt.txt
@@ -13,7 +13,7 @@
(import $an-imported "module" "base" (param i32 f64) (result f32))
(export "kitchen_sinker" "$kitchen()sinker")
(table 1 1 anyfunc)
- (elem "$kitchen()sinker")
+ (elem (i32.const 0) "$kitchen()sinker")
(func "$kitchen()sinker" (type $iiIfF) (param $0 i32) (param $1 i64) (param $2 f32) (param $3 f64) (result i32)
(local $4 i32)
(block $the-body
diff --git a/test/memorygrowth.fromasm b/test/memorygrowth.fromasm
index ee6b3ae68..c07cc247e 100644
--- a/test/memorygrowth.fromasm
+++ b/test/memorygrowth.fromasm
@@ -41,7 +41,7 @@
(export "dynCall_vi" $mb)
(export "__growWasmMemory" $__growWasmMemory)
(table 8 8 anyfunc)
- (elem $nb $Oa $ob $Va $Ua $Ra $pb $Sa)
+ (elem (i32.const 0) $nb $Oa $ob $Va $Ua $Ra $pb $Sa)
(func $eb (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
diff --git a/test/memorygrowth.fromasm.imprecise b/test/memorygrowth.fromasm.imprecise
index 458ab8f8f..5482b08f6 100644
--- a/test/memorygrowth.fromasm.imprecise
+++ b/test/memorygrowth.fromasm.imprecise
@@ -40,7 +40,7 @@
(export "dynCall_vi" $mb)
(export "__growWasmMemory" $__growWasmMemory)
(table 8 8 anyfunc)
- (elem $nb $Oa $ob $Va $Ua $Ra $pb $Sa)
+ (elem (i32.const 0) $nb $Oa $ob $Va $Ua $Ra $pb $Sa)
(func $eb (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
diff --git a/test/memorygrowth.fromasm.imprecise.no-opts b/test/memorygrowth.fromasm.imprecise.no-opts
index c30a5933b..ddd73a5f8 100644
--- a/test/memorygrowth.fromasm.imprecise.no-opts
+++ b/test/memorygrowth.fromasm.imprecise.no-opts
@@ -40,7 +40,7 @@
(export "dynCall_vi" $mb)
(export "__growWasmMemory" $__growWasmMemory)
(table 8 8 anyfunc)
- (elem $nb $Oa $ob $Va $Ua $Ra $pb $Sa)
+ (elem (i32.const 0) $nb $Oa $ob $Va $Ua $Ra $pb $Sa)
(func $eb (param $a i32) (result i32)
(local $b i32)
(local $c i32)
diff --git a/test/memorygrowth.fromasm.no-opts b/test/memorygrowth.fromasm.no-opts
index 3abed2662..c0a7307c5 100644
--- a/test/memorygrowth.fromasm.no-opts
+++ b/test/memorygrowth.fromasm.no-opts
@@ -41,7 +41,7 @@
(export "dynCall_vi" $mb)
(export "__growWasmMemory" $__growWasmMemory)
(table 8 8 anyfunc)
- (elem $nb $Oa $ob $Va $Ua $Ra $pb $Sa)
+ (elem (i32.const 0) $nb $Oa $ob $Va $Ua $Ra $pb $Sa)
(func $eb (param $a i32) (result i32)
(local $b i32)
(local $c i32)
diff --git a/test/passes/dce.txt b/test/passes/dce.txt
index 9c2836123..9ae5977b6 100644
--- a/test/passes/dce.txt
+++ b/test/passes/dce.txt
@@ -3,7 +3,7 @@
(type $ii (func (param i32 i32)))
(type $1 (func))
(table 1 1 anyfunc)
- (elem $call-me)
+ (elem (i32.const 0) $call-me)
(func $call-me (type $ii) (param $0 i32) (param $1 i32)
(nop)
)
diff --git a/test/passes/duplicate-function-elimination.txt b/test/passes/duplicate-function-elimination.txt
index 6c64b081c..a7511fc5c 100644
--- a/test/passes/duplicate-function-elimination.txt
+++ b/test/passes/duplicate-function-elimination.txt
@@ -39,7 +39,7 @@
(export "keep2" $keep2)
(export "other" $keep2)
(table 3 3 anyfunc)
- (elem $keep2 $keep2 $caller)
+ (elem (i32.const 0) $keep2 $keep2 $caller)
(func $keep2 (type $0)
(nop)
)
@@ -365,7 +365,7 @@
(memory 0)
(type $T (func))
(table 2 2 anyfunc)
- (elem $erase $erase)
+ (elem (i32.const 0) $erase $erase)
(func $erase (type $T)
(call_indirect $T
(i32.const 0)
@@ -376,7 +376,7 @@
(memory 0)
(type $T (func))
(table 2 2 anyfunc)
- (elem $keep2 $other)
+ (elem (i32.const 0) $keep2 $other)
(func $keep2 (type $T)
(call_indirect $T
(i32.const 0)
@@ -393,7 +393,7 @@
(type $T (func))
(type $S (func))
(table 2 2 anyfunc)
- (elem $keep2 $other)
+ (elem (i32.const 0) $keep2 $other)
(func $keep2 (type $T)
(call_indirect $T
(i32.const 0)
diff --git a/test/passes/remove-unused-functions.txt b/test/passes/remove-unused-functions.txt
index 6aa8e3265..cd819d347 100644
--- a/test/passes/remove-unused-functions.txt
+++ b/test/passes/remove-unused-functions.txt
@@ -4,7 +4,7 @@
(type $0 (func))
(export "exported" $exported)
(table 1 1 anyfunc)
- (elem $called_indirect)
+ (elem (i32.const 0) $called_indirect)
(func $start (type $0)
(call $called0)
)
diff --git a/test/passes/remove-unused-names_merge-blocks.txt b/test/passes/remove-unused-names_merge-blocks.txt
index ead2c99ca..88d284a5a 100644
--- a/test/passes/remove-unused-names_merge-blocks.txt
+++ b/test/passes/remove-unused-names_merge-blocks.txt
@@ -5,7 +5,7 @@
(type $iii (func (param i32 i32 i32)))
(type $3 (func))
(table 1 1 anyfunc)
- (elem $call-i)
+ (elem (i32.const 0) $call-i)
(func $call-i (type $i) (param $0 i32)
(nop)
)
diff --git a/test/unit.fromasm b/test/unit.fromasm
index e292f47ae..49189df43 100644
--- a/test/unit.fromasm
+++ b/test/unit.fromasm
@@ -16,7 +16,7 @@
(export "big_negative" $big_negative)
(export "pick" $big_negative)
(table 10 10 anyfunc)
- (elem $big_negative $big_negative $big_negative $big_negative $big_negative $big_negative $importedDoubles $big_negative $big_negative $cneg)
+ (elem (i32.const 0) $big_negative $big_negative $big_negative $big_negative $big_negative $big_negative $importedDoubles $big_negative $big_negative $cneg)
(func $big_negative
(nop)
)
diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise
index ef3c09ff0..d2c10b549 100644
--- a/test/unit.fromasm.imprecise
+++ b/test/unit.fromasm.imprecise
@@ -12,7 +12,7 @@
(export "big_negative" $big_negative)
(export "pick" $big_negative)
(table 10 10 anyfunc)
- (elem $big_negative $big_negative $big_negative $big_negative $big_negative $big_negative $importedDoubles $big_negative $big_negative $cneg)
+ (elem (i32.const 0) $big_negative $big_negative $big_negative $big_negative $big_negative $big_negative $importedDoubles $big_negative $big_negative $cneg)
(func $big_negative
(nop)
)
diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts
index cde7eb176..7037a6c1c 100644
--- a/test/unit.fromasm.imprecise.no-opts
+++ b/test/unit.fromasm.imprecise.no-opts
@@ -12,7 +12,7 @@
(export "big_negative" $big_negative)
(export "pick" $exportMe)
(table 10 10 anyfunc)
- (elem $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg)
+ (elem (i32.const 0) $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg)
(func $big_negative
(local $temp f64)
(set_local $temp
diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts
index c0650ebd5..51ae345b9 100644
--- a/test/unit.fromasm.no-opts
+++ b/test/unit.fromasm.no-opts
@@ -16,7 +16,7 @@
(export "big_negative" $big_negative)
(export "pick" $exportMe)
(table 10 10 anyfunc)
- (elem $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg)
+ (elem (i32.const 0) $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg)
(func $big_negative
(local $temp f64)
(set_local $temp
diff --git a/test/unit.wast b/test/unit.wast
index 30d16d1a2..2e21d44dd 100644
--- a/test/unit.wast
+++ b/test/unit.wast
@@ -14,7 +14,7 @@
(import $f64-rem "asm2wasm" "f64-rem" (param f64 f64) (result f64))
(export "big_negative" $big_negative)
(table 10 anyfunc)
- (elem $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg)
+ (elem (i32.const 0) $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg)
(func $big_negative (type $FUNCSIG$v)
(local $temp f64)
(block $block0
diff --git a/test/unit.wast.fromBinary b/test/unit.wast.fromBinary
index 4348394af..29d53598a 100644
--- a/test/unit.wast.fromBinary
+++ b/test/unit.wast.fromBinary
@@ -13,8 +13,8 @@
(import $import$1 "asm2wasm" "f64-to-int" (param f64) (result i32))
(import $import$2 "asm2wasm" "f64-rem" (param f64 f64) (result f64))
(export "big_negative" $big_negative)
- (table 10 10 anyfunc)
- (elem $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg)
+ (table 10 anyfunc)
+ (elem (i32.const 0) $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg)
(func $big_negative (type $1)
(local $var$0 f64)
(block $label$0