diff options
author | Alon Zakai <alonzakai@gmail.com> | 2015-11-05 13:04:15 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2015-11-05 13:04:15 -0800 |
commit | a3df15c2c6e7cfad29ce41603f954573f0726659 (patch) | |
tree | aa4e956e4889d85eae8399c38a16fe3b3fb39742 /src | |
parent | 4c7dc453f761391cc44646a5058036977272ca15 (diff) | |
download | binaryen-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.h | 39 | ||||
-rw-r--r-- | src/wasm-shell.cpp | 62 |
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++; } } |