Restore asm_offset printing code
authorCharles Giessen <charles@lunarg.com>
Fri, 21 Oct 2022 17:34:00 +0000 (11:34 -0600)
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>
Tue, 25 Oct 2022 13:43:07 +0000 (07:43 -0600)
The cross compiling workaround for asm_offset requires python, but this meant
that all builds required python. This commit re-adds the removed asm_offset
logic and then only requires python during cross compilation.

loader/CMakeLists.txt
loader/asm_offset.c

index 0be1c5d..eebb83a 100644 (file)
@@ -158,18 +158,25 @@ if(WIN32)
 
         add_executable(asm_offset asm_offset.c)
         target_link_libraries(asm_offset PRIVATE loader_specific_options)
-        # Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it.
-        target_compile_options(asm_offset PRIVATE "/Fa$<TARGET_FILE_DIR:asm_offset>/asm_offset.asm" /FA)
-        # Force off optimization so that the output assembly includes all the necessary info - optimizer would get rid of it otherwise.
-        target_compile_options(asm_offset PRIVATE /Od)
-
-        find_package(PythonInterp REQUIRED)
-        # Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on
-        add_custom_command(TARGET asm_offset POST_BUILD
-            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/parse_asm_values.py "${CMAKE_CURRENT_BINARY_DIR}/gen_defines.asm"
-                "$<TARGET_FILE_DIR:asm_offset>/asm_offset.asm" "MASM" "${CMAKE_CXX_COMPILER_ID}" "${CMAKE_SYSTEM_PROCESSOR}"
-            BYPRODUCTS gen_defines.asm
-            )
+        # If not cross compiling, run asm_offset to generage gen_defines.asm
+        if (NOT CMAKE_CROSSCOMPILING)
+            add_custom_command(TARGET asm_offset POST_BUILD
+                COMMAND asm_offset MASM
+                BYPRODUCTS gen_defines.asm)
+        else()
+            # Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it.
+            target_compile_options(asm_offset PRIVATE "/Fa$<TARGET_FILE_DIR:asm_offset>/asm_offset.asm" /FA)
+            # Force off optimization so that the output assembly includes all the necessary info - optimizer would get rid of it otherwise.
+            target_compile_options(asm_offset PRIVATE /Od)
+
+            find_package(PythonInterp REQUIRED)
+            # Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on
+            add_custom_command(TARGET asm_offset POST_BUILD
+                COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/parse_asm_values.py "${CMAKE_CURRENT_BINARY_DIR}/gen_defines.asm"
+                    "$<TARGET_FILE_DIR:asm_offset>/asm_offset.asm" "MASM" "${CMAKE_CXX_COMPILER_ID}" "${CMAKE_SYSTEM_PROCESSOR}"
+                BYPRODUCTS gen_defines.asm
+                )
+        endif()
         add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm)
         set_target_properties(loader_asm_gen_files PROPERTIES FOLDER ${LOADER_HELPER_FOLDER})
 
@@ -216,23 +223,30 @@ else() # i.e.: Linux
     endif()
 
     if(ASSEMBLER_WORKS)
-        add_library(asm_offset STATIC asm_offset.c)
+        add_executable(asm_offset asm_offset.c)
         target_link_libraries(asm_offset loader_specific_options)
-        # Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it.
-        target_compile_options(asm_offset PRIVATE -save-temps=obj)
-        if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-            set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.c.s")
-        elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
-            set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.s")
-        endif()
+        # If not cross compiling, run asm_offset to generage gen_defines.asm
+        if (NOT CMAKE_CROSSCOMPILING)
+            add_custom_command(TARGET asm_offset POST_BUILD
+                COMMAND asm_offset GAS
+                BYPRODUCTS gen_defines.asm)
+        else()
+            # Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it.
+            target_compile_options(asm_offset PRIVATE -save-temps=obj)
+            if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+                set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.c.s")
+            elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+                set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.s")
+            endif()
 
-        find_package(PythonInterp REQUIRED)
-        # Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on
-        add_custom_command(TARGET asm_offset POST_BUILD
-            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/parse_asm_values.py "$<TARGET_FILE_DIR:asm_offset>/gen_defines.asm"
-                "${ASM_OFFSET_INTERMEDIATE_LOCATION}" "GAS" "${CMAKE_CXX_COMPILER_ID}" "${CMAKE_SYSTEM_PROCESSOR}"
-            BYPRODUCTS gen_defines.asm
-            )
+            find_package(PythonInterp REQUIRED)
+            # Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on
+            add_custom_command(TARGET asm_offset POST_BUILD
+                COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/parse_asm_values.py "$<TARGET_FILE_DIR:asm_offset>/gen_defines.asm"
+                    "${ASM_OFFSET_INTERMEDIATE_LOCATION}" "GAS" "${CMAKE_CXX_COMPILER_ID}" "${CMAKE_SYSTEM_PROCESSOR}"
+                BYPRODUCTS gen_defines.asm
+                )
+        endif()
         add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm)
     else()
         if(USE_GAS)
index 82230b7..248d8fb 100644 (file)
@@ -68,6 +68,71 @@ struct ValueInfo {
     const char *comment;
 };
 
-// This file is not intended to be executed, as the generated asm contains all the relevant data which
-// the parse_asm_values.py script needs to write gen_defines.asm
-int main(int argc, char **argv) { return 0; }
+// This file can both be executed to produce gen_defines.asm and contains all the relevant data which
+// the parse_asm_values.py script needs to write gen_defines.asm, necessary for cross compilation
+int main(int argc, char **argv) {
+    const char *assembler = NULL;
+    for (int i = 0; i < argc; ++i) {
+        if (!strcmp(argv[i], "MASM")) {
+            assembler = "MASM";
+        } else if (!strcmp(argv[i], "GAS")) {
+            assembler = "GAS";
+        }
+    }
+    if (assembler == NULL) {
+        return 1;
+    }
+
+    struct ValueInfo values[] = {
+        // clang-format off
+        { .name = "VULKAN_LOADER_ERROR_BIT", .value = (size_t) VULKAN_LOADER_ERROR_BIT,
+            .comment = "The numerical value of the enum value 'VULKAN_LOADER_ERROR_BIT'" },
+        { .name = "PTR_SIZE", .value = sizeof(void*),
+            .comment = "The size of a pointer" },
+        { .name = "CHAR_PTR_SIZE", .value = sizeof(char *),
+            .comment = "The size of a 'const char *' struct" },
+        { .name = "FUNCTION_OFFSET_INSTANCE", .value = offsetof(struct loader_instance, phys_dev_ext_disp_functions),
+            .comment = "The offset of 'phys_dev_ext_disp_functions' within a 'loader_instance' struct" },
+        { .name = "PHYS_DEV_OFFSET_INST_DISPATCH", .value = offsetof(struct loader_instance_dispatch_table, phys_dev_ext),
+            .comment = "The offset of 'phys_dev_ext' within in 'loader_instance_dispatch_table' struct" },
+        { .name = "PHYS_DEV_OFFSET_PHYS_DEV_TRAMP", .value = offsetof(struct loader_physical_device_tramp, phys_dev),
+            .comment = "The offset of 'phys_dev' within a 'loader_physical_device_tramp' struct" },
+        { .name = "ICD_TERM_OFFSET_PHYS_DEV_TERM", .value = offsetof(struct loader_physical_device_term, this_icd_term),
+            .comment = "The offset of 'this_icd_term' within a 'loader_physical_device_term' struct" },
+        { .name = "PHYS_DEV_OFFSET_PHYS_DEV_TERM", .value = offsetof(struct loader_physical_device_term, phys_dev),
+            .comment = "The offset of 'phys_dev' within a 'loader_physical_device_term' struct" },
+        { .name = "INSTANCE_OFFSET_ICD_TERM", .value = offsetof(struct loader_icd_term, this_instance),
+            .comment = "The offset of 'this_instance' within a 'loader_icd_term' struct" },
+        { .name = "DISPATCH_OFFSET_ICD_TERM", .value = offsetof(struct loader_icd_term, phys_dev_ext),
+            .comment = "The offset of 'phys_dev_ext' within a 'loader_icd_term' struct" },
+        { .name = "EXT_OFFSET_DEVICE_DISPATCH", .value = offsetof(struct loader_dev_dispatch_table, ext_dispatch),
+            .comment = "The offset of 'ext_dispatch' within a 'loader_dev_dispatch_table' struct" },
+        // clang-format on
+    };
+
+    FILE *file = fopen("gen_defines.asm", "w");
+    fprintf(file, "\n");
+    if (!strcmp(assembler, "MASM")) {
+        for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i) {
+            fprintf(file, "%-32s equ " SIZE_T_FMT "; %s\n", values[i].name, values[i].value, values[i].comment);
+        }
+    } else if (!strcmp(assembler, "GAS")) {
+#if defined(__x86_64__) || defined(__i386__)
+        const char *comment_delimiter = "#";
+#if defined(__x86_64__)
+        fprintf(file, ".set X86_64, 1\n");
+#endif  // defined(__x86_64__)
+#elif defined(__aarch64__)
+        const char *comment_delimiter = "//";
+        fprintf(file, ".set AARCH_64, 1\n");
+#else
+        // Default comment delimiter
+        const char *comment_delimiter = "#";
+#endif
+        for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i) {
+            fprintf(file, ".set %-32s, " SIZE_T_FMT "%s %s\n", values[i].name, values[i].value, comment_delimiter,
+                    values[i].comment);
+        }
+    }
+    return fclose(file);
+}