#! /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. 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): 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)))