Skip to content

Commit

Permalink
Use ASM unknown function trampolines on GN
Browse files Browse the repository at this point in the history
The GN build doesn't currently support unknown function trampolines. To
fix that, we can use the assembly trampolines. To generate
the asm_offset assembly file, we can build it in a static library and
pass -S to it; that causes the assembly file to be copied into the .a
file. The python script can then extract it. This requires access to the
"ar" executable, so this mechanism is only used if a path to ar is
specified in //build_overrides/vulkan_loader.gni.

To fix incremental builds, "gen_defines.asm" must be included using
"#include", not ".include", since .include isn't a preprocessor
directive and isn't picked up by clang's depfile creation.
  • Loading branch information
John Bauman committed Aug 12, 2024
1 parent faeb588 commit ce22fe8
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 13 deletions.
65 changes: 60 additions & 5 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ if (is_win) {
}

config("vulkan_internal_config") {
defines = [
"VK_ENABLE_BETA_EXTENSIONS",
]
defines = [ "VK_ENABLE_BETA_EXTENSIONS" ]
if (is_clang || !is_win) {
cflags = [
"-Wno-conversion",
Expand Down Expand Up @@ -99,6 +97,52 @@ if (!is_android) {
} else {
library_type = "static_library"
}
support_unknown_function_handling = false
if (ar_path != "" && !is_win && (current_cpu == "arm64" || current_cpu == "x86_64")) {
support_unknown_function_handling = true
static_library("asm_offset") {
sources = [ "loader/asm_offset.c" ]
deps = [
"$vulkan_headers_dir:vulkan_headers",
]

if (is_fuchsia) {
deps += [
":dlopen_fuchsia",
]
}

# Output raw assembly instead of compiled object file. The assembly will be included as a member of the output ar file.
cflags = [ "-S" ]
configs += [ ":vulkan_internal_config" ]
configs += [ ":vulkan_loader_config" ]
}

action("gen_defines") {
script = "scripts/parse_asm_values.py"
deps = [ ":asm_offset" ]

inputs = [
"$target_out_dir/libasm_offset.a",
ar_path,
]
if (current_cpu == "arm64") {
cpu = "aarch64"
} else {
cpu = "x86_64"
}
args = [
rebase_path("$target_gen_dir/gen_defines.asm", root_build_dir),
rebase_path("$target_out_dir/libasm_offset.a", root_build_dir),
"GAS",
"Clang",
cpu,
rebase_path(ar_path, root_build_dir),
"libasm_offset.asm_offset.c.o",
]
outputs = [ "$target_gen_dir/gen_defines.asm" ]
}
}

target(library_type, "libvulkan") {
sources = [
Expand Down Expand Up @@ -135,8 +179,6 @@ if (!is_android) {
"loader/unknown_function_handling.h",
"loader/unknown_function_handling.c",
"loader/vk_loader_layer.h",

# TODO(jmadill): Use assembler where available.
"loader/vk_loader_platform.h",
"loader/wsi.c",
"loader/wsi.h",
Expand Down Expand Up @@ -217,6 +259,19 @@ if (!is_android) {

runtime_deps = [ "//sdk/lib/fdio:fdio_sdk" ]
}
if (support_unknown_function_handling) {
if (current_cpu == "arm64") {
sources += [ "loader/unknown_ext_chain_gas_aarch.S" ]
} else if (current_cpu == "x86_64") {
sources += [ "loader/unknown_ext_chain_gas_x86.S" ]
} else {
assert(false, "Unexpected CPU $current_cpu")
}

defines += ["UNKNOWN_FUNCTIONS_SUPPORTED=1"]
deps += [ ":gen_defines" ]
include_dirs = [ "$target_gen_dir" ]
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion loader/unknown_ext_chain_gas_aarch.S
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
// VkPhysicalDevice or a dispatchable object it can unwrap the object, possibly overwriting the wrapped physical device, and then
// jump to the next function in the call chain

.include "gen_defines.asm"
#include "gen_defines.asm"

/*
* References:
Expand Down Expand Up @@ -56,6 +56,7 @@
.macro PhysDevExtTramp num
.global vkPhysDevExtTramp\num
#if defined(__ELF__)
.type vkPhysDevExtTramp\num, @function
.hidden vkPhysDevExtTramp\num
#endif
.balign 4
Expand All @@ -77,6 +78,7 @@ vkPhysDevExtTramp\num:
.macro PhysDevExtTermin num
.global vkPhysDevExtTermin\num
#if defined(__ELF__)
.type vkPhysDevExtTermin\num, @function
.hidden vkPhysDevExtTermin\num
#endif
.balign 4
Expand Down
2 changes: 1 addition & 1 deletion loader/unknown_ext_chain_gas_x86.S
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#endif

.intel_syntax noprefix
.include "gen_defines.asm"
#include "gen_defines.asm"

.ifdef X86_64

Expand Down
2 changes: 2 additions & 0 deletions scripts/gn/secondary/build_overrides/vulkan_loader.gni
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ vulkan_gen_subdir = ""
# Vulkan loader build options
vulkan_loader_shared = true

# Path to ar or llvm-ar
ar_path = ""
25 changes: 19 additions & 6 deletions scripts/parse_asm_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import os.path
from os.path import exists
import re
import subprocess
import traceback


# Where to write the "gen_defines.asm" file
Expand Down Expand Up @@ -57,12 +59,23 @@
"DISPATCH_OFFSET_ICD_TERM",
"EXT_OFFSET_DEVICE_DISPATCH" ]

try:
with open(source_asm_file, 'r') as f:
asm_intermediate_file = f.read()
except IOError:
print("Could not open assembler file:", source_asm_file)
sys.exit(1)
if os.path.splitext(source_asm_file)[1] == ".a":
try:
ar_path = sys.argv[6]
asm_archive_member = sys.argv[7]
subprocess_result = subprocess.Popen([ar_path, "p", source_asm_file, asm_archive_member], stdout=subprocess.PIPE)
asm_intermediate_file = subprocess_result.stdout.read().decode("utf-8")
except IOError:
print("Could not open assembler archive file:", source_asm_file)
traceback.print_exc()
sys.exit(1)
else:
try:
with open(source_asm_file, 'r') as f:
asm_intermediate_file = f.read()
except IOError:
print("Could not open assembler file:", source_asm_file)
sys.exit(1)

with open(destination_file, "w", encoding="utf-8") as dest:
if assembler_type == "MASM":
Expand Down

0 comments on commit ce22fe8

Please sign in to comment.