| #!/usr/bin/env python3 |
| |
| # 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. |
| |
| import json |
| import math |
| import re |
| |
| class Wasm: |
| def __init__(self, scriptName, jsonPath): |
| wasmFile = open(jsonPath, "r") |
| wasm = json.load(open(jsonPath, "r")) |
| wasmFile.close() |
| for pre in wasm["preamble"]: |
| if pre["name"] == "version": |
| self.expectedVersionNumber = str(pre["value"]) |
| self.preamble = wasm["preamble"] |
| self.types = wasm["type"] |
| self.opcodes = wasm["opcode"] |
| self.header = """/* |
| * 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. |
| */ |
| |
| // DO NO EDIT! - This file was generated by """ + scriptName |
| |
| def opcodeIterator(self, filter, ret=None): |
| # We need to do this because python won't let me use self in the lambda, which is ridiculous. |
| if ret == None: |
| ret = lambda op: {"name": op, "opcode": self.opcodes[op]} |
| for op in self.opcodes.keys(): |
| if filter(self.opcodes[op]): |
| yield ret(op) |
| |
| def toCpp(self, name): |
| camelCase = re.sub(r'([^a-z0-9].)', lambda c: c.group(0)[1].upper(), name) |
| CamelCase = camelCase[:1].upper() + camelCase[1:] |
| return CamelCase |
| |
| |
| def isNormal(op): |
| if "extendedOp" in op: |
| return False |
| return op["category"] == "arithmetic" or op["category"] == "comparison" or op["category"] == "conversion" |
| |
| |
| def isUnary(op): |
| return isNormal(op) and len(op["parameter"]) == 1 |
| |
| |
| def isBinary(op): |
| return isNormal(op) and len(op["parameter"]) == 2 |
| |
| |
| def isAtomic(op): |
| return op["category"].startswith("atomic") |
| |
| |
| def isAtomicLoad(op): |
| return op["category"] == "atomic.load" |
| |
| |
| def isAtomicStore(op): |
| return op["category"] == "atomic.store" |
| |
| |
| def isAtomicBinaryRMW(op): |
| return op["category"] == "atomic.rmw.binary" |
| |
| |
| def isSimple(op): |
| return "b3op" in op |
| |
| |
| def memoryLog2Alignment(op): |
| assert op["opcode"]["category"] == "memory" or op["opcode"]["category"] == "atomic.load" or op["opcode"]["category"] == "atomic.store" or op["opcode"]["category"] == "atomic.rmw" or op["opcode"]["category"] == "atomic" or op["opcode"]["category"] == "atomic.rmw.binary" |
| if op["opcode"]["category"] == "atomic.rmw.binary" or op["opcode"]["category"] == "atomic.rmw": |
| match = re.match(r'^[if]([36][24])\.[^0-9]+([0-9]+)?\.[^0-9]+_?[us]?$', op["name"]) |
| if not match: |
| print(op["name"]) |
| memoryBits = int(match.group(2) if match.group(2) else match.group(1)) |
| elif op["opcode"]["category"] == "atomic": |
| if op["name"] == "atomic.fence": |
| memoryBits = 8 |
| elif op["name"] == "memory.atomic.notify": |
| memoryBits = 32 |
| else: |
| match = re.match(r'^memory\.atomic\.wait([0-9]+)$', op["name"]) |
| memoryBits = int(match.group(1)) |
| else: |
| match = re.match(r'^[if]([36][24])\.[^0-9]+([0-9]+)?_?[us]?$', op["name"]) |
| if not match: |
| print(op["name"]) |
| memoryBits = int(match.group(2) if match.group(2) else match.group(1)) |
| assert 2 ** math.log(memoryBits, 2) == memoryBits |
| return str(int(math.log(memoryBits / 8, 2))) |