• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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