summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/binaryen-shell.cpp108
-rw-r--r--src/wasm-binary.h17
-rw-r--r--src/wasm-interpreter.h4
-rw-r--r--src/wasm-validator.h15
m---------test/spec0
5 files changed, 94 insertions, 50 deletions
diff --git a/src/binaryen-shell.cpp b/src/binaryen-shell.cpp
index 4c973c50e..d450e4db7 100644
--- a/src/binaryen-shell.cpp
+++ b/src/binaryen-shell.cpp
@@ -242,20 +242,24 @@ static void run_asserts(size_t* i, bool* checked, AllocatingModule* wasm,
std::unique_ptr<SExpressionWasmBuilder>* builder,
bool print_before, bool print_after,
Name entry) {
- auto interface = new ShellExternalInterface();
- auto instance = new ModuleInstance(*wasm, interface);
- if (entry.is() > 0) {
- Function* function = wasm->functionsMap[entry];
- if (!function) {
- std::cerr << "Unknown entry " << entry << std::endl;
- } else {
- ModuleInstance::LiteralList arguments;
- for (NameType param : function->params) {
- arguments.push_back(Literal(param.type));
- }
- try {
- instance->callExport(entry, arguments);
- } catch (ExitException& x) {
+ ShellExternalInterface* interface = nullptr;
+ ModuleInstance* instance = nullptr;
+ if (wasm) {
+ interface = new ShellExternalInterface();
+ instance = new ModuleInstance(*wasm, interface);
+ if (entry.is() > 0) {
+ Function* function = wasm->functionsMap[entry];
+ if (!function) {
+ std::cerr << "Unknown entry " << entry << std::endl;
+ } else {
+ ModuleInstance::LiteralList arguments;
+ for (NameType param : function->params) {
+ arguments.push_back(Literal(param.type));
+ }
+ try {
+ instance->callExport(entry, arguments);
+ } catch (ExitException& x) {
+ }
}
}
}
@@ -280,12 +284,14 @@ static void run_asserts(size_t* i, bool* checked, AllocatingModule* wasm,
std::cout << wasm;
}
bool invalid = false;
+ std::unique_ptr<SExpressionWasmBuilder> builder;
try {
- *builder = std::unique_ptr<SExpressionWasmBuilder>(
- new SExpressionWasmBuilder(wasm, *curr[1], [&]() {
- invalid = true;
- throw ParseException();
- }));
+ builder = std::unique_ptr<SExpressionWasmBuilder>(
+ new SExpressionWasmBuilder(wasm, *curr[1], [&]() {
+ invalid = true;
+ throw ParseException();
+ })
+ );
} catch (const ParseException& e) {
invalid = true;
}
@@ -295,10 +301,12 @@ static void run_asserts(size_t* i, bool* checked, AllocatingModule* wasm,
}
assert(invalid);
} else if (id == INVOKE) {
+ assert(wasm);
Invocation invocation(curr, instance, *builder->get());
invocation.invoke();
} else {
// an invoke test
+ assert(wasm);
bool trapped = false;
Literal result;
try {
@@ -390,39 +398,45 @@ int main(int argc, const char* argv[]) {
bool checked = false;
size_t i = 0;
while (i < root.size()) {
- if (options.debug) std::cerr << "parsing s-expressions to wasm...\n";
- AllocatingModule wasm;
- std::unique_ptr<SExpressionWasmBuilder> builder(
- new SExpressionWasmBuilder(wasm, *root[i], [&]() { abort(); }, options.debug));
- i++;
-
- if (print_before) {
- Colors::bold(std::cout);
- std::cerr << "printing before:\n";
- Colors::normal(std::cout);
- std::cout << wasm;
- }
+ Element& curr = *root[i];
+ IString id = curr[0]->str();
+ if (id == MODULE) {
+ if (options.debug) std::cerr << "parsing s-expressions to wasm...\n";
+ AllocatingModule wasm;
+ std::unique_ptr<SExpressionWasmBuilder> builder(
+ new SExpressionWasmBuilder(wasm, *root[i], [&]() { abort(); }, options.debug));
+ i++;
+
+ if (print_before) {
+ Colors::bold(std::cout);
+ std::cerr << "printing before:\n";
+ Colors::normal(std::cout);
+ std::cout << wasm;
+ }
- MixedArena moreModuleAllocations;
+ MixedArena moreModuleAllocations;
- if (passes.size() > 0) {
- if (options.debug) std::cerr << "running passes...\n";
- PassRunner passRunner(&moreModuleAllocations);
- for (auto& passName : passes) {
- passRunner.add(passName);
+ if (passes.size() > 0) {
+ if (options.debug) std::cerr << "running passes...\n";
+ PassRunner passRunner(&moreModuleAllocations);
+ for (auto& passName : passes) {
+ passRunner.add(passName);
+ }
+ passRunner.run(&wasm);
}
- passRunner.run(&wasm);
- }
- if (print_after) {
- Colors::bold(std::cout);
- std::cerr << "printing after:\n";
- Colors::normal(std::cout);
- std::cout << wasm;
+ if (print_after) {
+ Colors::bold(std::cout);
+ std::cerr << "printing after:\n";
+ Colors::normal(std::cout);
+ std::cout << wasm;
+ }
+ run_asserts(&i, &checked, &wasm, &root, &builder, print_before,
+ print_after, entry);
+ } else {
+ run_asserts(&i, &checked, nullptr, &root, nullptr, print_before,
+ print_after, entry);
}
-
- run_asserts(&i, &checked, &wasm, &root, &builder, print_before,
- print_after, entry);
}
if (checked) {
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 2c884a4f5..b1db70a97 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -155,7 +155,8 @@ enum Section {
Functions = 2,
DataSegments = 4,
FunctionTable = 5,
- End = 6
+ End = 6,
+ Start = 7
};
enum FunctionEntry {
@@ -380,6 +381,7 @@ public:
}
void write() {
+ writeStart();
writeMemory();
writeSignatures();
writeFunctions();
@@ -389,6 +391,13 @@ public:
finishUp();
}
+ void writeStart() {
+ if (!wasm->start.is()) return;
+ if (debug) std::cerr << "== writeStart" << std::endl;
+ o << int8_t(BinaryConsts::Start);
+ emitString(wasm->start.str);
+ }
+
void writeMemory() {
if (wasm->memory.max == 0) return;
if (debug) std::cerr << "== writeMemory" << std::endl;
@@ -980,6 +989,7 @@ public:
}
switch (section) {
+ case BinaryConsts::Start: readStart(); break;
case BinaryConsts::Memory: readMemory(); break;
case BinaryConsts::Signatures: readSignatures(); break;
case BinaryConsts::Functions: readFunctions(); break;
@@ -1082,6 +1092,11 @@ public:
assert(x == y);
}
+ void readStart() {
+ if (debug) std::cerr << "== readStart" << std::endl;
+ wasm.start = getString();
+ }
+
void readMemory() {
if (debug) std::cerr << "== readMemory" << std::endl;
size_t initial = getInt8();
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 267615a55..59e42783d 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -100,6 +100,10 @@ public:
ModuleInstance(Module& wasm, ExternalInterface* externalInterface) : wasm(wasm), externalInterface(externalInterface) {
memorySize = wasm.memory.initial;
externalInterface->init(wasm);
+ if (wasm.start.is()) {
+ LiteralList arguments;
+ callFunction(wasm.start, arguments);
+ }
}
Literal callExport(IString name, LiteralList& arguments) {
diff --git a/src/wasm-validator.h b/src/wasm-validator.h
index fad33a081..04493bb5b 100644
--- a/src/wasm-validator.h
+++ b/src/wasm-validator.h
@@ -104,6 +104,7 @@ public:
shouldBeFalse(top > curr->initial);
}
void visitModule(Module *curr) {
+ // exports
for (auto& exp : curr->exports) {
Name name = exp->name;
bool found = false;
@@ -115,6 +116,14 @@ public:
}
shouldBeTrue(found);
}
+ // start
+ if (curr->start.is()) {
+ auto iter = curr->functionsMap.find(curr->start);
+ if (shouldBeTrue(iter != curr->functionsMap.end())) {
+ auto func = iter->second;
+ shouldBeTrue(func->params.size() == 0); // must be nullary
+ }
+ }
}
private:
@@ -135,11 +144,13 @@ private:
// helpers
- void shouldBeTrue(bool result) {
+ bool shouldBeTrue(bool result) {
if (!result) valid = false;
+ return result;
}
- void shouldBeFalse(bool result) {
+ bool shouldBeFalse(bool result) {
if (result) valid = false;
+ return result;
}
void validateAlignment(size_t align) {
diff --git a/test/spec b/test/spec
-Subproject 40558d388b7f99b0edf01d3cbb2a3d3efea3a41
+Subproject 09cd3e684629d6000bfbaf8dc17598bbd31b7e2