| #!/usr/bin/env python |
| |
| # Copyright (C) 2016-2017 Apple Inc. All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| # This tool has a couple of helpful macros to process Wasm files from the wasm.json. |
| |
| from generateWasm import * |
| import optparse |
| import sys |
| |
| parser = optparse.OptionParser(usage="usage: %prog <wasm.json> <WasmOps.h>") |
| (options, args) = parser.parse_args(sys.argv[0:]) |
| if len(args) != 3: |
| parser.error(parser.usage) |
| |
| wasm = Wasm(args[0], args[1]) |
| opcodes = wasm.opcodes |
| wasmValidateInlinesHFile = open(args[2], "w") |
| |
| |
| def cppType(name): |
| result = { |
| "bool": "I32", |
| "addr": "I32", |
| "i32": "I32", |
| "i64": "I64", |
| "f32": "F32", |
| "f64": "F64", |
| }.get(name, None) |
| if result == None: |
| raise ValueError("Unknown type name: " + name) |
| return result |
| |
| |
| def toCpp(name): |
| return wasm.toCpp(name) |
| |
| |
| def unaryMacro(name): |
| op = opcodes[name] |
| return """ |
| template<> auto Validate::addOp<OpType::""" + toCpp(name) + """>(ExpressionType value, ExpressionType& result) -> Result |
| { |
| if (UNLIKELY(value != """ + cppType(op["parameter"][0]) + """)) |
| return Unexpected<Result::error_type>("validation failed: """ + name + """ value type mismatch"); |
| |
| result = """ + cppType(op["return"][0]) + """; |
| return { }; |
| } |
| """ |
| |
| |
| def binaryMacro(name): |
| op = opcodes[name] |
| return """ |
| template<> auto Validate::addOp<OpType::""" + toCpp(name) + """>(ExpressionType left, ExpressionType right, ExpressionType& result) -> Result |
| { |
| if (UNLIKELY(left != """ + cppType(op["parameter"][0]) + """)) |
| return Unexpected<Result::error_type>("validation failed: """ + name + """ left value type mismatch"); |
| |
| if (UNLIKELY(right != """ + cppType(op["parameter"][1]) + """)) |
| return Unexpected<Result::error_type>("validation failed: """ + name + """ right value type mismatch"); |
| |
| result = """ + cppType(op["return"][0]) + """; |
| return { }; |
| } |
| """ |
| |
| def loadMacro(name): |
| op = opcodes[name] |
| return """ |
| case LoadOpType::""" + toCpp(name) + """: { |
| if (UNLIKELY(pointer != """ + cppType(op["parameter"][0]) + """)) |
| return Unexpected<Result::error_type>("validation failed: """ + name + """ pointer type mismatch"); |
| |
| result = """ + cppType(op["return"][0]) + """; |
| return { }; |
| }""" |
| |
| |
| def storeMacro(name): |
| op = opcodes[name] |
| return """ |
| case StoreOpType::""" + toCpp(name) + """: { |
| if (UNLIKELY(pointer != """ + cppType(op["parameter"][0]) + """)) |
| return Unexpected<Result::error_type>("validation failed: """ + name + """ pointer type mismatch"); |
| |
| if (UNLIKELY(value != """ + cppType(op["parameter"][1]) + """)) |
| return Unexpected<Result::error_type>("validation failed: """ + name + """ value type mismatch"); |
| |
| return { }; |
| }""" |
| |
| |
| unarySpecializations = "".join([op for op in wasm.opcodeIterator(isUnary, unaryMacro)]) |
| binarySpecializations = "".join([op for op in wasm.opcodeIterator(isBinary, binaryMacro)]) |
| loadCases = "".join([op for op in wasm.opcodeIterator(lambda op: op["category"] == "memory" and len(op["return"]) == 1, loadMacro)]) |
| storeCases = "".join([op for op in wasm.opcodeIterator(lambda op: op["category"] == "memory" and len(op["return"]) == 0, storeMacro)]) |
| |
| contents = wasm.header + """ |
| // This file is intended to be inlined by WasmValidate.cpp only! It should not be included elsewhere. |
| |
| #pragma once |
| |
| #if ENABLE(WEBASSEMBLY) |
| |
| #include <wtf/StdLibExtras.h> |
| |
| #if ASSERT_DISABLED |
| IGNORE_RETURN_TYPE_WARNINGS_BEGIN |
| #endif |
| |
| namespace JSC { namespace Wasm { |
| |
| """ + unarySpecializations + binarySpecializations + """ |
| |
| auto Validate::load(LoadOpType op, ExpressionType pointer, ExpressionType& result, uint32_t) -> Result |
| { |
| if (UNLIKELY(!hasMemory())) |
| return Unexpected<Result::error_type>("validation failed: load instruction without memory"); |
| |
| switch (op) { |
| """ + loadCases + """ |
| } |
| ASSERT_NOT_REACHED(); |
| } |
| |
| auto Validate::store(StoreOpType op, ExpressionType pointer, ExpressionType value, uint32_t) -> Result |
| { |
| if (UNLIKELY(!hasMemory())) |
| return Unexpected<Result::error_type>("validation failed: store instruction without memory"); |
| |
| switch (op) { |
| """ + storeCases + """ |
| } |
| ASSERT_NOT_REACHED(); |
| } |
| |
| } } // namespace JSC::Wasm |
| |
| #if ASSERT_DISABLED |
| IGNORE_RETURN_TYPE_WARNINGS_END |
| #endif |
| |
| #endif // ENABLE(WEBASSEMBLY) |
| |
| """ |
| |
| wasmValidateInlinesHFile.write(contents) |
| wasmValidateInlinesHFile.close() |