summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2015-11-05 13:04:15 -0800
committerAlon Zakai <alonzakai@gmail.com>2015-11-05 13:04:15 -0800
commita3df15c2c6e7cfad29ce41603f954573f0726659 (patch)
treeaa4e956e4889d85eae8399c38a16fe3b3fb39742 /src
parent4c7dc453f761391cc44646a5058036977272ca15 (diff)
downloadbinaryen-a3df15c2c6e7cfad29ce41603f954573f0726659.tar.gz
binaryen-a3df15c2c6e7cfad29ce41603f954573f0726659.tar.bz2
binaryen-a3df15c2c6e7cfad29ce41603f954573f0726659.zip
error callback in SExpressionWasmBuilder
Diffstat (limited to 'src')
-rw-r--r--src/wasm-s-parser.h39
-rw-r--r--src/wasm-shell.cpp62
2 files changed, 63 insertions, 38 deletions
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index e55ce9af1..6e383e17e 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -9,8 +9,6 @@
#include "wasm.h"
#include "mixed_arena.h"
-#define abort_on(str) { std::cerr << "aborting on " << str << '\n'; abort(); }
-
namespace wasm {
int debug;
@@ -193,9 +191,11 @@ class SExpressionWasmBuilder {
MixedArena allocator;
+ std::function<void ()> onError;
+
public:
// Assumes control of and modifies the input.
- SExpressionWasmBuilder(Module& wasm, Element& module) : wasm(wasm) {
+ SExpressionWasmBuilder(Module& wasm, Element& module, std::function<void ()> onError) : wasm(wasm), onError(onError) {
assert(module[0]->str() == MODULE);
for (unsigned i = 1; i < module.size(); i++) {
parseModuleElement(*module[i]);
@@ -213,14 +213,19 @@ private:
if (id == TABLE) return parseTable(curr);
if (id == TYPE) return parseType(curr);
std::cerr << "bad module element " << id.str << '\n';
- abort();
+ onError();
}
std::map<Name, WasmType> currLocalTypes;
void parseFunction(Element& s) {
auto func = allocator.alloc<Function>();
- func->name = s[1]->str();
+ if (s[1]->isStr()) {
+ func->name = s[1]->str();
+ } else {
+ // unnamed, use an index
+ func->name = IString(std::to_string(wasm.functions.size()).c_str(), false);
+ }
func->body = nullptr;
for (unsigned i = 2; i < s.size(); i++) {
Element& curr = *s[i];
@@ -256,11 +261,11 @@ private:
currLocalTypes.clear();
}
- static WasmType stringToWasmType(IString str) {
+ WasmType stringToWasmType(IString str) {
return stringToWasmType(str.str);
}
- static WasmType stringToWasmType(const char* str) {
+ WasmType stringToWasmType(const char* str) {
if (str[0] == 'i') {
if (str[1] == '3') return i32;
return i64;
@@ -269,6 +274,7 @@ private:
if (str[1] == '3') return f32;
return f64;
}
+ onError();
abort();
}
@@ -277,6 +283,8 @@ public:
return parseExpression(*s);
}
+ #define abort_on(str) { std::cerr << "aborting on " << str << '\n'; onError(); }
+
Expression* parseExpression(Element& s) {
//if (debug) std::cerr << "parse expression " << s << '\n';
IString id = s[0]->str();
@@ -387,7 +395,7 @@ public:
if (op[1] == 'r') {
if (op[6] == 's') return makeConvert(s, op[9] == '3' ? ConvertOp::TruncSFloat32 : ConvertOp::TruncSFloat64, type);
if (op[6] == 'u') return makeConvert(s, op[9] == '3' ? ConvertOp::TruncUFloat32 : ConvertOp::TruncUFloat64, type);
- abort();
+ onError();
}
abort_on(op);
}
@@ -440,6 +448,7 @@ public:
default: abort_on(str);
}
}
+ abort();
}
private:
@@ -513,7 +522,7 @@ private:
switch (type) {
case f32: ret->value.f32 = std::numeric_limits<float>::infinity(); break;
case f64: ret->value.f64 = std::numeric_limits<double>::infinity(); break;
- default: abort();
+ default: onError();
}
return ret;
}
@@ -521,7 +530,7 @@ private:
switch (type) {
case f32: ret->value.f32 = -std::numeric_limits<float>::infinity(); break;
case f64: ret->value.f64 = -std::numeric_limits<double>::infinity(); break;
- default: abort();
+ default: onError();
}
return ret;
}
@@ -529,7 +538,7 @@ private:
switch (type) {
case f32: ret->value.f32 = std::nan(""); break;
case f64: ret->value.f64 = std::nan(""); break;
- default: abort();
+ default: onError();
}
return ret;
}
@@ -567,7 +576,7 @@ private:
}
case f32: ret->value.f32 = std::stof(str, &size); break;
case f64: ret->value.f64 = std::stod(str, &size); break;
- default: abort();
+ default: onError();
}
return ret;
}
@@ -602,7 +611,7 @@ private:
ret->align = atoi(eq);
} else if (str[0] == 'o') {
ret->offset = atoi(eq);
- } else abort();
+ } else onError();
i++;
}
ret->ptr = parseExpression(s[i]);
@@ -638,7 +647,7 @@ private:
ret->align = atoi(eq);
} else if (str[0] == 'o') {
ret->offset = atoi(eq);
- } else abort();
+ } else onError();
i++;
}
ret->ptr = parseExpression(s[i]);
@@ -747,7 +756,7 @@ private:
im.type.params.push_back(stringToWasmType(params[i]->str()));
}
} else {
- abort();
+ onError();
}
assert(s.size() == 5);
wasm.imports[im.name] = im;
diff --git a/src/wasm-shell.cpp b/src/wasm-shell.cpp
index 160d58288..fd6adcfaf 100644
--- a/src/wasm-shell.cpp
+++ b/src/wasm-shell.cpp
@@ -13,6 +13,7 @@ using namespace wasm;
IString ASSERT_RETURN("assert_return"),
ASSERT_TRAP("assert_trap"),
+ ASSERT_INVALID("assert_invalid"),
PRINT("print"),
INVOKE("invoke");
@@ -141,7 +142,7 @@ int main(int argc, char **argv) {
while (i < root.size()) {
if (debug) std::cerr << "parsing s-expressions to wasm...\n";
Module wasm;
- SExpressionWasmBuilder builder(wasm, *root[i]);
+ SExpressionWasmBuilder builder(wasm, *root[i], [&]() { abort(); });
i++;
auto interface = new ShellExternalInterface();
@@ -163,31 +164,46 @@ int main(int argc, char **argv) {
std::cerr << " CHECKING: ";
Colors::normal(std::cerr);
std::cerr << curr << '\n';
- Element& invoke = *curr[1];
- assert(invoke[0]->str() == INVOKE);
- IString name = invoke[1]->str();
- ModuleInstance::LiteralList arguments;
- for (size_t j = 2; j < invoke.size(); j++) {
- Expression* argument = builder.parseExpression(*invoke[2]);
- arguments.push_back(argument->dyn_cast<Const>()->value);
- }
- bool trapped = false;
- Literal result;
- if (setjmp(interface->trapState) == 0) {
- result = instance->callFunction(name, arguments);
+ if (id == ASSERT_INVALID) {
+ // a module invalidity test
+ Module wasm;
+ bool invalid = false;
+ jmp_buf trapState;
+ if (setjmp(trapState) == 0) {
+ SExpressionWasmBuilder builder(wasm, *curr[1], [&]() {
+ invalid = true;
+ longjmp(trapState, 1);
+ });
+ }
+ assert(invalid);
} else {
- trapped = true;
- }
- if (id == ASSERT_RETURN) {
- assert(!trapped);
- Literal expected;
- if (curr.size() >= 3) {
- expected = builder.parseExpression(*curr[2])->dyn_cast<Const>()->value;
+ // an invoke test
+ Element& invoke = *curr[1];
+ assert(invoke[0]->str() == INVOKE);
+ IString name = invoke[1]->str();
+ ModuleInstance::LiteralList arguments;
+ for (size_t j = 2; j < invoke.size(); j++) {
+ Expression* argument = builder.parseExpression(*invoke[2]);
+ arguments.push_back(argument->dyn_cast<Const>()->value);
+ }
+ bool trapped = false;
+ Literal result;
+ if (setjmp(interface->trapState) == 0) {
+ result = instance->callFunction(name, arguments);
+ } else {
+ trapped = true;
+ }
+ if (id == ASSERT_RETURN) {
+ assert(!trapped);
+ Literal expected;
+ if (curr.size() >= 3) {
+ expected = builder.parseExpression(*curr[2])->dyn_cast<Const>()->value;
+ }
+ std::cerr << "seen " << result << ", expected " << expected << '\n';
+ assert(expected == result);
}
- std::cerr << "seen " << result << ", expected " << expected << '\n';
- assert(expected == result);
+ if (id == ASSERT_TRAP) assert(trapped);
}
- if (id == ASSERT_TRAP) assert(trapped);
i++;
}
}