mirror of
https://github.com/darlinghq/darling-JavaScriptCore.git
synced 2024-11-23 04:09:40 +00:00
219 lines
6.7 KiB
Python
Executable File
219 lines
6.7 KiB
Python
Executable File
#!/usr/bin/env 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:n
|
|
#
|
|
# 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
|
|
import re
|
|
|
|
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
|
|
wasmB3IRGeneratorHFile = open(args[2], "w")
|
|
|
|
opcodeRegex = re.compile('([a-zA-Z0-9]+)')
|
|
argumentRegex = re.compile('(\@[0-9]+)')
|
|
decimalRegex = re.compile('([-]?[0-9]+)')
|
|
whitespaceRegex = re.compile('\s+')
|
|
commaRegex = re.compile('(,)')
|
|
oparenRegex = re.compile('(\()')
|
|
cparenRegex = re.compile('(\))')
|
|
|
|
|
|
class Source:
|
|
def __init__(self, contents, offset=0):
|
|
self.contents = contents
|
|
self.offset = offset
|
|
|
|
|
|
def read(regex, source):
|
|
match = regex.match(source.contents, source.offset)
|
|
if not match:
|
|
return None
|
|
source.offset = match.end()
|
|
return match.group()
|
|
|
|
|
|
def lex(source):
|
|
result = []
|
|
while source.offset != len(source.contents):
|
|
read(whitespaceRegex, source)
|
|
opcode = read(opcodeRegex, source)
|
|
if opcode:
|
|
result.append(opcode)
|
|
continue
|
|
|
|
argument = read(argumentRegex, source)
|
|
if argument:
|
|
result.append(argument)
|
|
continue
|
|
|
|
number = read(decimalRegex, source)
|
|
if number:
|
|
result.append(int(number))
|
|
continue
|
|
|
|
oparen = read(oparenRegex, source)
|
|
if oparen:
|
|
result.append(oparen)
|
|
continue
|
|
|
|
cparen = read(cparenRegex, source)
|
|
if cparen:
|
|
result.append(cparen)
|
|
continue
|
|
|
|
comma = read(commaRegex, source)
|
|
if comma:
|
|
# Skip commas
|
|
continue
|
|
|
|
raise Exception("Lexing Error: could not lex token from: " + source.contents + " at offset: " + str(source.offset) + " (" + source.contents[source.offset:] + "). With tokens: [" + ", ".join(result) + "]")
|
|
return result
|
|
|
|
|
|
class CodeGenerator:
|
|
def __init__(self, tokens):
|
|
self.tokens = tokens
|
|
self.index = 0
|
|
self.code = []
|
|
|
|
def advance(self):
|
|
self.index += 1
|
|
|
|
def token(self):
|
|
return self.tokens[self.index]
|
|
|
|
def parseError(self, string):
|
|
raise Exception("Parse error " + string)
|
|
|
|
def consume(self, string):
|
|
if self.token() != string:
|
|
self.parseError("Expected " + string + " but got " + self.token())
|
|
self.advance()
|
|
|
|
def generateParameters(self):
|
|
self.advance()
|
|
params = []
|
|
tokens = self.tokens
|
|
while self.index < len(tokens):
|
|
if self.token() == ")":
|
|
self.advance()
|
|
return params
|
|
params.append(self.generateOpcode())
|
|
self.parseError("Parsing arguments fell off end")
|
|
|
|
def generateOpcode(self):
|
|
result = None
|
|
if self.token() == "i32" or self.token() == "i64":
|
|
type = "Int32"
|
|
if self.token() == "i64":
|
|
type = "Int64"
|
|
self.advance()
|
|
self.consume("(")
|
|
self.code.append(generateConstCode(self.index, self.token(), type))
|
|
result = temp(self.index)
|
|
self.advance()
|
|
self.consume(")")
|
|
elif argumentRegex.match(self.token()):
|
|
result = "arg" + self.token()[1:]
|
|
self.advance()
|
|
else:
|
|
op = self.token()
|
|
index = self.index
|
|
self.advance()
|
|
params = self.generateParameters()
|
|
self.code.append(generateB3OpCode(index, op, params))
|
|
result = temp(index)
|
|
|
|
return result
|
|
|
|
def generate(self, wasmOp):
|
|
if len(self.tokens) == 1:
|
|
params = ["arg" + str(param) for param in range(len(wasmOp["parameter"]))]
|
|
return " result = m_currentBlock->appendNew<Value>(m_proc, B3::" + self.token() + ", origin(), " + ", ".join(params) + ")"
|
|
result = self.generateOpcode()
|
|
self.code.append("result = " + result)
|
|
return " " + " \n".join(self.code)
|
|
|
|
|
|
def temp(index):
|
|
return "temp" + str(index)
|
|
|
|
|
|
def generateB3OpCode(index, op, params):
|
|
return "Value* " + temp(index) + " = m_currentBlock->appendNew<Value>(m_proc, B3::" + op + ", origin(), " + ", ".join(params) + ");"
|
|
|
|
|
|
def generateConstCode(index, value, type):
|
|
return "Value* " + temp(index) + " = constant(" + type + ", " + value + ");"
|
|
|
|
|
|
def generateB3Code(wasmOp, source):
|
|
tokens = lex(Source(source))
|
|
parser = CodeGenerator(tokens)
|
|
return parser.generate(wasmOp)
|
|
|
|
|
|
def generateSimpleCode(op):
|
|
opcode = op["opcode"]
|
|
b3op = opcode["b3op"]
|
|
args = ["ExpressionType arg" + str(param) for param in range(len(opcode["parameter"]))]
|
|
args.append("ExpressionType& result")
|
|
return """
|
|
template<> auto B3IRGenerator::addOp<OpType::""" + wasm.toCpp(op["name"]) + ">(" + ", ".join(args) + """) -> PartialResult
|
|
{
|
|
""" + generateB3Code(opcode, b3op) + """;
|
|
return { };
|
|
}
|
|
"""
|
|
|
|
|
|
definitions = [generateSimpleCode(op) for op in wasm.opcodeIterator(lambda op: isSimple(op) and (isBinary(op) or isUnary(op)))]
|
|
contents = wasm.header + """
|
|
|
|
#pragma once
|
|
|
|
#if ENABLE(WEBASSEMBLY)
|
|
|
|
namespace JSC { namespace Wasm {
|
|
|
|
""" + "".join(definitions) + """
|
|
|
|
} } // namespace JSC::Wasm
|
|
|
|
#endif // ENABLE(WEBASSEMBLY)
|
|
|
|
"""
|
|
|
|
wasmB3IRGeneratorHFile.write(contents)
|
|
wasmB3IRGeneratorHFile.close()
|