const std = @import("std"); const builtin = @import("builtin"); const Build = std.Build; /// When building from source, which repository and revision to clone. const spirv_tools_repository = "https://github.com/KhronosGroup/SPIRV-Tools"; const spirv_headers_repository = "https://github.com/KhronosGroup/SPIRV-Headers"; const log = std.log.scoped(.glslang_zig); const tools_prefix = "SPIRV-Tools"; const headers_prefix = "SPIRV-Headers"; pub fn build(b: *Build) !void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); const debug_symbols = b.option(bool, "debug_symbols", "Whether to produce detailed debug symbols (g0) or not. These increase binary size considerably.") orelse false; const build_shared = b.option(bool, "shared", "Build spirv-tools as a shared library") orelse false; _ = build_spirv(b, optimize, target, debug_symbols, build_shared); } pub fn build_spirv(b: *Build, optimize: std.builtin.OptimizeMode, target: std.ResolvedTarget, debug_symbols: bool, build_shared: bool) *std.Build.Step.Compile { var cflags = std.ArrayList([]const u8).init(b.allocator); var cppflags = std.ArrayList([]const u8).init(b.allocator); if (!debug_symbols) { try cflags.append("-g0"); try cppflags.append("-g0"); } try cppflags.append("-std=c++17"); const base_flags = &.{ "-Wno-unused-command-line-argument", "-Wno-unused-variable", "-Wno-missing-exception-spec", "-Wno-macro-redefined", "-Wno-unknown-attributes", "-Wno-implicit-fallthrough", "-fms-extensions", }; try cflags.appendSlice(base_flags); try cppflags.appendSlice(base_flags); const spirv_cpp_sources = spirv_tools ++ spirv_tools_util ++ spirv_tools_reduce ++ spirv_tools_link ++ spirv_tools_val ++ // spirv_tools_wasm ++ // Wasm build support- requires emscripten toolchain spirv_tools_opt; var spv_lib = null; if (build_shared) { spv_lib = b.addSharedLibrary(.{ .name = "SPIRV-Tools", .root_source_file = b.addWriteFiles().add("empty.c", ""), .optimize = optimize, .target = target, }); } else { spv_lib = b.addStaticLibrary(.{ .name = "SPIRV-Tools", .root_source_file = b.addWriteFiles().add("empty.c", ""), .optimize = optimize, .target = target, }); } if (target.result.os.tag == .windows) { spv_lib.defineCMacro("SPIRV_WINDOWS", ""); } else if (target.result.os.tag == .linux) { spv_lib.defineCMacro("SPIRV_LINUX", ""); } else if (target.result.os.tag == .macos) { spv_lib.defineCMacro("SPIRV_MAC", ""); } else if (target.result.os.tag == .ios) { spv_lib.defineCMacro("SPIRV_IOS", ""); } else if (target.result.os.tag == .tvos) { spv_lib.defineCMacro("SPIRV_TVOS", ""); } else if (target.result.os.tag == .kfreebsd) { spv_lib.defineCMacro("SPIRV_FREEBSD", ""); } else if (target.result.os.tag == .openbsd) { spv_lib.defineCMacro("SPIRV_OPENBSD", ""); } else if (target.result.os.tag == .fuchsia) { spv_lib.defineCMacro("SPIRV_FUCHSIA", ""); } else { log.err("Compilation target incompatible with SPIR-V.", .{}); std.process.exit(1); } var download_source = DownloadSourceStep.init(b); download_source.repository = spirv_tools_repository; download_source.revision = ""; download_source.output = tools_prefix; var download_headers = DownloadSourceStep.init(b); download_headers.repository = spirv_headers_repository; download_headers.revision = ""; download_headers.output = headers_prefix; var build_grammar = BuildSPIRVGrammarStep.init(b); spv_lib.step.dependOn(&download_source); spv_lib.step.dependOn(&download_headers); spv_lib.step.dependOn(&build_grammar.step); spv_lib.addCSourceFiles(.{ .files = &spirv_cpp_sources, .flags = cppflags.items, }); spv_lib.defineCMacro("SPIRV_COLOR_TERMINAL", ""); // Pretty lights by default addSPIRVIncludes(spv_lib); linkSPIRVDependencies(spv_lib); b.installArtifact(spv_lib); return spv_lib; } fn linkSPIRVDependencies(step: *std.Build.Step.Compile) void { const target = step.rootModuleTarget(); if (target.abi == .msvc) { step.linkLibC(); } else { step.linkLibCpp(); } if (target.os.tag == .windows) { step.linkSystemLibrary("ole32"); step.linkSystemLibrary("oleaut32"); } } fn addSPIRVIncludes(step: *std.Build.Step.Compile) void { // Generated SPIR-V headers get thrown in here step.addIncludePath(.{ .path = "generated-include" }); step.addIncludePath(.{ .path = tools_prefix ++ "/external/SPIRV-Tools" }); step.addIncludePath(.{ .path = tools_prefix ++ "/external/SPIRV-Tools/include" }); step.addIncludePath(.{ .path = tools_prefix ++ "/external/SPIRV-Tools/source" }); step.addIncludePath(.{ .path = tools_prefix ++ "/external/SPIRV-Headers/include" }); } fn ensureCommandExists(allocator: std.mem.Allocator, name: []const u8, exist_check: []const u8) bool { const result = std.ChildProcess.run(.{ .allocator = allocator, .argv = &[_][]const u8{ name, exist_check }, .cwd = ".", }) catch // e.g. FileNotFound { return false; }; defer { allocator.free(result.stderr); allocator.free(result.stdout); } if (result.term.Exited != 0) return false; return true; } // ------------------------------------------ // Source cloning logic // ------------------------------------------ fn ensureGitRepoCloned(allocator: std.mem.Allocator, clone_url: []const u8, revision: []const u8, dir: []const u8) !void { if (isEnvVarTruthy(allocator, "NO_ENSURE_SUBMODULES") or isEnvVarTruthy(allocator, "NO_ENSURE_GIT")) { return; } ensureGit(allocator); if (std.fs.openDirAbsolute(dir, .{})) |_| { const current_revision = try getCurrentGitRevision(allocator, dir); if (!std.mem.eql(u8, current_revision, revision)) { // Reset to the desired revision exec(allocator, &[_][]const u8{ "git", "fetch" }, dir) catch |err| log.warn("failed to 'git fetch' in {s}: {s}\n", .{ dir, @errorName(err) }); try exec(allocator, &[_][]const u8{ "git", "checkout", "--quiet", "--force", revision }, dir); try exec(allocator, &[_][]const u8{ "git", "submodule", "update", "--init", "--recursive" }, dir); } return; } else |err| return switch (err) { error.FileNotFound => { log.info("cloning required dependency..\ngit clone {s} {s}..\n", .{ clone_url, dir }); try exec(allocator, &[_][]const u8{ "git", "clone", "-c", "core.longpaths=true", clone_url, dir }, sdkPath("/")); try exec(allocator, &[_][]const u8{ "git", "checkout", "--quiet", "--force", revision }, dir); try exec(allocator, &[_][]const u8{ "git", "submodule", "update", "--init", "--recursive" }, dir); return; }, else => err, }; } fn getCurrentGitRevision(allocator: std.mem.Allocator, cwd: []const u8) ![]const u8 { const result = try std.ChildProcess.run(.{ .allocator = allocator, .argv = &.{ "git", "rev-parse", "HEAD" }, .cwd = cwd }); allocator.free(result.stderr); if (result.stdout.len > 0) return result.stdout[0 .. result.stdout.len - 1]; // trim newline return result.stdout; } // Command validation logic moved to ensureCommandExists() fn ensureGit(allocator: std.mem.Allocator) void { if (!ensureCommandExists(allocator, "git", "--version")) { log.err("'git --version' failed. Is git not installed?", .{}); std.process.exit(1); } } fn exec(allocator: std.mem.Allocator, argv: []const []const u8, cwd: []const u8) !void { log.info("cd {s}", .{cwd}); var buf = std.ArrayList(u8).init(allocator); for (argv) |arg| { try std.fmt.format(buf.writer(), "{s} ", .{arg}); } log.info("{s}", .{buf.items}); var child = std.ChildProcess.init(argv, allocator); child.cwd = cwd; _ = try child.spawnAndWait(); } fn isEnvVarTruthy(allocator: std.mem.Allocator, name: []const u8) bool { if (std.process.getEnvVarOwned(allocator, name)) |truthy| { defer allocator.free(truthy); if (std.mem.eql(u8, truthy, "true")) return true; return false; } else |_| { return false; } } fn sdkPath(comptime suffix: []const u8) []const u8 { if (suffix[0] != '/') @compileError("suffix must be an absolute path"); return comptime blk: { const root_dir = std.fs.path.dirname(@src().file) orelse "."; break :blk root_dir ++ suffix; }; } var download_mutex = std.Thread.Mutex{}; const DownloadSourceStep = struct { repository: []const u8, revision: []const u8, output: []const u8, step: std.Build.Step, b: *std.Build, fn init(b: *std.Build) *DownloadSourceStep { const download_step = b.allocator.create(DownloadSourceStep) catch unreachable; download_step.* = .{ .step = std.Build.Step.init(.{ .id = .custom, .name = "download", .owner = b, .makeFn = &make, }), .b = b, }; return download_step; } fn make(step_ptr: *std.Build.Step, prog_node: *std.Progress.Node) anyerror!void { _ = prog_node; const download_step: DownloadSourceStep = @fieldParentPtr("step", step_ptr); const b = download_step.b; // Zig will run build steps in parallel if possible, so if there were two invocations of // then this function would be called in parallel. We're manipulating the FS here // and so need to prevent that. download_mutex.lock(); defer download_mutex.unlock(); try ensureGitRepoCloned(b.allocator, download_step.repository, download_step.revision, download_step.output); } }; // ------------------------------------------ // SPIR-V include generation logic // ------------------------------------------ fn ensurePython(allocator: std.mem.Allocator) void { if (!ensureCommandExists(allocator, "python3", "--version")) { log.err("'python3 --version' failed. Is python not installed?", .{}); std.process.exit(1); } } const spirv_headers_path = tools_prefix ++ "/external/SPIRV-Headers"; const spirv_tools_path = tools_prefix ++ "/external/SPIRV-Tools"; const spirv_output_path = "generated-include/spirv-tools"; const grammar_tables_script = spirv_tools_path ++ "/utils/generate_grammar_tables.py"; const debuginfo_insts_file = spirv_headers_path ++ "/include/spirv/unified1/extinst.debuginfo.grammar.json"; const cldebuginfo100_insts_file = spirv_headers_path ++ "/include/spirv/unified1/extinst.opencl.debuginfo.100.grammar.json"; fn spvHeaderFile(comptime version: []const u8, comptime file_name: []const u8) []const u8 { return spirv_headers_path ++ "/include/spirv/" ++ version ++ "/" ++ file_name; } // Most of this was derived from the BUILD.gn file in SPIRV-Tools fn genSPIRVCoreTables(allocator: std.mem.Allocator, comptime version: []const u8) void { const core_json_file = spvHeaderFile(version, "spirv.core.grammar.json"); // Outputs const core_insts_file = spirv_output_path ++ "/core.insts-" ++ version ++ ".inc"; const operand_kinds_file = spirv_output_path ++ "/operand.kinds-" ++ version ++ ".inc"; const args = &[_][]const u8{ "python3", grammar_tables_script, "--spirv-core-grammar", core_json_file, "--core-insts-output", core_insts_file, "--extinst-debuginfo-grammar", debuginfo_insts_file, "--extinst-cldebuginfo100-grammar", cldebuginfo100_insts_file, "--operand-kinds-output", operand_kinds_file, "--output-language", "c++" }; exec(allocator, args, sdkPath("/")) catch |err| { log.err("Failed to build SPIR-V core tables: error: {s}", .{@errorName(err)}); std.process.exit(1); }; } fn genSPIRVCoreEnums(allocator: std.mem.Allocator, comptime version: []const u8) void { const core_json_file = spvHeaderFile(version, "spirv.core.grammar.json"); const extension_enum_file = spirv_output_path ++ "/extension_enum.inc"; const extension_map_file = spirv_output_path ++ "/enum_string_mapping.inc"; const args = &[_][]const u8{ "python3", grammar_tables_script, "--spirv-core-grammar", core_json_file, "--extinst-debuginfo-grammar", debuginfo_insts_file, "--extinst-cldebuginfo100-grammar", cldebuginfo100_insts_file, "--extension-enum-output", extension_enum_file, "--enum-string-mapping-output", extension_map_file, "--output-language", "c++" }; exec(allocator, args, sdkPath("/")) catch |err| { log.err("Failed to build SPIR-V core enums: error: {s}", .{@errorName(err)}); std.process.exit(1); }; } fn genSPIRVGlslTables(allocator: std.mem.Allocator, comptime version: []const u8) void { const core_json_file = spvHeaderFile(version, "spirv.core.grammar.json"); const glsl_json_file = spvHeaderFile(version, "extinst.glsl.std.450.grammar.json"); const glsl_insts_file = spirv_output_path ++ "/glsl.std.450.insts.inc"; const args = &[_][]const u8{ "python3", grammar_tables_script, "--spirv-core-grammar", core_json_file, "--extinst-debuginfo-grammar", debuginfo_insts_file, "--extinst-cldebuginfo100-grammar", cldebuginfo100_insts_file, "--extinst-glsl-grammar", glsl_json_file, "--glsl-insts-output", glsl_insts_file, "--output-language", "c++" }; exec(allocator, args, sdkPath("/")) catch |err| { log.err("Failed to build SPIR-V GLSL tables: error: {s}", .{@errorName(err)}); std.process.exit(1); }; } fn genSPIRVOpenCLTables(allocator: std.mem.Allocator, comptime version: []const u8) void { const core_json_file = spvHeaderFile(version, "spirv.core.grammar.json"); const opencl_json_file = spvHeaderFile(version, "extinst.opencl.std.100.grammar.json"); const opencl_insts_file = spirv_output_path ++ "/opencl.std.insts.inc"; const args = &[_][]const u8{ "python3", grammar_tables_script, "--spirv-core-grammar", core_json_file, "--extinst-debuginfo-grammar", debuginfo_insts_file, "--extinst-cldebuginfo100-grammar", cldebuginfo100_insts_file, "--extinst-opencl-grammar", opencl_json_file, "--opencl-insts-output", opencl_insts_file, }; exec(allocator, args, sdkPath("/")) catch |err| { log.err("Failed to build SPIR-V OpenCL tables: error: {s}", .{@errorName(err)}); std.process.exit(1); }; } fn genSPIRVLanguageHeader(allocator: std.mem.Allocator, comptime name: []const u8, comptime grammar_file: []const u8) void { const script = spirv_tools_path ++ "/utils/generate_language_headers.py"; const extinst_output_path = spirv_output_path ++ "/" ++ name ++ ".h"; const args = &[_][]const u8{ "python3", script, "--extinst-grammar", grammar_file, "--extinst-output-path", extinst_output_path, }; exec(allocator, args, sdkPath("/")) catch |err| { log.err("Failed to generate SPIR-V language header '" ++ name ++ "'. error: {s}", .{@errorName(err)}); std.process.exit(1); }; } fn genSPIRVVendorTable(allocator: std.mem.Allocator, comptime name: []const u8, comptime operand_kind_tools_prefix: []const u8) void { const extinst_vendor_grammar = spirv_headers_path ++ "/include/spirv/unified1/extinst." ++ name ++ ".grammar.json"; const extinst_file = spirv_output_path ++ "/" ++ name ++ ".insts.inc"; const args = &[_][]const u8{ "python3", grammar_tables_script, "--extinst-vendor-grammar", extinst_vendor_grammar, "--vendor-insts-output", extinst_file, "--vendor-operand-kind-tools_prefix", operand_kind_tools_prefix, }; exec(allocator, args, sdkPath("/")) catch |err| { log.err("Failed to generate SPIR-V vendor table '" ++ name ++ "'. error: {s}", .{@errorName(err)}); std.process.exit(1); }; } fn genSPIRVRegistryTables(allocator: std.mem.Allocator) void { const script = spirv_tools_path ++ "/utils/generate_registry_tables.py"; const xml_file = spirv_headers_path ++ "/include/spirv/spir-v.xml"; const inc_file = spirv_output_path ++ "/generators.inc"; const args = &[_][]const u8{ "python3", script, "--xml", xml_file, "--generator", inc_file, }; exec(allocator, args, sdkPath("/")) catch |err| { log.err("Failed to generate SPIR-V registry tables. error: {s}", .{@errorName(err)}); std.process.exit(1); }; } fn buildSPIRVVersion(allocator: std.mem.Allocator) void { const script = spirv_tools_path ++ "/utils/update_build_version.py"; const changes_file = spirv_tools_path ++ "/CHANGES"; const inc_file = spirv_output_path ++ "/build-version.inc"; const args = &[_][]const u8{ "python3", script, changes_file, inc_file, }; exec(allocator, args, sdkPath("/")) catch |err| { log.err("Failed to generate SPIR-V build version. error: {s}", .{@errorName(err)}); std.process.exit(1); }; } fn generateSPIRVGrammar(allocator: std.mem.Allocator) void { ensurePython(allocator); genSPIRVCoreTables(allocator, "unified1"); genSPIRVCoreEnums(allocator, "unified1"); genSPIRVGlslTables(allocator, "1.0"); genSPIRVOpenCLTables(allocator, "1.0"); genSPIRVLanguageHeader(allocator, "DebugInfo", spvHeaderFile("unified1", "extinst.debuginfo.grammar.json")); genSPIRVLanguageHeader(allocator, "OpenCLDebugInfo100", spvHeaderFile("unified1", "extinst.opencl.debuginfo.100.grammar.json")); genSPIRVLanguageHeader(allocator, "NonSemanticShaderDebugInfo100", spvHeaderFile("unified1", "extinst.nonsemantic.shader.debuginfo.100.grammar.json")); genSPIRVVendorTable(allocator, "spv-amd-shader-explicit-vertex-parameter", "...nil..."); genSPIRVVendorTable(allocator, "spv-amd-shader-trinary-minmax", "...nil..."); genSPIRVVendorTable(allocator, "spv-amd-gcn-shader", "...nil..."); genSPIRVVendorTable(allocator, "spv-amd-shader-ballot", "...nil..."); genSPIRVVendorTable(allocator, "debuginfo", "...nil..."); genSPIRVVendorTable(allocator, "opencl.debuginfo.100", "CLDEBUG100_"); genSPIRVVendorTable(allocator, "nonsemantic.clspvreflection", "...nil..."); genSPIRVVendorTable(allocator, "nonsemantic.shader.debuginfo.100", "SHDEBUG100_"); genSPIRVRegistryTables(allocator); buildSPIRVVersion(allocator); } const BuildSPIRVGrammarStep = struct { step: std.Build.Step, b: *std.Build, fn init(b: *std.Build) *BuildSPIRVGrammarStep { const build_grammar_step = b.allocator.create(BuildSPIRVGrammarStep) catch unreachable; build_grammar_step.* = .{ .step = std.Build.Step.init(.{ .id = .custom, .name = "generate grammar", .owner = b, .makeFn = &make, }), .b = b, }; return build_grammar_step; } fn make(step_ptr: *std.Build.Step, prog_node: *std.Progress.Node) anyerror!void { _ = prog_node; const build_grammar_step: BuildSPIRVGrammarStep = @fieldParentPtr("step", step_ptr); const b = build_grammar_step.b; // Zig will run build steps in parallel if possible, so if there were two invocations of // then this function would be called in parallel. We're manipulating the FS here // and so need to prevent that. download_mutex.lock(); defer download_mutex.unlock(); generateSPIRVGrammar(b.allocator); } }; const tools_source_path = tools_prefix ++ "/source/"; const spirv_tools = [_][]const u8{ tools_source_path ++ "spirv_reducer_options.cpp", tools_source_path ++ "spirv_validator_options.cpp", tools_source_path ++ "spirv_endian.cpp", tools_source_path ++ "table.cpp", tools_source_path ++ "text.cpp", tools_source_path ++ "spirv_fuzzer_options.cpp", tools_source_path ++ "parsed_operand.cpp", tools_source_path ++ "operand.cpp", tools_source_path ++ "assembly_grammar.cpp", tools_source_path ++ "text_handler.cpp", tools_source_path ++ "opcode.cpp", tools_source_path ++ "pch_source.cpp", tools_source_path ++ "software_version.cpp", tools_source_path ++ "binary.cpp", tools_source_path ++ "ext_inst.cpp", tools_source_path ++ "print.cpp", tools_source_path ++ "disassemble.cpp", tools_source_path ++ "enum_string_mapping.cpp", tools_source_path ++ "spirv_optimizer_options.cpp", tools_source_path ++ "libspirv.cpp", tools_source_path ++ "diagnostic.cpp", tools_source_path ++ "spirv_target_env.cpp", tools_source_path ++ "name_mapper.cpp", tools_source_path ++ "extensions.cpp", }; const tools_reduce_path = tools_source_path ++ "reduce/"; const spirv_tools_reduce = [_][]const u8{ tools_reduce_path ++ "structured_loop_to_selection_reduction_opportunity_finder.cpp", tools_reduce_path ++ "structured_construct_to_block_reduction_opportunity_finder.cpp", tools_reduce_path ++ "operand_to_undef_reduction_opportunity_finder.cpp", tools_reduce_path ++ "remove_block_reduction_opportunity_finder.cpp", tools_reduce_path ++ "change_operand_reduction_opportunity.cpp", tools_reduce_path ++ "remove_unused_struct_member_reduction_opportunity_finder.cpp", tools_reduce_path ++ "simple_conditional_branch_to_branch_opportunity_finder.cpp", tools_reduce_path ++ "remove_function_reduction_opportunity.cpp", tools_reduce_path ++ "merge_blocks_reduction_opportunity_finder.cpp", tools_reduce_path ++ "simple_conditional_branch_to_branch_reduction_opportunity.cpp", tools_reduce_path ++ "structured_construct_to_block_reduction_opportunity.cpp", tools_reduce_path ++ "reduction_opportunity.cpp", tools_reduce_path ++ "change_operand_to_undef_reduction_opportunity.cpp", tools_reduce_path ++ "remove_function_reduction_opportunity_finder.cpp", tools_reduce_path ++ "remove_selection_reduction_opportunity.cpp", tools_reduce_path ++ "operand_to_const_reduction_opportunity_finder.cpp", tools_reduce_path ++ "operand_to_dominating_id_reduction_opportunity_finder.cpp", tools_reduce_path ++ "remove_block_reduction_opportunity.cpp", tools_reduce_path ++ "reduction_pass.cpp", tools_reduce_path ++ "conditional_branch_to_simple_conditional_branch_reduction_opportunity.cpp", tools_reduce_path ++ "conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp", tools_reduce_path ++ "remove_selection_reduction_opportunity_finder.cpp", tools_reduce_path ++ "pch_source_reduce.cpp", tools_reduce_path ++ "reduction_util.cpp", tools_reduce_path ++ "merge_blocks_reduction_opportunity.cpp", tools_reduce_path ++ "reducer.cpp", tools_reduce_path ++ "remove_struct_member_reduction_opportunity.cpp", tools_reduce_path ++ "structured_loop_to_selection_reduction_opportunity.cpp", tools_reduce_path ++ "reduction_opportunity_finder.cpp", tools_reduce_path ++ "remove_instruction_reduction_opportunity.cpp", tools_reduce_path ++ "remove_unused_instruction_reduction_opportunity_finder.cpp", }; const tools_opt_path = tools_source_path ++ "opt/"; const spirv_tools_opt = [_][]const u8{ tools_opt_path ++ "loop_unswitch_pass.cpp", tools_opt_path ++ "eliminate_dead_output_stores_pass.cpp", tools_opt_path ++ "dominator_tree.cpp", tools_opt_path ++ "flatten_decoration_pass.cpp", tools_opt_path ++ "convert_to_half_pass.cpp", tools_opt_path ++ "loop_unroller.cpp", tools_opt_path ++ "interface_var_sroa.cpp", tools_opt_path ++ "wrap_opkill.cpp", tools_opt_path ++ "inst_debug_printf_pass.cpp", tools_opt_path ++ "liveness.cpp", tools_opt_path ++ "eliminate_dead_io_components_pass.cpp", tools_opt_path ++ "feature_manager.cpp", tools_opt_path ++ "instrument_pass.cpp", tools_opt_path ++ "scalar_replacement_pass.cpp", tools_opt_path ++ "loop_dependence_helpers.cpp", tools_opt_path ++ "redundancy_elimination.cpp", tools_opt_path ++ "strip_nonsemantic_info_pass.cpp", tools_opt_path ++ "aggressive_dead_code_elim_pass.cpp", tools_opt_path ++ "fix_func_call_arguments.cpp", tools_opt_path ++ "fold_spec_constant_op_and_composite_pass.cpp", tools_opt_path ++ "dataflow.cpp", tools_opt_path ++ "block_merge_util.cpp", tools_opt_path ++ "pass.cpp", tools_opt_path ++ "relax_float_ops_pass.cpp", tools_opt_path ++ "interp_fixup_pass.cpp", tools_opt_path ++ "instruction.cpp", tools_opt_path ++ "folding_rules.cpp", tools_opt_path ++ "inst_bindless_check_pass.cpp", tools_opt_path ++ "ssa_rewrite_pass.cpp", tools_opt_path ++ "inline_exhaustive_pass.cpp", tools_opt_path ++ "amd_ext_to_khr.cpp", tools_opt_path ++ "dead_branch_elim_pass.cpp", tools_opt_path ++ "loop_dependence.cpp", tools_opt_path ++ "eliminate_dead_constant_pass.cpp", tools_opt_path ++ "simplification_pass.cpp", tools_opt_path ++ "eliminate_dead_functions_pass.cpp", tools_opt_path ++ "loop_fusion_pass.cpp", tools_opt_path ++ "decoration_manager.cpp", tools_opt_path ++ "debug_info_manager.cpp", tools_opt_path ++ "basic_block.cpp", tools_opt_path ++ "switch_descriptorset_pass.cpp", tools_opt_path ++ "code_sink.cpp", tools_opt_path ++ "fix_storage_class.cpp", tools_opt_path ++ "convert_to_sampled_image_pass.cpp", tools_opt_path ++ "graphics_robust_access_pass.cpp", tools_opt_path ++ "inline_opaque_pass.cpp", tools_opt_path ++ "strip_debug_info_pass.cpp", tools_opt_path ++ "dominator_analysis.cpp", tools_opt_path ++ "upgrade_memory_model.cpp", tools_opt_path ++ "loop_peeling.cpp", tools_opt_path ++ "register_pressure.cpp", tools_opt_path ++ "unify_const_pass.cpp", tools_opt_path ++ "replace_desc_array_access_using_var_index.cpp", tools_opt_path ++ "analyze_live_input_pass.cpp", tools_opt_path ++ "invocation_interlock_placement_pass.cpp", tools_opt_path ++ "scalar_analysis.cpp", tools_opt_path ++ "local_redundancy_elimination.cpp", tools_opt_path ++ "inst_buff_addr_check_pass.cpp", tools_opt_path ++ "const_folding_rules.cpp", tools_opt_path ++ "trim_capabilities_pass.cpp", tools_opt_path ++ "reduce_load_size.cpp", tools_opt_path ++ "build_module.cpp", tools_opt_path ++ "local_single_store_elim_pass.cpp", tools_opt_path ++ "mem_pass.cpp", tools_opt_path ++ "module.cpp", tools_opt_path ++ "scalar_analysis_simplification.cpp", tools_opt_path ++ "function.cpp", tools_opt_path ++ "desc_sroa.cpp", tools_opt_path ++ "def_use_manager.cpp", tools_opt_path ++ "compact_ids_pass.cpp", tools_opt_path ++ "workaround1209.cpp", tools_opt_path ++ "instruction_list.cpp", tools_opt_path ++ "loop_fission.cpp", tools_opt_path ++ "strength_reduction_pass.cpp", tools_opt_path ++ "remove_unused_interface_variables_pass.cpp", tools_opt_path ++ "fold.cpp", tools_opt_path ++ "ccp_pass.cpp", tools_opt_path ++ "if_conversion.cpp", tools_opt_path ++ "value_number_table.cpp", tools_opt_path ++ "loop_descriptor.cpp", tools_opt_path ++ "inline_pass.cpp", tools_opt_path ++ "struct_cfg_analysis.cpp", tools_opt_path ++ "composite.cpp", tools_opt_path ++ "freeze_spec_constant_value_pass.cpp", tools_opt_path ++ "cfg.cpp", tools_opt_path ++ "ir_loader.cpp", tools_opt_path ++ "licm_pass.cpp", tools_opt_path ++ "replace_invalid_opc.cpp", tools_opt_path ++ "propagator.cpp", tools_opt_path ++ "types.cpp", tools_opt_path ++ "private_to_local_pass.cpp", tools_opt_path ++ "spread_volatile_semantics.cpp", tools_opt_path ++ "dead_variable_elimination.cpp", tools_opt_path ++ "loop_utils.cpp", tools_opt_path ++ "local_access_chain_convert_pass.cpp", tools_opt_path ++ "cfg_cleanup_pass.cpp", tools_opt_path ++ "combine_access_chains.cpp", tools_opt_path ++ "copy_prop_arrays.cpp", tools_opt_path ++ "type_manager.cpp", tools_opt_path ++ "ir_context.cpp", tools_opt_path ++ "constants.cpp", tools_opt_path ++ "remove_dontinline_pass.cpp", tools_opt_path ++ "dead_insert_elim_pass.cpp", tools_opt_path ++ "pass_manager.cpp", tools_opt_path ++ "merge_return_pass.cpp", tools_opt_path ++ "remove_duplicates_pass.cpp", tools_opt_path ++ "eliminate_dead_functions_util.cpp", tools_opt_path ++ "eliminate_dead_members_pass.cpp", tools_opt_path ++ "control_dependence.cpp", tools_opt_path ++ "vector_dce.cpp", tools_opt_path ++ "optimizer.cpp", tools_opt_path ++ "block_merge_pass.cpp", tools_opt_path ++ "desc_sroa_util.cpp", tools_opt_path ++ "local_single_block_elim_pass.cpp", tools_opt_path ++ "set_spec_constant_default_value_pass.cpp", tools_opt_path ++ "pch_source_opt.cpp", tools_opt_path ++ "loop_fusion.cpp", }; const tools_util_path = tools_source_path ++ "util/"; const spirv_tools_util = [_][]const u8{ tools_util_path ++ "bit_vector.cpp", tools_util_path ++ "parse_number.cpp", tools_util_path ++ "string_utils.cpp", tools_util_path ++ "timer.cpp", }; const spirv_tools_wasm = [_][]const u8{ tools_source_path ++ "wasm/spirv-tools.cpp", }; const spirv_tools_link = [_][]const u8{ tools_source_path ++ "link/linker.cpp", }; const tools_val_path = tools_source_path ++ "val/"; const spirv_tools_val = [_][]const u8{ tools_val_path ++ "validate_extensions.cpp", tools_val_path ++ "validate_conversion.cpp", tools_val_path ++ "validate_arithmetics.cpp", tools_val_path ++ "validate_primitives.cpp", tools_val_path ++ "validate_ray_tracing.cpp", tools_val_path ++ "validate_builtins.cpp", tools_val_path ++ "validate_atomics.cpp", tools_val_path ++ "validate_memory.cpp", tools_val_path ++ "instruction.cpp", tools_val_path ++ "validate_ray_tracing_reorder.cpp", tools_val_path ++ "validate_ray_query.cpp", tools_val_path ++ "validate_literals.cpp", tools_val_path ++ "construct.cpp", tools_val_path ++ "basic_block.cpp", tools_val_path ++ "validate.cpp", tools_val_path ++ "validate_small_type_uses.cpp", tools_val_path ++ "validate_instruction.cpp", tools_val_path ++ "validate_logicals.cpp", tools_val_path ++ "validate_execution_limitations.cpp", tools_val_path ++ "validate_mesh_shading.cpp", tools_val_path ++ "validate_capability.cpp", tools_val_path ++ "validate_decorations.cpp", tools_val_path ++ "validation_state.cpp", tools_val_path ++ "validate_function.cpp", tools_val_path ++ "function.cpp", tools_val_path ++ "validate_interfaces.cpp", tools_val_path ++ "validate_image.cpp", tools_val_path ++ "validate_constants.cpp", tools_val_path ++ "validate_derivatives.cpp", tools_val_path ++ "validate_cfg.cpp", tools_val_path ++ "validate_barriers.cpp", tools_val_path ++ "validate_mode_setting.cpp", tools_val_path ++ "validate_memory_semantics.cpp", tools_val_path ++ "validate_type.cpp", tools_val_path ++ "validate_misc.cpp", tools_val_path ++ "validate_debug.cpp", tools_val_path ++ "validate_bitwise.cpp", tools_val_path ++ "validate_adjacency.cpp", tools_val_path ++ "validate_annotation.cpp", tools_val_path ++ "validate_layout.cpp", tools_val_path ++ "validate_composites.cpp", tools_val_path ++ "validate_scopes.cpp", tools_val_path ++ "validate_non_uniform.cpp", tools_val_path ++ "validate_id.cpp", };