Updated spirv-tools.

This commit is contained in:
Бранимир Караџић 2021-08-06 19:13:12 -07:00
parent f4642f5ba6
commit e67311db7e
14 changed files with 549 additions and 21 deletions

View File

@ -1 +1 @@
"v2021.3-dev", "SPIRV-Tools v2021.3-dev 13e61006818199bd11c1f6f0148d1258d8200375"
"v2021.3-dev", "SPIRV-Tools v2021.3-dev 25ef0e5c8566c2abe88852e3b72e0facccbbbcb9"

View File

@ -92,6 +92,8 @@ const char* ExtensionToString(Extension extension) {
return "SPV_INTEL_loop_fuse";
case Extension::kSPV_INTEL_media_block_io:
return "SPV_INTEL_media_block_io";
case Extension::kSPV_INTEL_optnone:
return "SPV_INTEL_optnone";
case Extension::kSPV_INTEL_shader_integer_functions2:
return "SPV_INTEL_shader_integer_functions2";
case Extension::kSPV_INTEL_subgroups:
@ -195,8 +197,8 @@ const char* ExtensionToString(Extension extension) {
bool GetExtensionFromString(const char* str, Extension* extension) {
static const char* known_ext_strs[] = { "SPV_AMD_gcn_shader", "SPV_AMD_gpu_shader_half_float", "SPV_AMD_gpu_shader_half_float_fetch", "SPV_AMD_gpu_shader_int16", "SPV_AMD_shader_ballot", "SPV_AMD_shader_explicit_vertex_parameter", "SPV_AMD_shader_fragment_mask", "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_trinary_minmax", "SPV_AMD_texture_gather_bias_lod", "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered", "SPV_EXT_fragment_invocation_density", "SPV_EXT_fragment_shader_interlock", "SPV_EXT_physical_storage_buffer", "SPV_EXT_shader_atomic_float16_add", "SPV_EXT_shader_atomic_float_add", "SPV_EXT_shader_atomic_float_min_max", "SPV_EXT_shader_image_int64", "SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer", "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_INTEL_arbitrary_precision_fixed_point", "SPV_INTEL_arbitrary_precision_floating_point", "SPV_INTEL_arbitrary_precision_integers", "SPV_INTEL_blocking_pipes", "SPV_INTEL_debug_module", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_float_controls2", "SPV_INTEL_fp_fast_math_mode", "SPV_INTEL_fpga_buffer_location", "SPV_INTEL_fpga_cluster_attributes", "SPV_INTEL_fpga_loop_controls", "SPV_INTEL_fpga_memory_accesses", "SPV_INTEL_fpga_memory_attributes", "SPV_INTEL_fpga_reg", "SPV_INTEL_function_pointers", "SPV_INTEL_inline_assembly", "SPV_INTEL_io_pipes", "SPV_INTEL_kernel_attributes", "SPV_INTEL_long_constant_composite", "SPV_INTEL_loop_fuse", "SPV_INTEL_media_block_io", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_subgroups", "SPV_INTEL_unstructured_loop_controls", "SPV_INTEL_usm_storage_classes", "SPV_INTEL_variable_length_array", "SPV_INTEL_vector_compute", "SPV_KHR_16bit_storage", "SPV_KHR_8bit_storage", "SPV_KHR_bit_instructions", "SPV_KHR_device_group", "SPV_KHR_expect_assume", "SPV_KHR_float_controls", "SPV_KHR_fragment_shading_rate", "SPV_KHR_integer_dot_product", "SPV_KHR_linkonce_odr", "SPV_KHR_multiview", "SPV_KHR_no_integer_wrap_decoration", "SPV_KHR_non_semantic_info", "SPV_KHR_physical_storage_buffer", "SPV_KHR_post_depth_coverage", "SPV_KHR_ray_query", "SPV_KHR_ray_tracing", "SPV_KHR_shader_atomic_counter_ops", "SPV_KHR_shader_ballot", "SPV_KHR_shader_clock", "SPV_KHR_shader_draw_parameters", "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_subgroup_uniform_control_flow", "SPV_KHR_subgroup_vote", "SPV_KHR_terminate_invocation", "SPV_KHR_variable_pointers", "SPV_KHR_vulkan_memory_model", "SPV_KHR_workgroup_memory_explicit_layout", "SPV_NVX_multiview_per_view_attributes", "SPV_NV_compute_shader_derivatives", "SPV_NV_cooperative_matrix", "SPV_NV_fragment_shader_barycentric", "SPV_NV_geometry_shader_passthrough", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", "SPV_NV_sample_mask_override_coverage", "SPV_NV_shader_image_footprint", "SPV_NV_shader_sm_builtins", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_shading_rate", "SPV_NV_stereo_view_rendering", "SPV_NV_viewport_array2", "SPV_VALIDATOR_ignore_type_decl_unique" };
static const Extension known_ext_ids[] = { Extension::kSPV_AMD_gcn_shader, Extension::kSPV_AMD_gpu_shader_half_float, Extension::kSPV_AMD_gpu_shader_half_float_fetch, Extension::kSPV_AMD_gpu_shader_int16, Extension::kSPV_AMD_shader_ballot, Extension::kSPV_AMD_shader_explicit_vertex_parameter, Extension::kSPV_AMD_shader_fragment_mask, Extension::kSPV_AMD_shader_image_load_store_lod, Extension::kSPV_AMD_shader_trinary_minmax, Extension::kSPV_AMD_texture_gather_bias_lod, Extension::kSPV_EXT_demote_to_helper_invocation, Extension::kSPV_EXT_descriptor_indexing, Extension::kSPV_EXT_fragment_fully_covered, Extension::kSPV_EXT_fragment_invocation_density, Extension::kSPV_EXT_fragment_shader_interlock, Extension::kSPV_EXT_physical_storage_buffer, Extension::kSPV_EXT_shader_atomic_float16_add, Extension::kSPV_EXT_shader_atomic_float_add, Extension::kSPV_EXT_shader_atomic_float_min_max, Extension::kSPV_EXT_shader_image_int64, Extension::kSPV_EXT_shader_stencil_export, Extension::kSPV_EXT_shader_viewport_index_layer, Extension::kSPV_GOOGLE_decorate_string, Extension::kSPV_GOOGLE_hlsl_functionality1, Extension::kSPV_GOOGLE_user_type, Extension::kSPV_INTEL_arbitrary_precision_fixed_point, Extension::kSPV_INTEL_arbitrary_precision_floating_point, Extension::kSPV_INTEL_arbitrary_precision_integers, Extension::kSPV_INTEL_blocking_pipes, Extension::kSPV_INTEL_debug_module, Extension::kSPV_INTEL_device_side_avc_motion_estimation, Extension::kSPV_INTEL_float_controls2, Extension::kSPV_INTEL_fp_fast_math_mode, Extension::kSPV_INTEL_fpga_buffer_location, Extension::kSPV_INTEL_fpga_cluster_attributes, Extension::kSPV_INTEL_fpga_loop_controls, Extension::kSPV_INTEL_fpga_memory_accesses, Extension::kSPV_INTEL_fpga_memory_attributes, Extension::kSPV_INTEL_fpga_reg, Extension::kSPV_INTEL_function_pointers, Extension::kSPV_INTEL_inline_assembly, Extension::kSPV_INTEL_io_pipes, Extension::kSPV_INTEL_kernel_attributes, Extension::kSPV_INTEL_long_constant_composite, Extension::kSPV_INTEL_loop_fuse, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_subgroups, Extension::kSPV_INTEL_unstructured_loop_controls, Extension::kSPV_INTEL_usm_storage_classes, Extension::kSPV_INTEL_variable_length_array, Extension::kSPV_INTEL_vector_compute, Extension::kSPV_KHR_16bit_storage, Extension::kSPV_KHR_8bit_storage, Extension::kSPV_KHR_bit_instructions, Extension::kSPV_KHR_device_group, Extension::kSPV_KHR_expect_assume, Extension::kSPV_KHR_float_controls, Extension::kSPV_KHR_fragment_shading_rate, Extension::kSPV_KHR_integer_dot_product, Extension::kSPV_KHR_linkonce_odr, Extension::kSPV_KHR_multiview, Extension::kSPV_KHR_no_integer_wrap_decoration, Extension::kSPV_KHR_non_semantic_info, Extension::kSPV_KHR_physical_storage_buffer, Extension::kSPV_KHR_post_depth_coverage, Extension::kSPV_KHR_ray_query, Extension::kSPV_KHR_ray_tracing, Extension::kSPV_KHR_shader_atomic_counter_ops, Extension::kSPV_KHR_shader_ballot, Extension::kSPV_KHR_shader_clock, Extension::kSPV_KHR_shader_draw_parameters, Extension::kSPV_KHR_storage_buffer_storage_class, Extension::kSPV_KHR_subgroup_uniform_control_flow, Extension::kSPV_KHR_subgroup_vote, Extension::kSPV_KHR_terminate_invocation, Extension::kSPV_KHR_variable_pointers, Extension::kSPV_KHR_vulkan_memory_model, Extension::kSPV_KHR_workgroup_memory_explicit_layout, Extension::kSPV_NVX_multiview_per_view_attributes, Extension::kSPV_NV_compute_shader_derivatives, Extension::kSPV_NV_cooperative_matrix, Extension::kSPV_NV_fragment_shader_barycentric, Extension::kSPV_NV_geometry_shader_passthrough, Extension::kSPV_NV_mesh_shader, Extension::kSPV_NV_ray_tracing, Extension::kSPV_NV_sample_mask_override_coverage, Extension::kSPV_NV_shader_image_footprint, Extension::kSPV_NV_shader_sm_builtins, Extension::kSPV_NV_shader_subgroup_partitioned, Extension::kSPV_NV_shading_rate, Extension::kSPV_NV_stereo_view_rendering, Extension::kSPV_NV_viewport_array2, Extension::kSPV_VALIDATOR_ignore_type_decl_unique };
static const char* known_ext_strs[] = { "SPV_AMD_gcn_shader", "SPV_AMD_gpu_shader_half_float", "SPV_AMD_gpu_shader_half_float_fetch", "SPV_AMD_gpu_shader_int16", "SPV_AMD_shader_ballot", "SPV_AMD_shader_explicit_vertex_parameter", "SPV_AMD_shader_fragment_mask", "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_trinary_minmax", "SPV_AMD_texture_gather_bias_lod", "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered", "SPV_EXT_fragment_invocation_density", "SPV_EXT_fragment_shader_interlock", "SPV_EXT_physical_storage_buffer", "SPV_EXT_shader_atomic_float16_add", "SPV_EXT_shader_atomic_float_add", "SPV_EXT_shader_atomic_float_min_max", "SPV_EXT_shader_image_int64", "SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer", "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_INTEL_arbitrary_precision_fixed_point", "SPV_INTEL_arbitrary_precision_floating_point", "SPV_INTEL_arbitrary_precision_integers", "SPV_INTEL_blocking_pipes", "SPV_INTEL_debug_module", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_float_controls2", "SPV_INTEL_fp_fast_math_mode", "SPV_INTEL_fpga_buffer_location", "SPV_INTEL_fpga_cluster_attributes", "SPV_INTEL_fpga_loop_controls", "SPV_INTEL_fpga_memory_accesses", "SPV_INTEL_fpga_memory_attributes", "SPV_INTEL_fpga_reg", "SPV_INTEL_function_pointers", "SPV_INTEL_inline_assembly", "SPV_INTEL_io_pipes", "SPV_INTEL_kernel_attributes", "SPV_INTEL_long_constant_composite", "SPV_INTEL_loop_fuse", "SPV_INTEL_media_block_io", "SPV_INTEL_optnone", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_subgroups", "SPV_INTEL_unstructured_loop_controls", "SPV_INTEL_usm_storage_classes", "SPV_INTEL_variable_length_array", "SPV_INTEL_vector_compute", "SPV_KHR_16bit_storage", "SPV_KHR_8bit_storage", "SPV_KHR_bit_instructions", "SPV_KHR_device_group", "SPV_KHR_expect_assume", "SPV_KHR_float_controls", "SPV_KHR_fragment_shading_rate", "SPV_KHR_integer_dot_product", "SPV_KHR_linkonce_odr", "SPV_KHR_multiview", "SPV_KHR_no_integer_wrap_decoration", "SPV_KHR_non_semantic_info", "SPV_KHR_physical_storage_buffer", "SPV_KHR_post_depth_coverage", "SPV_KHR_ray_query", "SPV_KHR_ray_tracing", "SPV_KHR_shader_atomic_counter_ops", "SPV_KHR_shader_ballot", "SPV_KHR_shader_clock", "SPV_KHR_shader_draw_parameters", "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_subgroup_uniform_control_flow", "SPV_KHR_subgroup_vote", "SPV_KHR_terminate_invocation", "SPV_KHR_variable_pointers", "SPV_KHR_vulkan_memory_model", "SPV_KHR_workgroup_memory_explicit_layout", "SPV_NVX_multiview_per_view_attributes", "SPV_NV_compute_shader_derivatives", "SPV_NV_cooperative_matrix", "SPV_NV_fragment_shader_barycentric", "SPV_NV_geometry_shader_passthrough", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", "SPV_NV_sample_mask_override_coverage", "SPV_NV_shader_image_footprint", "SPV_NV_shader_sm_builtins", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_shading_rate", "SPV_NV_stereo_view_rendering", "SPV_NV_viewport_array2", "SPV_VALIDATOR_ignore_type_decl_unique" };
static const Extension known_ext_ids[] = { Extension::kSPV_AMD_gcn_shader, Extension::kSPV_AMD_gpu_shader_half_float, Extension::kSPV_AMD_gpu_shader_half_float_fetch, Extension::kSPV_AMD_gpu_shader_int16, Extension::kSPV_AMD_shader_ballot, Extension::kSPV_AMD_shader_explicit_vertex_parameter, Extension::kSPV_AMD_shader_fragment_mask, Extension::kSPV_AMD_shader_image_load_store_lod, Extension::kSPV_AMD_shader_trinary_minmax, Extension::kSPV_AMD_texture_gather_bias_lod, Extension::kSPV_EXT_demote_to_helper_invocation, Extension::kSPV_EXT_descriptor_indexing, Extension::kSPV_EXT_fragment_fully_covered, Extension::kSPV_EXT_fragment_invocation_density, Extension::kSPV_EXT_fragment_shader_interlock, Extension::kSPV_EXT_physical_storage_buffer, Extension::kSPV_EXT_shader_atomic_float16_add, Extension::kSPV_EXT_shader_atomic_float_add, Extension::kSPV_EXT_shader_atomic_float_min_max, Extension::kSPV_EXT_shader_image_int64, Extension::kSPV_EXT_shader_stencil_export, Extension::kSPV_EXT_shader_viewport_index_layer, Extension::kSPV_GOOGLE_decorate_string, Extension::kSPV_GOOGLE_hlsl_functionality1, Extension::kSPV_GOOGLE_user_type, Extension::kSPV_INTEL_arbitrary_precision_fixed_point, Extension::kSPV_INTEL_arbitrary_precision_floating_point, Extension::kSPV_INTEL_arbitrary_precision_integers, Extension::kSPV_INTEL_blocking_pipes, Extension::kSPV_INTEL_debug_module, Extension::kSPV_INTEL_device_side_avc_motion_estimation, Extension::kSPV_INTEL_float_controls2, Extension::kSPV_INTEL_fp_fast_math_mode, Extension::kSPV_INTEL_fpga_buffer_location, Extension::kSPV_INTEL_fpga_cluster_attributes, Extension::kSPV_INTEL_fpga_loop_controls, Extension::kSPV_INTEL_fpga_memory_accesses, Extension::kSPV_INTEL_fpga_memory_attributes, Extension::kSPV_INTEL_fpga_reg, Extension::kSPV_INTEL_function_pointers, Extension::kSPV_INTEL_inline_assembly, Extension::kSPV_INTEL_io_pipes, Extension::kSPV_INTEL_kernel_attributes, Extension::kSPV_INTEL_long_constant_composite, Extension::kSPV_INTEL_loop_fuse, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_optnone, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_subgroups, Extension::kSPV_INTEL_unstructured_loop_controls, Extension::kSPV_INTEL_usm_storage_classes, Extension::kSPV_INTEL_variable_length_array, Extension::kSPV_INTEL_vector_compute, Extension::kSPV_KHR_16bit_storage, Extension::kSPV_KHR_8bit_storage, Extension::kSPV_KHR_bit_instructions, Extension::kSPV_KHR_device_group, Extension::kSPV_KHR_expect_assume, Extension::kSPV_KHR_float_controls, Extension::kSPV_KHR_fragment_shading_rate, Extension::kSPV_KHR_integer_dot_product, Extension::kSPV_KHR_linkonce_odr, Extension::kSPV_KHR_multiview, Extension::kSPV_KHR_no_integer_wrap_decoration, Extension::kSPV_KHR_non_semantic_info, Extension::kSPV_KHR_physical_storage_buffer, Extension::kSPV_KHR_post_depth_coverage, Extension::kSPV_KHR_ray_query, Extension::kSPV_KHR_ray_tracing, Extension::kSPV_KHR_shader_atomic_counter_ops, Extension::kSPV_KHR_shader_ballot, Extension::kSPV_KHR_shader_clock, Extension::kSPV_KHR_shader_draw_parameters, Extension::kSPV_KHR_storage_buffer_storage_class, Extension::kSPV_KHR_subgroup_uniform_control_flow, Extension::kSPV_KHR_subgroup_vote, Extension::kSPV_KHR_terminate_invocation, Extension::kSPV_KHR_variable_pointers, Extension::kSPV_KHR_vulkan_memory_model, Extension::kSPV_KHR_workgroup_memory_explicit_layout, Extension::kSPV_NVX_multiview_per_view_attributes, Extension::kSPV_NV_compute_shader_derivatives, Extension::kSPV_NV_cooperative_matrix, Extension::kSPV_NV_fragment_shader_barycentric, Extension::kSPV_NV_geometry_shader_passthrough, Extension::kSPV_NV_mesh_shader, Extension::kSPV_NV_ray_tracing, Extension::kSPV_NV_sample_mask_override_coverage, Extension::kSPV_NV_shader_image_footprint, Extension::kSPV_NV_shader_sm_builtins, Extension::kSPV_NV_shader_subgroup_partitioned, Extension::kSPV_NV_shading_rate, Extension::kSPV_NV_stereo_view_rendering, Extension::kSPV_NV_viewport_array2, Extension::kSPV_VALIDATOR_ignore_type_decl_unique };
const auto b = std::begin(known_ext_strs);
const auto e = std::end(known_ext_strs);
const auto found = std::equal_range(
@ -588,6 +590,8 @@ const char* CapabilityToString(SpvCapability capability) {
return "AtomicFloat64AddEXT";
case SpvCapabilityLongConstantCompositeINTEL:
return "LongConstantCompositeINTEL";
case SpvCapabilityOptNoneINTEL:
return "OptNoneINTEL";
case SpvCapabilityAtomicFloat16AddEXT:
return "AtomicFloat16AddEXT";
case SpvCapabilityDebugInfoModuleINTEL:

View File

@ -44,6 +44,7 @@ kSPV_INTEL_kernel_attributes,
kSPV_INTEL_long_constant_composite,
kSPV_INTEL_loop_fuse,
kSPV_INTEL_media_block_io,
kSPV_INTEL_optnone,
kSPV_INTEL_shader_integer_functions2,
kSPV_INTEL_subgroups,
kSPV_INTEL_unstructured_loop_controls,

View File

@ -156,6 +156,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_INTEL_kernel_attributes
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_long_constant_composite[] = {spvtools::Extension::kSPV_INTEL_long_constant_composite};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_loop_fuse[] = {spvtools::Extension::kSPV_INTEL_loop_fuse};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_media_block_io[] = {spvtools::Extension::kSPV_INTEL_media_block_io};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_optnone[] = {spvtools::Extension::kSPV_INTEL_optnone};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_shader_integer_functions2[] = {spvtools::Extension::kSPV_INTEL_shader_integer_functions2};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_subgroups[] = {spvtools::Extension::kSPV_INTEL_subgroups};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_unstructured_loop_controls[] = {spvtools::Extension::kSPV_INTEL_unstructured_loop_controls};
@ -270,7 +271,8 @@ static const spv_operand_desc_t pygen_variable_FunctionControlEntries[] = {
{"Inline", 0x0001, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
{"DontInline", 0x0002, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
{"Pure", 0x0004, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
{"Const", 0x0008, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}
{"Const", 0x0008, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
{"OptNoneINTEL", 0x10000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}
};
static const spv_operand_desc_t pygen_variable_MemorySemanticsEntries[] = {
@ -1118,6 +1120,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
{"AtomicFloat32AddEXT", 6033, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float_add, {}, 0xffffffffu, 0xffffffffu},
{"AtomicFloat64AddEXT", 6034, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float_add, {}, 0xffffffffu, 0xffffffffu},
{"LongConstantCompositeINTEL", 6089, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_long_constant_composite, {}, 0xffffffffu, 0xffffffffu},
{"OptNoneINTEL", 6094, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_optnone, {}, 0xffffffffu, 0xffffffffu},
{"AtomicFloat16AddEXT", 6095, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float16_add, {}, 0xffffffffu, 0xffffffffu},
{"DebugInfoModuleINTEL", 6114, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_debug_module, {}, 0xffffffffu, 0xffffffffu}
};

View File

@ -0,0 +1,48 @@
// Copyright (c) 2021 Google LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef INCLUDE_SPIRV_TOOLS_LINTER_HPP_
#define INCLUDE_SPIRV_TOOLS_LINTER_HPP_
#include "libspirv.hpp"
namespace spvtools {
// C++ interface for SPIR-V linting functionalities. It wraps the context
// (including target environment and the corresponding SPIR-V grammar) and
// provides a method for linting.
//
// Instances of this class provides basic thread-safety guarantee.
class Linter {
public:
explicit Linter(spv_target_env env);
~Linter();
// Sets the message consumer to the given |consumer|. The |consumer| will be
// invoked once for each message communicated from the library.
void SetMessageConsumer(MessageConsumer consumer);
// Returns a reference to the registered message consumer.
const MessageConsumer& consumer() const;
bool Run(const uint32_t* binary, size_t binary_size);
private:
struct Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace spvtools
#endif // INCLUDE_SPIRV_TOOLS_LINTER_HPP_

View File

@ -0,0 +1,51 @@
// Copyright (c) 2021 Google LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "spirv-tools/linter.hpp"
namespace spvtools {
struct Linter::Impl {
explicit Impl(spv_target_env env) : target_env(env) {
message_consumer = [](spv_message_level_t /*level*/, const char* /*source*/,
const spv_position_t& /*position*/,
const char* /*message*/) {};
}
spv_target_env target_env; // Target environment.
MessageConsumer message_consumer; // Message consumer.
};
Linter::Linter(spv_target_env env) : impl_(new Impl(env)) {}
Linter::~Linter() {}
void Linter::SetMessageConsumer(MessageConsumer consumer) {
impl_->message_consumer = consumer;
}
const MessageConsumer& Linter::consumer() const {
return impl_->message_consumer;
}
bool Linter::Run(const uint32_t* binary, size_t binary_size) {
(void)binary;
(void)binary_size;
consumer()(SPV_MSG_INFO, "", {0, 0, 0}, "Hello, world!");
return true;
}
} // namespace spvtools

View File

@ -578,6 +578,12 @@ std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
std::function<bool(unsigned)> spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
spv_ext_inst_type_t ext_type, uint32_t key) {
// The Vulkan debug info extended instruction set is non-semantic so allows no
// forward references ever.
if (ext_type == SPV_EXT_INST_TYPE_NONSEMANTIC_VULKAN_DEBUGINFO_100) {
return [](unsigned) { return false; };
}
// TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/532): Forward
// references for debug info instructions are still in discussion. We must
// update the following lines of code when we conclude the spec.

View File

@ -0,0 +1,156 @@
// Copyright (c) 2021 Google LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "source/opt/control_dependence.h"
#include <cassert>
#include <tuple>
#include <utility>
#include <vector>
#include "source/opt/basic_block.h"
#include "source/opt/cfg.h"
#include "source/opt/dominator_analysis.h"
#include "source/opt/function.h"
#include "source/opt/instruction.h"
#include "spirv/unified1/spirv.h"
// Computes the control dependence graph (CDG) using the algorithm in Cytron
// 1991, "Efficiently Computing Static Single Assignment Form and the Control
// Dependence Graph." It relies on the fact that the control dependence sources
// (blocks on which a block is control dependent) are exactly the post-dominance
// frontier for that block. The explanation and proofs are given in Section 6 of
// that paper.
// Link: https://www.cs.utexas.edu/~pingali/CS380C/2010/papers/ssaCytron.pdf
//
// The algorithm in Section 4.2 of the same paper is used to construct the
// dominance frontier. It uses the post-dominance tree, which is available in
// the IR context.
namespace spvtools {
namespace opt {
constexpr uint32_t ControlDependenceAnalysis::kPseudoEntryBlock;
uint32_t ControlDependence::GetConditionID(const CFG& cfg) const {
if (source_bb_id() == 0) {
// Entry dependence; return 0.
return 0;
}
const BasicBlock* source_bb = cfg.block(source_bb_id());
const Instruction* branch = source_bb->terminator();
assert((branch->opcode() == SpvOpBranchConditional ||
branch->opcode() == SpvOpSwitch) &&
"invalid control dependence; last instruction must be conditional "
"branch or switch");
return branch->GetSingleWordInOperand(0);
}
bool ControlDependence::operator<(const ControlDependence& other) const {
return std::tie(source_bb_id_, target_bb_id_, branch_target_bb_id_) <
std::tie(other.source_bb_id_, other.target_bb_id_,
other.branch_target_bb_id_);
}
bool ControlDependence::operator==(const ControlDependence& other) const {
return std::tie(source_bb_id_, target_bb_id_, branch_target_bb_id_) ==
std::tie(other.source_bb_id_, other.target_bb_id_,
other.branch_target_bb_id_);
}
std::ostream& operator<<(std::ostream& os, const ControlDependence& dep) {
os << dep.source_bb_id() << "->" << dep.target_bb_id();
if (dep.branch_target_bb_id() != dep.target_bb_id()) {
os << " through " << dep.branch_target_bb_id();
}
return os;
}
void ControlDependenceAnalysis::ComputePostDominanceFrontiers(
const CFG& cfg, const PostDominatorAnalysis& pdom) {
// Compute post-dominance frontiers (reverse graph).
// The dominance frontier for a block X is equal to (Equation 4)
// DF_local(X) U { B in DF_up(Z) | X = ipdom(Z) }
// (ipdom(Z) is the immediate post-dominator of Z.)
// where
// DF_local(X) = { Y | X -> Y in CFG, X does not strictly post-dominate Y }
// represents the contribution of X's predecessors to the DF, and
// DF_up(Z) = { Y | Y in DF(Z), ipdom(Z) does not strictly post-dominate Y }
// (note: ipdom(Z) = X.)
// represents the contribution of a block to its immediate post-
// dominator's DF.
// This is computed in one pass through a post-order traversal of the
// post-dominator tree.
// Assert that there is a block other than the pseudo exit in the pdom tree,
// as we need one to get the function entry point (as the pseudo exit is not
// actually part of the function.)
assert(!cfg.IsPseudoExitBlock(pdom.GetDomTree().post_begin()->bb_));
Function* function = pdom.GetDomTree().post_begin()->bb_->GetParent();
uint32_t function_entry = function->entry()->id();
// Explicitly initialize pseudo-entry block, as it doesn't depend on anything,
// so it won't be initialized in the following loop.
reverse_nodes_[kPseudoEntryBlock] = {};
for (auto it = pdom.GetDomTree().post_cbegin();
it != pdom.GetDomTree().post_cend(); ++it) {
ComputePostDominanceFrontierForNode(cfg, pdom, function_entry, *it);
}
}
void ControlDependenceAnalysis::ComputePostDominanceFrontierForNode(
const CFG& cfg, const PostDominatorAnalysis& pdom, uint32_t function_entry,
const DominatorTreeNode& pdom_node) {
const uint32_t label = pdom_node.id();
ControlDependenceList& edges = reverse_nodes_[label];
for (uint32_t pred : cfg.preds(label)) {
if (!pdom.StrictlyDominates(label, pred)) {
edges.push_back(ControlDependence(pred, label));
}
}
if (label == function_entry) {
// Add edge from pseudo-entry to entry.
// In CDG construction, an edge is added from entry to exit, so only the
// exit node can post-dominate entry.
edges.push_back(ControlDependence(kPseudoEntryBlock, label));
}
for (DominatorTreeNode* child : pdom_node) {
// Note: iterate dependences by value, as we need a copy.
for (const ControlDependence& dep : reverse_nodes_[child->id()]) {
// Special-case pseudo-entry, as above.
if (dep.source_bb_id() == kPseudoEntryBlock ||
!pdom.StrictlyDominates(label, dep.source_bb_id())) {
edges.push_back(ControlDependence(dep.source_bb_id(), label,
dep.branch_target_bb_id()));
}
}
}
}
void ControlDependenceAnalysis::ComputeControlDependenceGraph(
const CFG& cfg, const PostDominatorAnalysis& pdom) {
ComputePostDominanceFrontiers(cfg, pdom);
ComputeForwardGraphFromReverse();
}
void ControlDependenceAnalysis::ComputeForwardGraphFromReverse() {
for (const auto& entry : reverse_nodes_) {
// Ensure an entry is created for each node.
forward_nodes_[entry.first];
for (const ControlDependence& dep : entry.second) {
forward_nodes_[dep.source_bb_id()].push_back(dep);
}
}
}
} // namespace opt
} // namespace spvtools

View File

@ -0,0 +1,197 @@
// Copyright (c) 2021 Google LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SOURCE_OPT_CONTROL_DEPENDENCE_H_
#define SOURCE_OPT_CONTROL_DEPENDENCE_H_
#include <algorithm>
#include <cstdint>
#include <functional>
#include <ostream>
#include <unordered_map>
#include <vector>
#include "source/opt/cfg.h"
#include "source/opt/dominator_analysis.h"
namespace spvtools {
namespace opt {
class ControlDependence {
public:
// The label of the source of this dependence, i.e. the block on which the
// target is dependent on.
// A |source_bb_id| of 0 represents an "entry" dependence, meaning that the
// execution of |target_bb_id| is only dependent on entry to the function.
uint32_t source_bb_id() const { return source_bb_id_; }
// The label of the target of this dependence, i.e. the block which is
// dependent on the source.
uint32_t target_bb_id() const { return target_bb_id_; }
// The label of the target of the *branch* for this dependence.
// Equal to the ID of the entry block for entry dependences.
//
// For example, for the partial CFG pictured below:
// 1 ---> 2 ---> 4 ---> 6
// \ \ ^
// \-> 3 \-> 5 -----/
// Block 6 is control dependent on block 1, but this dependence comes from the
// branch 1 -> 2, so in this case the branch target ID would be 2.
uint32_t branch_target_bb_id() const { return branch_target_bb_id_; }
// Create a direct control dependence from BB ID |source| to |target|.
ControlDependence(uint32_t source, uint32_t target)
: source_bb_id_(source),
target_bb_id_(target),
branch_target_bb_id_(target) {}
// Create a control dependence from BB ID |source| to |target| through the
// branch from |source| to |branch_target|.
ControlDependence(uint32_t source, uint32_t target, uint32_t branch_target)
: source_bb_id_(source),
target_bb_id_(target),
branch_target_bb_id_(branch_target) {}
// Gets the ID of the conditional value for the branch corresponding to this
// control dependence. This is the first input operand for both
// OpConditionalBranch and OpSwitch.
// Returns 0 for entry dependences.
uint32_t GetConditionID(const CFG& cfg) const;
bool operator==(const ControlDependence& other) const;
bool operator!=(const ControlDependence& other) const {
return !(*this == other);
}
// Comparison operators, ordered lexicographically. Total ordering.
bool operator<(const ControlDependence& other) const;
bool operator>(const ControlDependence& other) const { return other < *this; }
bool operator<=(const ControlDependence& other) const {
return !(*this > other);
}
bool operator>=(const ControlDependence& other) const {
return !(*this < other);
}
private:
uint32_t source_bb_id_;
uint32_t target_bb_id_;
uint32_t branch_target_bb_id_;
};
// Prints |dep| to |os| in a human-readable way. For example,
// 1->2 (target_bb_id = branch_target_bb_id = 2)
// 3->4 through 5 (target_bb_id = 4, branch_target_bb_id = 5)
std::ostream& operator<<(std::ostream& os, const ControlDependence& dep);
// Represents the control dependence graph. A basic block is control dependent
// on another if the result of that block (e.g. the condition of a conditional
// branch) influences whether it is executed or not. More formally, a block A is
// control dependent on B iff:
// 1. there exists a path from A to the exit node that does *not* go through B
// (i.e., A does not postdominate B), and
// 2. there exists a path B -> b_1 -> ... -> b_n -> A such that A post-dominates
// all nodes b_i.
class ControlDependenceAnalysis {
public:
// Map basic block labels to control dependencies/dependents.
// Not guaranteed to be in any particular order.
using ControlDependenceList = std::vector<ControlDependence>;
using ControlDependenceListMap =
std::unordered_map<uint32_t, ControlDependenceList>;
// 0, the label number for the pseudo entry block.
// All control dependences on the pseudo entry block are of type kEntry, and
// vice versa.
static constexpr uint32_t kPseudoEntryBlock = 0;
// Build the control dependence graph for the given control flow graph |cfg|
// and corresponding post-dominator analysis |pdom|.
void ComputeControlDependenceGraph(const CFG& cfg,
const PostDominatorAnalysis& pdom);
// Get the list of the nodes that depend on a block.
// Return value is not guaranteed to be in any particular order.
const ControlDependenceList& GetDependenceTargets(uint32_t block) const {
return forward_nodes_.at(block);
}
// Get the list of the nodes on which a block depends on.
// Return value is not guaranteed to be in any particular order.
const ControlDependenceList& GetDependenceSources(uint32_t block) const {
return reverse_nodes_.at(block);
}
// Runs the function |f| on each block label in the CDG. If any iteration
// returns false, immediately stops iteration and returns false. Otherwise
// returns true. Nodes are iterated in some undefined order, including the
// pseudo-entry block.
bool WhileEachBlockLabel(std::function<bool(uint32_t)> f) const {
for (const auto& entry : forward_nodes_) {
if (!f(entry.first)) {
return false;
}
}
return true;
}
// Runs the function |f| on each block label in the CDG. Nodes are iterated in
// some undefined order, including the pseudo-entry block.
void ForEachBlockLabel(std::function<void(uint32_t)> f) const {
WhileEachBlockLabel([&f](uint32_t label) {
f(label);
return true;
});
}
// Returns true if the block |id| exists in the control dependence graph.
// This can be false even if the block exists in the function when it is part
// of an infinite loop, since it is not part of the post-dominator tree.
bool HasBlock(uint32_t id) const { return forward_nodes_.count(id) > 0; }
// Returns true if block |a| is dependent on block |b|.
bool IsDependent(uint32_t a, uint32_t b) const {
if (!HasBlock(a)) return false;
// BBs tend to have more dependents (targets) than they are dependent on
// (sources), so search sources.
const ControlDependenceList& a_sources = GetDependenceSources(a);
return std::find_if(a_sources.begin(), a_sources.end(),
[b](const ControlDependence& dep) {
return dep.source_bb_id() == b;
}) != a_sources.end();
}
private:
// Computes the post-dominance frontiers (i.e. the reverse CDG) for each node
// in the post-dominator tree. Only modifies reverse_nodes_; forward_nodes_ is
// not modified.
void ComputePostDominanceFrontiers(const CFG& cfg,
const PostDominatorAnalysis& pdom);
// Computes the post-dominance frontier for a specific node |pdom_node| in the
// post-dominator tree. Result is placed in reverse_nodes_[pdom_node.id()].
void ComputePostDominanceFrontierForNode(const CFG& cfg,
const PostDominatorAnalysis& pdom,
uint32_t function_entry,
const DominatorTreeNode& pdom_node);
// Computes the forward graph (forward_nodes_) from the reverse graph
// (reverse_nodes_).
void ComputeForwardGraphFromReverse();
ControlDependenceListMap forward_nodes_;
ControlDependenceListMap reverse_nodes_;
};
} // namespace opt
} // namespace spvtools
#endif // SOURCE_OPT_CONTROL_DEPENDENCE_H_

View File

@ -403,6 +403,14 @@ bool InlinePass::InlineEntryBlock(
callee2caller, inlined_at_ctx, new_blk_ptr, callee_first_block);
while (callee_inst_itr != callee_first_block->end()) {
// Don't inline function definition links, the calling function is not a
// definition.
if (callee_inst_itr->GetVulkan100DebugOpcode() ==
NonSemanticVulkanDebugInfo100DebugFunctionDefinition) {
++callee_inst_itr;
continue;
}
if (!InlineSingleInstruction(
callee2caller, new_blk_ptr->get(), &*callee_inst_itr,
context()->get_debug_info_mgr()->BuildDebugInlinedAtChain(

View File

@ -17,6 +17,7 @@
#include <utility>
#include "DebugInfo.h"
#include "NonSemanticVulkanDebugInfo100.h"
#include "OpenCLDebugInfo100.h"
#include "source/ext_inst.h"
#include "source/opt/log.h"
@ -232,6 +233,35 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
block_->AddInstruction(std::move(spv_inst));
break;
}
default: {
Errorf(consumer_, src, loc,
"Debug info extension instruction other than DebugScope, "
"DebugNoScope, DebugFunctionDefinition, DebugDeclare, and "
"DebugValue found inside function",
opcode);
return false;
}
}
} else if (inst->ext_inst_type ==
SPV_EXT_INST_TYPE_NONSEMANTIC_VULKAN_DEBUGINFO_100) {
const NonSemanticVulkanDebugInfo100Instructions ext_inst_key =
NonSemanticVulkanDebugInfo100Instructions(ext_inst_index);
switch (ext_inst_key) {
case NonSemanticVulkanDebugInfo100DebugDeclare:
case NonSemanticVulkanDebugInfo100DebugValue:
case NonSemanticVulkanDebugInfo100DebugScope:
case NonSemanticVulkanDebugInfo100DebugNoScope:
case NonSemanticVulkanDebugInfo100DebugFunctionDefinition: {
if (block_ == nullptr) { // Inside function but outside blocks
Errorf(consumer_, src, loc,
"Debug info extension instruction found inside function "
"but outside block",
opcode);
} else {
block_->AddInstruction(std::move(spv_inst));
}
break;
}
default: {
Errorf(consumer_, src, loc,
"Debug info extension instruction other than DebugScope, "

View File

@ -145,8 +145,10 @@ void Module::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
DebugScope last_scope(kNoDebugScope, kNoInlinedAt);
const Instruction* last_line_inst = nullptr;
bool between_merge_and_branch = false;
bool between_label_and_phi_var = false;
auto write_inst = [binary, skip_nop, &last_scope, &last_line_inst,
&between_merge_and_branch, this](const Instruction* i) {
&between_merge_and_branch, &between_label_and_phi_var,
this](const Instruction* i) {
// Skip emitting line instructions between merge and branch instructions.
auto opcode = i->opcode();
if (between_merge_and_branch &&
@ -175,13 +177,29 @@ void Module::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
last_line_inst = nullptr;
}
}
if (opcode == SpvOpLabel) {
between_label_and_phi_var = true;
} else if (opcode != SpvOpVariable && opcode != SpvOpPhi &&
opcode != SpvOpLine && opcode != SpvOpNoLine) {
between_label_and_phi_var = false;
}
if (!(skip_nop && i->IsNop())) {
const auto& scope = i->GetDebugScope();
if (scope != last_scope) {
// Emit DebugScope |scope| to |binary|.
auto dbg_inst = ext_inst_debuginfo_.begin();
scope.ToBinary(dbg_inst->type_id(), context()->TakeNextId(),
dbg_inst->GetSingleWordOperand(2), binary);
// Can only emit nonsemantic instructions after all phi instructions
// in a block so don't emit scope instructions before phi instructions
// for Vulkan.NonSemantic.DebugInfo.100.
if (!between_label_and_phi_var ||
context()
->get_feature_mgr()
->GetExtInstImportId_OpenCL100DebugInfo()) {
// Emit DebugScope |scope| to |binary|.
auto dbg_inst = ext_inst_debuginfo_.begin();
scope.ToBinary(dbg_inst->type_id(), context()->TakeNextId(),
dbg_inst->GetSingleWordOperand(2), binary);
}
last_scope = scope;
}

View File

@ -549,17 +549,23 @@ spv_result_t checkLayout(uint32_t struct_id, const char* storage_class_str,
// limitation to this check if the array size is a spec constant or is a
// runtime array then we will only check a single element. This means
// some improper straddles might be missed.
for (uint32_t i = 0; i < num_elements; ++i) {
uint32_t next_offset = i * array_stride + offset;
if (SpvOpTypeStruct == element_inst->opcode() &&
SPV_SUCCESS != (recursive_status = checkLayout(
typeId, storage_class_str, decoration_str,
blockRules, scalar_block_layout,
next_offset, constraints, vstate)))
return recursive_status;
// If offsets accumulate up to a 16-byte multiple stop checking since
// it will just repeat.
if (i > 0 && (next_offset % 16 == 0)) break;
if (SpvOpTypeStruct == element_inst->opcode()) {
std::vector<bool> seen(16, false);
for (uint32_t i = 0; i < num_elements; ++i) {
uint32_t next_offset = i * array_stride + offset;
// Stop checking if offsets repeat in terms of 16-byte multiples.
if (seen[next_offset % 16]) {
break;
}
if (SPV_SUCCESS !=
(recursive_status = checkLayout(
typeId, storage_class_str, decoration_str, blockRules,
scalar_block_layout, next_offset, constraints, vstate)))
return recursive_status;
seen[next_offset % 16] = true;
}
}
// Proceed to the element in case it is an array.

View File

@ -812,7 +812,7 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
for (uint32_t operand_index = 4; operand_index < num_operands;
++operand_index) {
const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
if (!_.IsIntScalarOrVectorType(operand_type)) {
if (!operand_type || !_.IsIntScalarOrVectorType(operand_type)) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< ext_inst_name() << ": "
<< "expected all operands to be int scalars or vectors";