summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-validator.cpp
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2017-07-12 17:41:43 -0700
committerGitHub <noreply@github.com>2017-07-12 17:41:43 -0700
commit25cbf641c6133d5156e8591072d2705fde92752b (patch)
tree8eb4bd61894f94c1f0c7e2923ff033e6f7390b87 /src/wasm/wasm-validator.cpp
parentdec4529844e517220d9b336b23afb61aa057eb6a (diff)
downloadbinaryen-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.cpp52
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 ";