1#!/usr/bin/python3 -i 2# 3# Copyright (c) 2022 The Khronos Group Inc. 4# Copyright (c) 2022 LunarG, Inc. 5 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18# Author: Charles Giessen <charles@lunarg.com> 19 20# This script reads in the 'intermediate output' of a compiler to look for sizeof/offsetof information 21# necessary for the assembler portions of the loader. This is achieved by forcing the compiler to output 22# the intermediate assembly output and looking for specific patterns which contain the relevant information 23 24import sys 25import os.path 26from os.path import exists 27import re 28import subprocess 29import traceback 30 31 32# Where to write the "gen_defines.asm" file 33destination_file = sys.argv[1] 34# The location the build system puts the intermediate asm file which depends on the compiler 35source_asm_file = sys.argv[2] 36# Whether we are using "MASM", "MARMASM" or "GAS" for the assembler 37assembler_type = sys.argv[3] 38# Whether we are using gcc, clang, or msvc 39compiler = sys.argv[4] 40# taken from CMAKE_SYSTEM_PROCESSOR - x86_64, aarch64|arm64, x86, aarch32|armhf 41# Only used with GAS/MARMASM - MASM doesn't need this, as it has its own way to determine x86 vs x64 42arch = sys.argv[5] 43 44POSIX_COMPILERS = ["GNU", "Clang", "AppleClang"] 45 46if destination_file is None or source_asm_file is None or assembler_type is None or compiler is None or arch is None: 47 print("Required command line arguments were not provided") 48 sys.exit(1) 49 50defines = ["VULKAN_LOADER_ERROR_BIT", 51 "PTR_SIZE", 52 "CHAR_PTR_SIZE", 53 "FUNCTION_OFFSET_INSTANCE", 54 "PHYS_DEV_OFFSET_INST_DISPATCH", 55 "PHYS_DEV_OFFSET_PHYS_DEV_TRAMP", 56 "ICD_TERM_OFFSET_PHYS_DEV_TERM", 57 "PHYS_DEV_OFFSET_PHYS_DEV_TERM", 58 "INSTANCE_OFFSET_ICD_TERM", 59 "DISPATCH_OFFSET_ICD_TERM", 60 "EXT_OFFSET_DEVICE_DISPATCH" ] 61 62if os.path.splitext(source_asm_file)[1] == ".a": 63 try: 64 ar_path = sys.argv[6] 65 asm_archive_member = sys.argv[7] 66 subprocess_result = subprocess.Popen([ar_path, "p", source_asm_file, asm_archive_member], stdout=subprocess.PIPE) 67 asm_intermediate_file = subprocess_result.stdout.read().decode("utf-8") 68 except IOError: 69 print("Could not open assembler archive file:", source_asm_file) 70 traceback.print_exc() 71 sys.exit(1) 72else: 73 try: 74 with open(source_asm_file, 'r') as f: 75 asm_intermediate_file = f.read() 76 except IOError: 77 print("Could not open assembler file:", source_asm_file) 78 sys.exit(1) 79 80with open(destination_file, "w", encoding="utf-8") as dest: 81 # special case vulkan error bit due to it not appearing in the asm - its defined in the header as 8 so it shouldn't change 82 if assembler_type == "MASM": 83 dest.write("VULKAN_LOADER_ERROR_BIT equ 8;\n") 84 elif assembler_type == 'MARMASM': 85 dest.write(' AREA loader_structs_details, DATA,READONLY\n') 86 if arch == "aarch64" or arch == "arm64": 87 dest.write("AARCH_64 EQU 1\n") 88 elif arch in ["aarch32", "armhf", "arm"]: 89 dest.write("AARCH_64 EQU 0\n") 90 else: 91 print('The parameter "arch" has value of ', arch, ' which is not recognized') 92 dest.write("VULKAN_LOADER_ERROR_BIT EQU 8\n") 93 elif assembler_type == "GAS": 94 # let the assembler know which platform to use 95 if arch == "x86_64": 96 dest.write(".set X86_64, 1\n") 97 elif arch == "aarch64" or arch == "arm64": 98 dest.write(".set AARCH_64, 1\n") 99 elif arch in ["aarch32", "armhf", "arm"]: 100 dest.write(".set AARCH_64, 0\n") 101 else: 102 print('The parameter "arch" has value of ', arch, ' which is not recognized') 103 # Nothing to write in the x86 case 104 105 for d in defines: 106 match = None 107 if compiler == "MSVC": 108 if d == "VULKAN_LOADER_ERROR_BIT": 109 continue # skip due to special case 110 if 'arm' in arch.lower(): 111 match = re.search('\\|'+ d + '\\| DCD[\t ]*0x([0-9a-f]+)', asm_intermediate_file) 112 else: 113 match = re.search(d + " DD [ ]*([0-9a-f]+)H", asm_intermediate_file) 114 elif compiler in POSIX_COMPILERS: 115 match = re.search(d + " = ([0-9]+)", asm_intermediate_file) 116 117 if len(match.groups()) > 0: 118 if compiler == "MSVC": 119 value = str(int(match.group(1), 16)) 120 elif compiler in POSIX_COMPILERS: 121 value = match.group(1) 122 123 # MASM uses hex values, decode them here 124 if assembler_type == "MASM": 125 dest.write(d + " equ " + value +";\n") 126 elif assembler_type == 'MARMASM': 127 dest.write(d + ' EQU ' + value +'\n') 128 elif assembler_type == "GAS": 129 dest.write(".set " + d + ", " + value + "\n") 130 else: 131 print("Couldn't find ", d) 132 sys.exit(1) 133 if assembler_type == 'MARMASM': 134 dest.write(" END\n") 135 136