diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/support/file.cpp | 6 | ||||
-rw-r--r-- | src/tools/wasm-ctor-eval.cpp | 2 | ||||
-rw-r--r-- | src/wasm-validator.h | 21 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 26 |
4 files changed, 44 insertions, 11 deletions
diff --git a/src/support/file.cpp b/src/support/file.cpp index fd38a7ae3..c1d9e6e33 100644 --- a/src/support/file.cpp +++ b/src/support/file.cpp @@ -40,8 +40,14 @@ T wasm::read_file(const std::string &filename, Flags::BinaryOption binary, Flags exit(EXIT_FAILURE); } T input(size_t(insize) + (binary == Flags::Binary ? 0 : 1), '\0'); + if (size_t(insize) == 0) return input; infile.seekg(0); infile.read(&input[0], insize); + if (binary == Flags::Text) { + size_t chars = size_t(infile.gcount()); + input.resize(chars+1); // Truncate size to the number of ASCII characters actually read in text mode (which is generally less than the number of bytes on Windows, if \r\n line endings are present) + input[chars] = '\0'; + } return input; } diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 67c9f9707..f3d420aac 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -352,7 +352,7 @@ int main(int argc, const char* argv[]) { bool debugInfo = false; std::string ctorsString; - Options options("wasm-opt", "Optimize .wast files"); + Options options("wasm-ctor-eval", "Optimize .wast files"); options .add("--output", "-o", "Output file (stdout if not specified)", Options::Arguments::One, diff --git a/src/wasm-validator.h b/src/wasm-validator.h index f83f5209d..a359102ea 100644 --- a/src/wasm-validator.h +++ b/src/wasm-validator.h @@ -46,13 +46,15 @@ namespace wasm { // Print anything that can be streamed to an ostream -template <typename T> +template <typename T, + typename std::enable_if< + !std::is_base_of<Expression, typename std::remove_pointer<T>::type>::value + >::type* = nullptr> inline std::ostream& printModuleComponent(T curr, std::ostream& stream) { stream << curr << std::endl; return stream; } -// Specialization for Expressions to print type info too -template <> +// Extra overload for Expressions, to print type info too inline std::ostream& printModuleComponent(Expression* curr, std::ostream& stream) { WasmPrinter::printExpression(curr, stream, false, true) << std::endl; return stream; @@ -162,13 +164,13 @@ public: // helpers private: template <typename T, typename S> - std::ostream& fail(T curr, S text); + std::ostream& fail(S text, T curr); std::ostream& printFailureHeader(); template<typename T> bool shouldBeTrue(bool result, T curr, const char* text) { if (!result) { - fail(curr, "unexpected false: " + std::string(text)); + fail("unexpected false: " + std::string(text), curr); return false; } return result; @@ -176,7 +178,7 @@ public: template<typename T> bool shouldBeFalse(bool result, T curr, const char* text) { if (result) { - fail(curr, "unexpected true: " + std::string(text)); + fail("unexpected true: " + std::string(text), curr); return false; } return result; @@ -187,7 +189,7 @@ public: if (left != right) { std::ostringstream ss; ss << left << " != " << right << ": " << text; - fail(curr, ss.str()); + fail(ss.str(), curr); return false; } return true; @@ -198,7 +200,7 @@ public: if (left != unreachable && left != right) { std::ostringstream ss; ss << left << " != " << right << ": " << text; - fail(curr, ss.str()); + fail(ss.str(), curr); return false; } return true; @@ -209,12 +211,13 @@ public: if (left == right) { std::ostringstream ss; ss << left << " == " << right << ": " << text; - fail(curr, ss.str()); + fail(ss.str(), curr); return false; } return true; } + void shouldBeIntOrUnreachable(WasmType ty, Expression* curr, const char* text); void validateAlignment(size_t align, WasmType type, Index bytes, bool isAtomic, Expression* curr); void validateMemBytes(uint8_t bytes, WasmType type, Expression* curr); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 25f2588d3..5ca6b2783 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -220,22 +220,46 @@ void WasmValidator::visitSetLocal(SetLocal *curr) { } } void WasmValidator::visitLoad(Load *curr) { + if (curr->isAtomic && !getModule()->memory.shared) fail("Atomic operation with non-shared memory", curr); validateMemBytes(curr->bytes, curr->type, curr); validateAlignment(curr->align, curr->type, curr->bytes, curr->isAtomic, curr); shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "load pointer type must be i32"); } void WasmValidator::visitStore(Store *curr) { + if (curr->isAtomic && !getModule()->memory.shared) fail("Atomic operation with non-shared memory", curr); validateMemBytes(curr->bytes, curr->valueType, curr); validateAlignment(curr->align, curr->type, curr->bytes, curr->isAtomic, curr); shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "store pointer type must be i32"); shouldBeUnequal(curr->value->type, none, curr, "store value type must not be none"); shouldBeEqualOrFirstIsUnreachable(curr->value->type, curr->valueType, curr, "store value type must match"); } +void WasmValidator::shouldBeIntOrUnreachable(WasmType ty, Expression* curr, const char* text) { + switch (ty) { + case i32: + case i64: + case unreachable: { + break; + } + default: fail(text, curr); + } +} void WasmValidator::visitAtomicRMW(AtomicRMW* curr) { + if (!getModule()->memory.shared) fail("Atomic operation with non-shared memory", curr); validateMemBytes(curr->bytes, curr->type, curr); + shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "AtomicRMW pointer type must be i32"); + shouldBeEqualOrFirstIsUnreachable(curr->value->type, curr->type, curr, "AtomicRMW result type must match operand"); + shouldBeIntOrUnreachable(curr->type, curr, "Atomic operations are only valid on int types"); } void WasmValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) { + if (!getModule()->memory.shared) fail("Atomic operation with non-shared memory", curr); validateMemBytes(curr->bytes, curr->type, curr); + shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "cmpxchg pointer type must be i32"); + if (curr->expected->type != unreachable && curr->replacement->type != unreachable) { + shouldBeEqual(curr->expected->type, curr->replacement->type, curr, "cmpxchg operand types must match"); + } + shouldBeEqualOrFirstIsUnreachable(curr->expected->type, curr->type, curr, "Cmpxchg result type must match expected"); + shouldBeEqualOrFirstIsUnreachable(curr->replacement->type, curr->type, curr, "Cmpxchg result type must match replacement"); + shouldBeIntOrUnreachable(curr->expected->type, curr, "Atomic operations are only valid on int types"); } void WasmValidator::validateMemBytes(uint8_t bytes, WasmType type, Expression* curr) { if (type == unreachable) { @@ -658,7 +682,7 @@ void WasmValidator::validateBinaryenIR(Module& wasm) { } template <typename T, typename S> -std::ostream& WasmValidator::fail(T curr, S text) { +std::ostream& WasmValidator::fail(S text, T curr) { valid = false; auto& ret = printFailureHeader() << text << ", on \n"; return printModuleComponent(curr, ret); |