| #! /usr/bin/env python | 
 |  | 
 | # Copyright (C) 2014-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 processes the bytecode list to create Bytecodes.h and InitBytecodes.asm | 
 |  | 
 | import hashlib | 
 | import json | 
 | import optparse | 
 | import os | 
 | import re | 
 | import sys | 
 |  | 
 | cCopyrightMsg = """/* | 
 | * Copyright (C) 2014 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. | 
 |  | 
 | * Autogenerated from %s, do not modify. | 
 | */ | 
 |  | 
 | """ | 
 |  | 
 | asmCopyrightMsg = """# Copyright (C) 2014 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. | 
 |  | 
 | # Autogenerated from %s, do not modify. | 
 |  | 
 | """ | 
 | def openOrExit(path, mode): | 
 |     try: | 
 |         return open(path, mode) | 
 |     except IOError as e: | 
 |         print("I/O error opening {0}, ({1}): {2}".format(path, e.errno, e.strerror)) | 
 |         exit(1) | 
 |  | 
 | def hashFile(file): | 
 |     sha1 = hashlib.sha1() | 
 |     file.seek(0) | 
 |     for line in file: | 
 |         sha1.update(line) | 
 |  | 
 |     file.seek(0) | 
 |  | 
 |     return sha1.hexdigest() | 
 |  | 
 |  | 
 | def toCpp(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 writeInstructionAccessor(bytecodeHFile, typeName, name): | 
 |     bytecodeHFile.write("    {0}& {1}() {{ return *reinterpret_cast<{0}*>(&m_{1}); }}\n".format(typeName, name)) | 
 |     bytecodeHFile.write("    const {0}& {1}() const {{ return *reinterpret_cast<const {0}*>(&m_{1}); }}\n".format(typeName, name)) | 
 |  | 
 |  | 
 | def writeInstructionMember(bytecodeHFile, typeName, name): | 
 |     bytecodeHFile.write("    std::aligned_storage<sizeof({0}), sizeof(Instruction)>::type m_{1};\n".format(typeName, name)) | 
 |  | 
 |  | 
 | def writeStruct(bytecodeHFile, bytecode): | 
 |     bytecodeHFile.write("struct {0} {{\n".format(toCpp(bytecode["name"]))) | 
 |     bytecodeHFile.write("public:\n") | 
 |  | 
 |     writeInstructionAccessor(bytecodeHFile, "Opcode", "opcode") | 
 |     for offset in bytecode["offsets"]: | 
 |         for name, typeName in offset.iteritems(): | 
 |             writeInstructionAccessor(bytecodeHFile, typeName, name) | 
 |  | 
 |     bytecodeHFile.write("\nprivate:\n") | 
 |     bytecodeHFile.write("    friend class LLIntOffsetsExtractor;\n\n") | 
 |  | 
 |     writeInstructionMember(bytecodeHFile, "Opcode", "opcode") | 
 |     for offset in bytecode["offsets"]: | 
 |         for name, typeName in offset.iteritems(): | 
 |             writeInstructionMember(bytecodeHFile, typeName, name) | 
 |     bytecodeHFile.write("};\n\n") | 
 |  | 
 |  | 
 | if __name__ == "__main__": | 
 |     parser = optparse.OptionParser(usage = "usage: %prog [--bytecodes_h <FILE>] [--init_bytecodes_asm <FILE>] <bytecode-json-file>") | 
 |     parser.add_option("-b", "--bytecodes_h", dest = "bytecodesHFileName", help = "generate bytecodes macro .h FILE", metavar = "FILE") | 
 |     parser.add_option("-s", "--bytecode_structs_h", dest = "bytecodeStructsHFileName", help = "generate bytecodes macro .h FILE", metavar = "FILE") | 
 |     parser.add_option("-a", "--init_bytecodes_asm", dest = "initASMFileName", help="generate ASM bytecodes init FILE", metavar = "FILE") | 
 |     (options, args) = parser.parse_args() | 
 |  | 
 |     if len(args) != 1: | 
 |         parser.error("missing <bytecode-json-file>") | 
 |  | 
 |     bytecodeJSONFile = args[0] | 
 |     bytecodeFile = openOrExit(bytecodeJSONFile, "rb") | 
 |     sha1Hash = hashFile(bytecodeFile) | 
 |  | 
 |     hFileHashString = "// SHA1Hash: {0}\n".format(sha1Hash) | 
 |     asmFileHashString = "# SHA1Hash: {0}\n".format(sha1Hash) | 
 |  | 
 |     bytecodeHFilename = options.bytecodesHFileName | 
 |     bytecodeStructsHFilename = options.bytecodeStructsHFileName | 
 |     initASMFileName = options.initASMFileName | 
 |  | 
 |     if not bytecodeHFilename and not initASMFileName and not bytecodeStructsHFilename: | 
 |         parser.print_help() | 
 |         exit(0) | 
 |  | 
 |     needToGenerate = False | 
 |  | 
 |     if bytecodeHFilename: | 
 |         try: | 
 |             bytecodeHReadFile = open(bytecodeHFilename, "rb") | 
 |  | 
 |             hashLine = bytecodeHReadFile.readline() | 
 |             if hashLine != hFileHashString: | 
 |                 needToGenerate = True | 
 |         except: | 
 |             needToGenerate = True | 
 |         else: | 
 |             bytecodeHReadFile.close() | 
 |  | 
 |     if bytecodeStructsHFilename: | 
 |         try: | 
 |             bytecodeStructsHReadFile = open(bytecodeStructsHFilename, "rb") | 
 |  | 
 |             hashLine = bytecodeStructsHReadFile.readline() | 
 |             if hashLine != hFileHashString: | 
 |                 needToGenerate = True | 
 |         except: | 
 |             needToGenerate = True | 
 |         else: | 
 |             bytecodeStructsHReadFile.close() | 
 |  | 
 |     if initASMFileName: | 
 |         try: | 
 |             initBytecodesReadFile = open(initASMFileName, "rb") | 
 |              | 
 |             hashLine = initBytecodesReadFile.readline() | 
 |             if hashLine != asmFileHashString: | 
 |                 needToGenerate = True | 
 |         except: | 
 |             needToGenerate = True | 
 |         else: | 
 |             initBytecodesReadFile.close() | 
 |  | 
 |     if not needToGenerate: | 
 |         exit(0) | 
 |  | 
 |     if bytecodeHFilename: | 
 |         bytecodeHFile = openOrExit(bytecodeHFilename, "wb") | 
 |  | 
 |     if bytecodeStructsHFilename: | 
 |         bytecodeStructsHFile = openOrExit(bytecodeStructsHFilename, "wb") | 
 |  | 
 |     if initASMFileName: | 
 |         initBytecodesFile = openOrExit(initASMFileName, "wb") | 
 |  | 
 |     try: | 
 |         bytecodeSections = json.load(bytecodeFile, encoding = "utf-8") | 
 |     except: | 
 |         print("Unexpected error parsing {0}: {1}".format(bytecodeJSONFile, sys.exc_info())) | 
 |  | 
 |     if bytecodeHFilename: | 
 |         bytecodeHFile.write(hFileHashString) | 
 |         bytecodeHFile.write(cCopyrightMsg % bytecodeJSONFile) | 
 |         bytecodeHFile.write("#pragma once\n\n") | 
 |  | 
 |     if bytecodeStructsHFilename: | 
 |         bytecodeStructsHFile.write(hFileHashString) | 
 |         bytecodeStructsHFile.write(cCopyrightMsg % bytecodeJSONFile) | 
 |         bytecodeStructsHFile.write("#pragma once\n\n") | 
 |         bytecodeStructsHFile.write("#include \"Instruction.h\"\n") | 
 |         bytecodeStructsHFile.write("\n") | 
 |  | 
 |     if initASMFileName: | 
 |         initBytecodesFile.write(asmFileHashString) | 
 |         initBytecodesFile.write(asmCopyrightMsg % bytecodeJSONFile) | 
 |         initASMBytecodeNum = 0 | 
 |  | 
 |     for section in bytecodeSections: | 
 |         if bytecodeHFilename and section['emitInHFile']: | 
 |             bytecodeHFile.write("#define FOR_EACH_{0}_ID(macro) \\\n".format(section["macroNameComponent"])) | 
 |             firstMacro = True | 
 |             defaultLength = 1 | 
 |             if "defaultLength" in section: | 
 |                 defaultLength = section["defaultLength"] | 
 |  | 
 |             bytecodeNum = 0 | 
 |             for bytecode in section["bytecodes"]: | 
 |                 if not firstMacro: | 
 |                     bytecodeHFile.write(" \\\n") | 
 |  | 
 |                 length = defaultLength | 
 |                 if "length" in bytecode: | 
 |                     length = bytecode["length"] | 
 |                 elif "offsets" in bytecode: | 
 |                     # Add one for the opcode | 
 |                     length = len(bytecode["offsets"]) + 1 | 
 |  | 
 |                 bytecodeHFile.write("    macro({0}, {1})".format(bytecode["name"], length)) | 
 |                 firstMacro = False | 
 |                 bytecodeNum = bytecodeNum + 1 | 
 |  | 
 |             bytecodeHFile.write("\n\n") | 
 |             bytecodeHFile.write("#define NUMBER_OF_{0}_IDS {1}\n\n".format(section["macroNameComponent"], bytecodeNum)) | 
 |  | 
 |  | 
 |         if bytecodeStructsHFilename and section['emitInStructsFile']: | 
 |             bytecodeStructsHFile.write("namespace JSC {\n\n") | 
 |  | 
 |             for bytecode in section["bytecodes"]: | 
 |                 if not "offsets" in bytecode: | 
 |                     continue | 
 |                 writeStruct(bytecodeStructsHFile, bytecode) | 
 |  | 
 |             bytecodeStructsHFile.write("} // namespace JSC \n") | 
 |  | 
 |         if bytecodeHFilename and section['emitOpcodeIDStringValuesInHFile']: | 
 |             bytecodeNum = 0 | 
 |             for bytecode in section["bytecodes"]: | 
 |                 bytecodeHFile.write("#define {0}_value_string \"{1}\"\n".format(bytecode["name"], bytecodeNum)) | 
 |                 firstMacro = False | 
 |                 bytecodeNum = bytecodeNum + 1 | 
 |  | 
 |             bytecodeHFile.write("\n")             | 
 |  | 
 |         if initASMFileName and section['emitInASMFile']: | 
 |             prefix = "" | 
 |             if "asmPrefix" in section: | 
 |                 prefix = section["asmPrefix"] | 
 |             for bytecode in section["bytecodes"]: | 
 |                 initBytecodesFile.write("setEntryAddress({0}, _{1}{2})\n".format(initASMBytecodeNum, prefix, bytecode["name"])) | 
 |                 initASMBytecodeNum = initASMBytecodeNum + 1 | 
 |  | 
 |     if bytecodeHFilename: | 
 |         bytecodeHFile.close() | 
 |  | 
 |     if initASMFileName: | 
 |         initBytecodesFile.close() | 
 |  | 
 |     bytecodeFile.close() | 
 |  | 
 |     exit(0) |