diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/wasm/generateWasmOpsHeader.py | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/wasm/generateWasmOpsHeader.py')
-rwxr-xr-x | Source/JavaScriptCore/wasm/generateWasmOpsHeader.py | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py b/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py new file mode 100755 index 000000000..de8aa2c69 --- /dev/null +++ b/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py @@ -0,0 +1,285 @@ +#! /usr/bin/python + +# Copyright (C) 2016 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]) +types = wasm.types +opcodes = wasm.opcodes +wasmOpsHFile = open(args[2], "w") + + +def cppMacro(wasmOpcode, value, b3, inc): + return " \\\n macro(" + wasm.toCpp(wasmOpcode) + ", " + hex(int(value)) + ", " + b3 + ", " + str(inc) + ")" + + +def typeMacroizer(): + inc = 0 + for ty in wasm.types: + yield cppMacro(ty, wasm.types[ty]["value"], wasm.types[ty]["b3type"], inc) + inc += 1 + +type_definitions = ["#define FOR_EACH_WASM_TYPE(macro)"] +type_definitions.extend([t for t in typeMacroizer()]) +type_definitions = "".join(type_definitions) + + +def opcodeMacroizer(filter): + inc = 0 + for op in wasm.opcodeIterator(filter): + b3op = "Oops" + if isSimple(op["opcode"]): + b3op = op["opcode"]["b3op"] + yield cppMacro(op["name"], op["opcode"]["value"], b3op, inc) + inc += 1 + +defines = ["#define FOR_EACH_WASM_SPECIAL_OP(macro)"] +defines.extend([op for op in opcodeMacroizer(lambda op: not (isUnary(op) or isBinary(op) or op["category"] == "control" or op["category"] == "memory"))]) +defines.append("\n\n#define FOR_EACH_WASM_CONTROL_FLOW_OP(macro)") +defines.extend([op for op in opcodeMacroizer(lambda op: op["category"] == "control")]) +defines.append("\n\n#define FOR_EACH_WASM_SIMPLE_UNARY_OP(macro)") +defines.extend([op for op in opcodeMacroizer(lambda op: isUnary(op) and isSimple(op))]) +defines.append("\n\n#define FOR_EACH_WASM_UNARY_OP(macro) \\\n FOR_EACH_WASM_SIMPLE_UNARY_OP(macro)") +defines.extend([op for op in opcodeMacroizer(lambda op: isUnary(op) and not (isSimple(op)))]) +defines.append("\n\n#define FOR_EACH_WASM_SIMPLE_BINARY_OP(macro)") +defines.extend([op for op in opcodeMacroizer(lambda op: isBinary(op) and isSimple(op))]) +defines.append("\n\n#define FOR_EACH_WASM_BINARY_OP(macro) \\\n FOR_EACH_WASM_SIMPLE_BINARY_OP(macro)") +defines.extend([op for op in opcodeMacroizer(lambda op: isBinary(op) and not (isSimple(op)))]) +defines.append("\n\n#define FOR_EACH_WASM_MEMORY_LOAD_OP(macro)") +defines.extend([op for op in opcodeMacroizer(lambda op: (op["category"] == "memory" and len(op["return"]) == 1))]) +defines.append("\n\n#define FOR_EACH_WASM_MEMORY_STORE_OP(macro)") +defines.extend([op for op in opcodeMacroizer(lambda op: (op["category"] == "memory" and len(op["return"]) == 0))]) +defines.append("\n\n") + +defines = "".join(defines) + +opValueSet = set([op for op in wasm.opcodeIterator(lambda op: True, lambda op: opcodes[op]["value"])]) +maxOpValue = max(opValueSet) + + +# Luckily, python does floor division rather than trunc division so this works. +def ceilDiv(a, b): + return -(-a // b) + + +def bitSet(): + v = "" + for i in range(ceilDiv(maxOpValue, 8)): + entry = 0 + for j in range(8): + if i * 8 + j in opValueSet: + entry |= 1 << j + v += (", " if i else "") + hex(entry) + return v + +validOps = bitSet() + +contents = wasm.header + """ + +#pragma once + +#if ENABLE(WEBASSEMBLY) + +#include <cstdint> + +namespace JSC { namespace Wasm { + +static constexpr unsigned expectedVersionNumber = """ + wasm.expectedVersionNumber + """; + +static constexpr unsigned numTypes = """ + str(len(types)) + """; + +""" + type_definitions + """ +#define CREATE_ENUM_VALUE(name, id, b3type, inc) name = id, +enum Type : int8_t { + FOR_EACH_WASM_TYPE(CREATE_ENUM_VALUE) +}; +#undef CREATE_ENUM_VALUE + +#define CREATE_CASE(name, id, b3type, inc) case id: return true; +template <typename Int> +inline bool isValidType(Int i) +{ + switch (i) { + default: return false; + FOR_EACH_WASM_TYPE(CREATE_CASE) + } + RELEASE_ASSERT_NOT_REACHED(); + return false; +} +#undef CREATE_CASE + +#define CREATE_CASE(name, id, b3type, inc) case name: return b3type; +inline B3::Type toB3Type(Type type) +{ + switch (type) { + FOR_EACH_WASM_TYPE(CREATE_CASE) + } + RELEASE_ASSERT_NOT_REACHED(); + return B3::Void; +} +#undef CREATE_CASE + +#define CREATE_CASE(name, id, b3type, inc) case name: return #name; +inline const char* makeString(Type type) +{ + switch (type) { + FOR_EACH_WASM_TYPE(CREATE_CASE) + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} +#undef CREATE_CASE + +#define CREATE_CASE(name, id, b3type, inc) case id: return inc; +inline int linearizeType(Type type) +{ + switch (type) { + FOR_EACH_WASM_TYPE(CREATE_CASE) + } + RELEASE_ASSERT_NOT_REACHED(); + return 0; +} +#undef CREATE_CASE + +#define CREATE_CASE(name, id, b3type, inc) case inc: return name; +inline Type linearizedToType(int i) +{ + switch (i) { + FOR_EACH_WASM_TYPE(CREATE_CASE) + } + RELEASE_ASSERT_NOT_REACHED(); + return Void; +} +#undef CREATE_CASE + + +""" + defines + """ +#define FOR_EACH_WASM_OP(macro) \\ + FOR_EACH_WASM_SPECIAL_OP(macro) \\ + FOR_EACH_WASM_CONTROL_FLOW_OP(macro) \\ + FOR_EACH_WASM_UNARY_OP(macro) \\ + FOR_EACH_WASM_BINARY_OP(macro) \\ + FOR_EACH_WASM_MEMORY_LOAD_OP(macro) \\ + FOR_EACH_WASM_MEMORY_STORE_OP(macro) + +#define CREATE_ENUM_VALUE(name, id, b3op, inc) name = id, + +enum OpType : uint8_t { + FOR_EACH_WASM_OP(CREATE_ENUM_VALUE) +}; + +template<typename Int> +inline bool isValidOpType(Int i) +{ + // Bitset of valid ops. + static const uint8_t valid[] = { """ + validOps + """ }; + return 0 <= i && i <= """ + str(maxOpValue) + """ && (valid[i / 8] & (1 << (i % 8))); +} + +enum class BinaryOpType : uint8_t { + FOR_EACH_WASM_BINARY_OP(CREATE_ENUM_VALUE) +}; + +enum class UnaryOpType : uint8_t { + FOR_EACH_WASM_UNARY_OP(CREATE_ENUM_VALUE) +}; + +enum class LoadOpType : uint8_t { + FOR_EACH_WASM_MEMORY_LOAD_OP(CREATE_ENUM_VALUE) +}; + +enum class StoreOpType : uint8_t { + FOR_EACH_WASM_MEMORY_STORE_OP(CREATE_ENUM_VALUE) +}; + +#undef CREATE_ENUM_VALUE + +inline bool isControlOp(OpType op) +{ + switch (op) { +#define CREATE_CASE(name, id, b3op, inc) case OpType::name: + FOR_EACH_WASM_CONTROL_FLOW_OP(CREATE_CASE) + return true; +#undef CREATE_CASE + default: + break; + } + return false; +} + +inline bool isSimple(UnaryOpType op) +{ + switch (op) { +#define CREATE_CASE(name, id, b3op, inc) case UnaryOpType::name: + FOR_EACH_WASM_SIMPLE_UNARY_OP(CREATE_CASE) + return true; +#undef CREATE_CASE + default: + break; + } + return false; +} + +inline bool isSimple(BinaryOpType op) +{ + switch (op) { +#define CREATE_CASE(name, id, b3op, inc) case BinaryOpType::name: + FOR_EACH_WASM_SIMPLE_BINARY_OP(CREATE_CASE) + return true; +#undef CREATE_CASE + default: + break; + } + return false; +} + +#define CREATE_CASE(name, id, b3type, inc) case name: return #name; +inline const char* makeString(OpType op) +{ + switch (op) { + FOR_EACH_WASM_OP(CREATE_CASE) + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} +#undef CREATE_CASE + +} } // namespace JSC::Wasm + +#endif // ENABLE(WEBASSEMBLY) + +""" + +wasmOpsHFile.write(contents) +wasmOpsHFile.close() |