diff options
author | Derek Schuff <dschuff@chromium.org> | 2017-07-12 17:41:43 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-12 17:41:43 -0700 |
commit | 25cbf641c6133d5156e8591072d2705fde92752b (patch) | |
tree | 8eb4bd61894f94c1f0c7e2923ff033e6f7390b87 /src/wasm/wasm-validator.cpp | |
parent | dec4529844e517220d9b336b23afb61aa057eb6a (diff) | |
download | binaryen-25cbf641c6133d5156e8591072d2705fde92752b.tar.gz binaryen-25cbf641c6133d5156e8591072d2705fde92752b.tar.bz2 binaryen-25cbf641c6133d5156e8591072d2705fde92752b.zip |
Refactor validation failure and printing, validate atomic memory (#1090)
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r-- | src/wasm/wasm-validator.cpp | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 21bf68b62..4c02fe6d3 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -219,15 +219,36 @@ void WasmValidator::visitSetLocal(SetLocal *curr) { } } void WasmValidator::visitLoad(Load *curr) { - validateAlignment(curr->align, curr->type, curr->bytes); + 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) { - validateAlignment(curr->align, curr->type, curr->bytes); + 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::visitAtomicRMW(AtomicRMW* curr) { + validateMemBytes(curr->bytes, curr->type, curr); +} +void WasmValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) { + validateMemBytes(curr->bytes, curr->type, curr); +} +void WasmValidator::validateMemBytes(uint8_t bytes, WasmType ty, Expression* curr) { + switch (bytes) { + case 1: + case 2: + case 4: + break; + case 8: { + shouldBeEqual(getWasmTypeSize(ty), 8U, curr, "8-byte mem operations are only allowed with 8-byte wasm types"); + break; + } + default: fail("Memory operations must be 1,2,4, or 8 bytes", curr); + } +} void WasmValidator::visitBinary(Binary *curr) { if (curr->left->type != unreachable && curr->right->type != unreachable) { shouldBeEqual(curr->left->type, curr->right->type, curr, "binary child types must be equal"); @@ -566,28 +587,32 @@ void WasmValidator::visitModule(Module *curr) { } } -void WasmValidator::validateAlignment(size_t align, WasmType type, Index bytes) { +void WasmValidator::validateAlignment(size_t align, WasmType type, Index bytes, + bool isAtomic, Expression* curr) { + if (isAtomic) { + shouldBeEqual(align, (size_t)bytes, curr, "atomic accesses must have natural alignment"); + return; + } switch (align) { case 1: case 2: case 4: case 8: break; default:{ - fail() << "bad alignment: " << align << std::endl; - valid = false; + fail("bad alignment: " + std::to_string(align), curr); break; } } - shouldBeTrue(align <= bytes, align, "alignment must not exceed natural"); + shouldBeTrue(align <= bytes, curr, "alignment must not exceed natural"); switch (type) { case i32: case f32: { - shouldBeTrue(align <= 4, align, "alignment must not exceed natural"); + shouldBeTrue(align <= 4, curr, "alignment must not exceed natural"); break; } case i64: case f64: { - shouldBeTrue(align <= 8, align, "alignment must not exceed natural"); + shouldBeTrue(align <= 8, curr, "alignment must not exceed natural"); break; } default: {} @@ -614,7 +639,7 @@ void WasmValidator::validateBinaryenIR(Module& wasm) { // The block has an added type, not derived from the ast itself, so it is // ok for it to be either i32 or unreachable. if (!(isConcreteWasmType(oldType) && newType == unreachable)) { - parent.fail() << "stale type found in " << (getFunction() ? getFunction()->name : Name("(global scope)")) << " on " << curr << "\n(marked as " << printWasmType(oldType) << ", should be " << printWasmType(newType) << ")\n"; + parent.printFailureHeader() << "stale type found in " << (getFunction() ? getFunction()->name : Name("(global scope)")) << " on " << curr << "\n(marked as " << printWasmType(oldType) << ", should be " << printWasmType(newType) << ")\n"; parent.valid = false; } curr->type = oldType; @@ -625,7 +650,14 @@ void WasmValidator::validateBinaryenIR(Module& wasm) { binaryenIRValidator.walkModule(&wasm); } -std::ostream& WasmValidator::fail() { +template <typename T, typename S> +std::ostream& WasmValidator::fail(T curr, S text) { + valid = false; + auto& ret = printFailureHeader() << text << ", on \n"; + return printModuleComponent(curr, ret); +} + +std::ostream& WasmValidator::printFailureHeader() { Colors::red(std::cerr); if (getFunction()) { std::cerr << "[wasm-validator error in function "; |