darling-JavaScriptCore/wasm/generateWasm.py

138 lines
5.6 KiB
Python
Executable File

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