Browse Source

Updated spirv-tools.

Бранимир Караџић 5 years ago
parent
commit
6f49e86e7a
26 changed files with 652 additions and 95 deletions
  1. 38 2
      3rdparty/spirv-tools/CHANGES
  2. 1 1
      3rdparty/spirv-tools/include/generated/build-version.inc
  3. 14 0
      3rdparty/spirv-tools/include/generated/core.insts-unified1.inc
  4. 14 1
      3rdparty/spirv-tools/include/generated/enum_string_mapping.inc
  5. 7 0
      3rdparty/spirv-tools/include/generated/extension_enum.inc
  6. 52 5
      3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc
  7. 4 0
      3rdparty/spirv-tools/source/fuzz/CMakeLists.txt
  8. 4 0
      3rdparty/spirv-tools/source/fuzz/fuzzer.cpp
  9. 3 0
      3rdparty/spirv-tools/source/fuzz/fuzzer_context.cpp
  10. 4 0
      3rdparty/spirv-tools/source/fuzz/fuzzer_context.h
  11. 36 35
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass.cpp
  12. 28 24
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass.h
  13. 2 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.cpp
  14. 5 5
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.cpp
  15. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.cpp
  16. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.cpp
  17. 12 13
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp
  18. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
  19. 109 0
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
  20. 41 0
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_push_ids_through_variables.h
  21. 25 0
      3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto
  22. 4 0
      3rdparty/spirv-tools/source/fuzz/transformation.cpp
  23. 159 0
      3rdparty/spirv-tools/source/fuzz/transformation_push_id_through_variable.cpp
  24. 64 0
      3rdparty/spirv-tools/source/fuzz/transformation_push_id_through_variable.h
  25. 8 1
      3rdparty/spirv-tools/source/val/validate_extensions.cpp
  26. 15 3
      3rdparty/spirv-tools/source/val/validate_image.cpp

+ 38 - 2
3rdparty/spirv-tools/CHANGES

@@ -1,7 +1,43 @@
 Revision history for SPIRV-Tools
 
-v2020.3-dev 2020-03-26
- - Start v2020.3-dev
+v2020.4-dev 2020-05-27
+ - Start v2020.4-dev
+
+v2020.3 2020-05-27
+ - General
+   - Prevent Effcee install his things when build spirv-tools with testing enabled (#3256)
+   - Update acorn version (#3294)
+   - If SPIRV-Headers is in our tree, include it as subproject (#3299)
+   - allow cross compiling for Windows Store, UWP, etc. (#3330)
+ - Optimizer
+   - Remove deprecated interfaces from instrument passes (#3361)
+   - Preserve debug info in inline pass (#3349)
+   - Handle more cases in dead member elim (#3289)
+   - Preserve debug info in eliminate-dead-functions (#3251)
+   - Fix Struct CFG analysis for single block loop (#3293)
+   - Add tests for recently added command line option (#3297)
+   - Consider sampled images as read-only storage (#3295)
+   - Allow various validation options to be passed to spirv-opt (#3314)
+   - Add debug information analysis (#3305)
+   - Preserve debug info for wrap-opkill (#3331)
+   - refactor inlining pass (#3328)
+   - Add unrolling to performance passes (#3082)
+ - Validator
+   - Add validation support for ImageGatherBiasLodAMD (#3363)
+   - Validate ShaderCallKHR memory scope (#3332)
+   - Validate Buffer and BufferBlock apply only to struct types (#3259)
+ - Reduce
+   - increase default step limit (#3327)
+   - Remove unused uniforms and similar (#3321)
+ - Fuzz
+   - Add support for StorageBuffer (#3348)
+   - Add validator options (#3254)
+   - Limit adding of new variables to 'basic' types (#3257)
+   - Transformation to add OpConstantNull (#3273)
+   - Handling of more fuzzing opportunities (#3277, #3280, #3281, #3290, #3292)
+   - Respect rules for OpSampledImage (#3287)
+   - Do not outline regions that produce pointer outputs (#3291)
+ - Linker
 
 v2020.2 2020-03-26
  - General:

+ 1 - 1
3rdparty/spirv-tools/include/generated/build-version.inc

@@ -1 +1 @@
-"v2020.3-dev", "SPIRV-Tools v2020.3-dev 2a43c86c2428dd427bb5c8dc62e57774d87952a8"
+"v2020.4-dev", "SPIRV-Tools v2020.4-dev 3e4a8382b6d054cbd8f0a04a4f83c4350dd803ea"

+ 14 - 0
3rdparty/spirv-tools/include/generated/core.insts-unified1.inc

@@ -2,12 +2,15 @@ static const SpvCapability pygen_variable_caps_Addresses[] = {SpvCapabilityAddre
 static const SpvCapability pygen_variable_caps_AddressesPhysicalStorageBufferAddresses[] = {SpvCapabilityAddresses, SpvCapabilityPhysicalStorageBufferAddresses};
 static const SpvCapability pygen_variable_caps_AddressesVariablePointersVariablePointersStorageBuffer[] = {SpvCapabilityAddresses, SpvCapabilityVariablePointers, SpvCapabilityVariablePointersStorageBuffer};
 static const SpvCapability pygen_variable_caps_AddressesVariablePointersVariablePointersStorageBufferPhysicalStorageBufferAddresses[] = {SpvCapabilityAddresses, SpvCapabilityVariablePointers, SpvCapabilityVariablePointersStorageBuffer, SpvCapabilityPhysicalStorageBufferAddresses};
+static const SpvCapability pygen_variable_caps_BlockingPipesINTEL[] = {SpvCapabilityBlockingPipesINTEL};
 static const SpvCapability pygen_variable_caps_CooperativeMatrixNV[] = {SpvCapabilityCooperativeMatrixNV};
 static const SpvCapability pygen_variable_caps_DemoteToHelperInvocationEXT[] = {SpvCapabilityDemoteToHelperInvocationEXT};
 static const SpvCapability pygen_variable_caps_DerivativeControl[] = {SpvCapabilityDerivativeControl};
 static const SpvCapability pygen_variable_caps_DeviceEnqueue[] = {SpvCapabilityDeviceEnqueue};
+static const SpvCapability pygen_variable_caps_FPGARegINTEL[] = {SpvCapabilityFPGARegINTEL};
 static const SpvCapability pygen_variable_caps_FragmentMaskAMD[] = {SpvCapabilityFragmentMaskAMD};
 static const SpvCapability pygen_variable_caps_FragmentShaderSampleInterlockEXTFragmentShaderPixelInterlockEXTFragmentShaderShadingRateInterlockEXT[] = {SpvCapabilityFragmentShaderSampleInterlockEXT, SpvCapabilityFragmentShaderPixelInterlockEXT, SpvCapabilityFragmentShaderShadingRateInterlockEXT};
+static const SpvCapability pygen_variable_caps_FunctionPointersINTEL[] = {SpvCapabilityFunctionPointersINTEL};
 static const SpvCapability pygen_variable_caps_Geometry[] = {SpvCapabilityGeometry};
 static const SpvCapability pygen_variable_caps_GeometryStreams[] = {SpvCapabilityGeometryStreams};
 static const SpvCapability pygen_variable_caps_GroupNonUniform[] = {SpvCapabilityGroupNonUniform};
@@ -46,6 +49,7 @@ static const SpvCapability pygen_variable_caps_SubgroupImageBlockIOINTEL[] = {Sp
 static const SpvCapability pygen_variable_caps_SubgroupImageMediaBlockIOINTEL[] = {SpvCapabilitySubgroupImageMediaBlockIOINTEL};
 static const SpvCapability pygen_variable_caps_SubgroupShuffleINTEL[] = {SpvCapabilitySubgroupShuffleINTEL};
 static const SpvCapability pygen_variable_caps_SubgroupVoteKHR[] = {SpvCapabilitySubgroupVoteKHR};
+static const SpvCapability pygen_variable_caps_UnstructuredLoopControlsINTEL[] = {SpvCapabilityUnstructuredLoopControlsINTEL};
 
 static const spvtools::Extension pygen_variable_exts_SPV_AMD_shader_ballot[] = {spvtools::Extension::kSPV_AMD_shader_ballot};
 static const spvtools::Extension pygen_variable_exts_SPV_AMD_shader_fragment_mask[] = {spvtools::Extension::kSPV_AMD_shader_fragment_mask};
@@ -53,6 +57,10 @@ static const spvtools::Extension pygen_variable_exts_SPV_EXT_demote_to_helper_in
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_shader_interlock[] = {spvtools::Extension::kSPV_EXT_fragment_shader_interlock};
 static const spvtools::Extension pygen_variable_exts_SPV_GOOGLE_decorate_stringSPV_GOOGLE_hlsl_functionality1[] = {spvtools::Extension::kSPV_GOOGLE_decorate_string, spvtools::Extension::kSPV_GOOGLE_hlsl_functionality1};
 static const spvtools::Extension pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1[] = {spvtools::Extension::kSPV_GOOGLE_hlsl_functionality1};
+static const spvtools::Extension pygen_variable_exts_SPV_INTEL_blocking_pipes[] = {spvtools::Extension::kSPV_INTEL_blocking_pipes};
+static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_reg[] = {spvtools::Extension::kSPV_INTEL_fpga_reg};
+static const spvtools::Extension pygen_variable_exts_SPV_INTEL_function_pointers[] = {spvtools::Extension::kSPV_INTEL_function_pointers};
+static const spvtools::Extension pygen_variable_exts_SPV_INTEL_unstructured_loop_controls[] = {spvtools::Extension::kSPV_INTEL_unstructured_loop_controls};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_query[] = {spvtools::Extension::kSPV_KHR_ray_query};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {spvtools::Extension::kSPV_KHR_shader_ballot};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_clock[] = {spvtools::Extension::kSPV_KHR_shader_clock};
@@ -481,6 +489,8 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"USubSatINTEL", SpvOpUSubSatINTEL, 1, pygen_variable_caps_IntegerFunctions2INTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"IMul32x16INTEL", SpvOpIMul32x16INTEL, 1, pygen_variable_caps_IntegerFunctions2INTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"UMul32x16INTEL", SpvOpUMul32x16INTEL, 1, pygen_variable_caps_IntegerFunctions2INTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"FunctionPointerINTEL", SpvOpFunctionPointerINTEL, 1, pygen_variable_caps_FunctionPointersINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_INTEL_function_pointers, 0xffffffffu, 0xffffffffu},
+  {"FunctionPointerCallINTEL", SpvOpFunctionPointerCallINTEL, 1, pygen_variable_caps_FunctionPointersINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 1, pygen_variable_exts_SPV_INTEL_function_pointers, 0xffffffffu, 0xffffffffu},
   {"DecorateString", SpvOpDecorateString, 0, nullptr, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DECORATION}, 0, 0, 2, pygen_variable_exts_SPV_GOOGLE_decorate_stringSPV_GOOGLE_hlsl_functionality1, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
   {"DecorateStringGOOGLE", SpvOpDecorateStringGOOGLE, 0, nullptr, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DECORATION}, 0, 0, 2, pygen_variable_exts_SPV_GOOGLE_decorate_stringSPV_GOOGLE_hlsl_functionality1, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
   {"MemberDecorateString", SpvOpMemberDecorateString, 0, nullptr, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_DECORATION}, 0, 0, 2, pygen_variable_exts_SPV_GOOGLE_decorate_stringSPV_GOOGLE_hlsl_functionality1, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
@@ -603,6 +613,10 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"SubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL", SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL, 2, pygen_variable_caps_SubgroupAvcMotionEstimationINTELSubgroupAvcMotionEstimationIntraINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"SubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL", SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL, 2, pygen_variable_caps_SubgroupAvcMotionEstimationINTELSubgroupAvcMotionEstimationIntraINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"SubgroupAvcSicGetInterRawSadsINTEL", SpvOpSubgroupAvcSicGetInterRawSadsINTEL, 1, pygen_variable_caps_SubgroupAvcMotionEstimationINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"LoopControlINTEL", SpvOpLoopControlINTEL, 1, pygen_variable_caps_UnstructuredLoopControlsINTEL, 1, {SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER}, 0, 0, 1, pygen_variable_exts_SPV_INTEL_unstructured_loop_controls, 0xffffffffu, 0xffffffffu},
+  {"ReadPipeBlockingINTEL", SpvOpReadPipeBlockingINTEL, 1, pygen_variable_caps_BlockingPipesINTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_INTEL_blocking_pipes, 0xffffffffu, 0xffffffffu},
+  {"WritePipeBlockingINTEL", SpvOpWritePipeBlockingINTEL, 1, pygen_variable_caps_BlockingPipesINTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_INTEL_blocking_pipes, 0xffffffffu, 0xffffffffu},
+  {"FPGARegINTEL", SpvOpFPGARegINTEL, 1, pygen_variable_caps_FPGARegINTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_INTEL_fpga_reg, 0xffffffffu, 0xffffffffu},
   {"RayQueryGetRayTMinKHR", SpvOpRayQueryGetRayTMinKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},
   {"RayQueryGetRayFlagsKHR", SpvOpRayQueryGetRayFlagsKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},
   {"RayQueryGetIntersectionTKHR", SpvOpRayQueryGetIntersectionTKHR, 1, pygen_variable_caps_RayQueryProvisionalKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},

File diff suppressed because it is too large
+ 14 - 1
3rdparty/spirv-tools/include/generated/enum_string_mapping.inc


+ 7 - 0
3rdparty/spirv-tools/include/generated/extension_enum.inc

@@ -19,10 +19,17 @@ kSPV_EXT_shader_viewport_index_layer,
 kSPV_GOOGLE_decorate_string,
 kSPV_GOOGLE_hlsl_functionality1,
 kSPV_GOOGLE_user_type,
+kSPV_INTEL_blocking_pipes,
 kSPV_INTEL_device_side_avc_motion_estimation,
+kSPV_INTEL_fpga_loop_controls,
+kSPV_INTEL_fpga_memory_attributes,
+kSPV_INTEL_fpga_reg,
+kSPV_INTEL_function_pointers,
+kSPV_INTEL_kernel_attributes,
 kSPV_INTEL_media_block_io,
 kSPV_INTEL_shader_integer_functions2,
 kSPV_INTEL_subgroups,
+kSPV_INTEL_unstructured_loop_controls,
 kSPV_KHR_16bit_storage,
 kSPV_KHR_8bit_storage,
 kSPV_KHR_device_group,

+ 52 - 5
3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc

@@ -10,12 +10,16 @@ static const SpvCapability pygen_variable_caps_DeviceEnqueue[] = {SpvCapabilityD
 static const SpvCapability pygen_variable_caps_DeviceGroup[] = {SpvCapabilityDeviceGroup};
 static const SpvCapability pygen_variable_caps_DrawParameters[] = {SpvCapabilityDrawParameters};
 static const SpvCapability pygen_variable_caps_DrawParametersMeshShadingNV[] = {SpvCapabilityDrawParameters, SpvCapabilityMeshShadingNV};
+static const SpvCapability pygen_variable_caps_FPGAKernelAttributesINTEL[] = {SpvCapabilityFPGAKernelAttributesINTEL};
+static const SpvCapability pygen_variable_caps_FPGALoopControlsINTEL[] = {SpvCapabilityFPGALoopControlsINTEL};
+static const SpvCapability pygen_variable_caps_FPGAMemoryAttributesINTEL[] = {SpvCapabilityFPGAMemoryAttributesINTEL};
 static const SpvCapability pygen_variable_caps_FragmentBarycentricNV[] = {SpvCapabilityFragmentBarycentricNV};
 static const SpvCapability pygen_variable_caps_FragmentDensityEXTShadingRateNV[] = {SpvCapabilityFragmentDensityEXT, SpvCapabilityShadingRateNV};
 static const SpvCapability pygen_variable_caps_FragmentFullyCoveredEXT[] = {SpvCapabilityFragmentFullyCoveredEXT};
 static const SpvCapability pygen_variable_caps_FragmentShaderPixelInterlockEXT[] = {SpvCapabilityFragmentShaderPixelInterlockEXT};
 static const SpvCapability pygen_variable_caps_FragmentShaderSampleInterlockEXT[] = {SpvCapabilityFragmentShaderSampleInterlockEXT};
 static const SpvCapability pygen_variable_caps_FragmentShaderShadingRateInterlockEXT[] = {SpvCapabilityFragmentShaderShadingRateInterlockEXT};
+static const SpvCapability pygen_variable_caps_FunctionPointersINTEL[] = {SpvCapabilityFunctionPointersINTEL};
 static const SpvCapability pygen_variable_caps_GenericPointer[] = {SpvCapabilityGenericPointer};
 static const SpvCapability pygen_variable_caps_Geometry[] = {SpvCapabilityGeometry};
 static const SpvCapability pygen_variable_caps_GeometryMeshShadingNV[] = {SpvCapabilityGeometry, SpvCapabilityMeshShadingNV};
@@ -32,6 +36,7 @@ static const SpvCapability pygen_variable_caps_ImageBasic[] = {SpvCapabilityImag
 static const SpvCapability pygen_variable_caps_ImageBuffer[] = {SpvCapabilityImageBuffer};
 static const SpvCapability pygen_variable_caps_ImageBufferShaderNonUniform[] = {SpvCapabilityImageBuffer, SpvCapabilityShaderNonUniform};
 static const SpvCapability pygen_variable_caps_ImageGatherExtended[] = {SpvCapabilityImageGatherExtended};
+static const SpvCapability pygen_variable_caps_IndirectReferencesINTEL[] = {SpvCapabilityIndirectReferencesINTEL};
 static const SpvCapability pygen_variable_caps_InputAttachment[] = {SpvCapabilityInputAttachment};
 static const SpvCapability pygen_variable_caps_InputAttachmentShaderNonUniform[] = {SpvCapabilityInputAttachment, SpvCapabilityShaderNonUniform};
 static const SpvCapability pygen_variable_caps_Int64[] = {SpvCapabilityInt64};
@@ -39,6 +44,7 @@ static const SpvCapability pygen_variable_caps_Kernel[] = {SpvCapabilityKernel};
 static const SpvCapability pygen_variable_caps_KernelGroupNonUniform[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniform};
 static const SpvCapability pygen_variable_caps_KernelGroupNonUniformSubgroupBallotKHR[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniform, SpvCapabilitySubgroupBallotKHR};
 static const SpvCapability pygen_variable_caps_KernelGroupNonUniformArithmeticGroupNonUniformBallot[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniformArithmetic, SpvCapabilityGroupNonUniformBallot};
+static const SpvCapability pygen_variable_caps_KernelAttributesINTEL[] = {SpvCapabilityKernelAttributesINTEL};
 static const SpvCapability pygen_variable_caps_Linkage[] = {SpvCapabilityLinkage};
 static const SpvCapability pygen_variable_caps_Matrix[] = {SpvCapabilityMatrix};
 static const SpvCapability pygen_variable_caps_MeshShadingNV[] = {SpvCapabilityMeshShadingNV};
@@ -106,10 +112,17 @@ static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_stencil_expo
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_viewport_index_layerSPV_NV_viewport_array2[] = {spvtools::Extension::kSPV_EXT_shader_viewport_index_layer, spvtools::Extension::kSPV_NV_viewport_array2};
 static const spvtools::Extension pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1[] = {spvtools::Extension::kSPV_GOOGLE_hlsl_functionality1};
 static const spvtools::Extension pygen_variable_exts_SPV_GOOGLE_user_type[] = {spvtools::Extension::kSPV_GOOGLE_user_type};
+static const spvtools::Extension pygen_variable_exts_SPV_INTEL_blocking_pipes[] = {spvtools::Extension::kSPV_INTEL_blocking_pipes};
 static const spvtools::Extension pygen_variable_exts_SPV_INTEL_device_side_avc_motion_estimation[] = {spvtools::Extension::kSPV_INTEL_device_side_avc_motion_estimation};
+static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_loop_controls[] = {spvtools::Extension::kSPV_INTEL_fpga_loop_controls};
+static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_memory_attributes[] = {spvtools::Extension::kSPV_INTEL_fpga_memory_attributes};
+static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_reg[] = {spvtools::Extension::kSPV_INTEL_fpga_reg};
+static const spvtools::Extension pygen_variable_exts_SPV_INTEL_function_pointers[] = {spvtools::Extension::kSPV_INTEL_function_pointers};
+static const spvtools::Extension pygen_variable_exts_SPV_INTEL_kernel_attributes[] = {spvtools::Extension::kSPV_INTEL_kernel_attributes};
 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_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};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_16bit_storage[] = {spvtools::Extension::kSPV_KHR_16bit_storage};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_8bit_storage[] = {spvtools::Extension::kSPV_KHR_8bit_storage};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_device_group[] = {spvtools::Extension::kSPV_KHR_device_group};
@@ -193,7 +206,14 @@ static const spv_operand_desc_t pygen_variable_LoopControlEntries[] = {
   {"MaxIterations", 0x0020, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
   {"IterationMultiple", 0x0040, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
   {"PeelCount", 0x0080, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
-  {"PartialCount", 0x0100, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu}
+  {"PartialCount", 0x0100, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
+  {"InitiationIntervalINTEL", 0x10000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"MaxConcurrencyINTEL", 0x20000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"DependencyArrayINTEL", 0x40000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"PipelineEnableINTEL", 0x80000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"LoopCoalesceINTEL", 0x100000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"MaxInterleavingINTEL", 0x200000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"SpeculatedIterationsINTEL", 0x400000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}
 };
 
 static const spv_operand_desc_t pygen_variable_FunctionControlEntries[] = {
@@ -363,7 +383,11 @@ static const spv_operand_desc_t pygen_variable_ExecutionModeEntries[] = {
   {"SampleInterlockOrderedEXT", 5368, 1, pygen_variable_caps_FragmentShaderSampleInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu},
   {"SampleInterlockUnorderedEXT", 5369, 1, pygen_variable_caps_FragmentShaderSampleInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu},
   {"ShadingRateInterlockOrderedEXT", 5370, 1, pygen_variable_caps_FragmentShaderShadingRateInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu},
-  {"ShadingRateInterlockUnorderedEXT", 5371, 1, pygen_variable_caps_FragmentShaderShadingRateInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu}
+  {"ShadingRateInterlockUnorderedEXT", 5371, 1, pygen_variable_caps_FragmentShaderShadingRateInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu},
+  {"MaxWorkgroupSizeINTEL", 5893, 1, pygen_variable_caps_KernelAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"MaxWorkDimINTEL", 5894, 1, pygen_variable_caps_KernelAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"NoGlobalOffsetINTEL", 5895, 1, pygen_variable_caps_KernelAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {}, 0xffffffffu, 0xffffffffu},
+  {"NumSIMDWorkitemsINTEL", 5896, 1, pygen_variable_caps_FPGAKernelAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}
 };
 
 static const spv_operand_desc_t pygen_variable_StorageClassEntries[] = {
@@ -393,7 +417,8 @@ static const spv_operand_desc_t pygen_variable_StorageClassEntries[] = {
   {"ShaderRecordBufferNV", 5343, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
   {"ShaderRecordBufferKHR", 5343, 2, pygen_variable_caps_RayTracingNVRayTracingProvisionalKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
   {"PhysicalStorageBuffer", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
-  {"PhysicalStorageBufferEXT", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}
+  {"PhysicalStorageBufferEXT", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
+  {"CodeSectionINTEL", 5605, 1, pygen_variable_caps_FunctionPointersINTEL, 1, pygen_variable_exts_SPV_INTEL_function_pointers, {}, 0xffffffffu, 0xffffffffu}
 };
 
 static const spv_operand_desc_t pygen_variable_DimEntries[] = {
@@ -599,11 +624,24 @@ static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
   {"RestrictPointerEXT", 5355, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"AliasedPointer", 5356, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"AliasedPointerEXT", 5356, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
+  {"ReferencedIndirectlyINTEL", 5602, 1, pygen_variable_caps_IndirectReferencesINTEL, 1, pygen_variable_exts_SPV_INTEL_function_pointers, {}, 0xffffffffu, 0xffffffffu},
   {"CounterBuffer", 5634, 0, nullptr, 1, pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
   {"HlslCounterBufferGOOGLE", 5634, 0, nullptr, 1, pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1, {SPV_OPERAND_TYPE_ID}, 0xffffffffu, 0xffffffffu},
   {"UserSemantic", 5635, 0, nullptr, 1, pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1, {SPV_OPERAND_TYPE_LITERAL_STRING}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
   {"HlslSemanticGOOGLE", 5635, 0, nullptr, 1, pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1, {SPV_OPERAND_TYPE_LITERAL_STRING}, 0xffffffffu, 0xffffffffu},
-  {"UserTypeGOOGLE", 5636, 0, nullptr, 1, pygen_variable_exts_SPV_GOOGLE_user_type, {SPV_OPERAND_TYPE_LITERAL_STRING}, 0xffffffffu, 0xffffffffu}
+  {"UserTypeGOOGLE", 5636, 0, nullptr, 1, pygen_variable_exts_SPV_GOOGLE_user_type, {SPV_OPERAND_TYPE_LITERAL_STRING}, 0xffffffffu, 0xffffffffu},
+  {"RegisterINTEL", 5825, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {}, 0xffffffffu, 0xffffffffu},
+  {"MemoryINTEL", 5826, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {SPV_OPERAND_TYPE_LITERAL_STRING}, 0xffffffffu, 0xffffffffu},
+  {"NumbanksINTEL", 5827, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"BankwidthINTEL", 5828, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"MaxPrivateCopiesINTEL", 5829, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"SinglepumpINTEL", 5830, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {}, 0xffffffffu, 0xffffffffu},
+  {"DoublepumpINTEL", 5831, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {}, 0xffffffffu, 0xffffffffu},
+  {"MaxReplicatesINTEL", 5832, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"SimpleDualPortINTEL", 5833, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {}, 0xffffffffu, 0xffffffffu},
+  {"MergeINTEL", 5834, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_LITERAL_STRING}, 0xffffffffu, 0xffffffffu},
+  {"BankBitsINTEL", 5835, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"ForcePow2DepthINTEL", 5836, 1, pygen_variable_caps_FPGAMemoryAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}
 };
 
 static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = {
@@ -913,9 +951,18 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
   {"SubgroupImageBlockIOINTEL", 5570, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupImageMediaBlockIOINTEL", 5579, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_media_block_io, {}, 0xffffffffu, 0xffffffffu},
   {"IntegerFunctions2INTEL", 5584, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_INTEL_shader_integer_functions2, {}, 0xffffffffu, 0xffffffffu},
+  {"FunctionPointersINTEL", 5603, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_function_pointers, {}, 0xffffffffu, 0xffffffffu},
+  {"IndirectReferencesINTEL", 5604, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_function_pointers, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupAvcMotionEstimationINTEL", 5696, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_device_side_avc_motion_estimation, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupAvcMotionEstimationIntraINTEL", 5697, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_device_side_avc_motion_estimation, {}, 0xffffffffu, 0xffffffffu},
-  {"SubgroupAvcMotionEstimationChromaINTEL", 5698, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_device_side_avc_motion_estimation, {}, 0xffffffffu, 0xffffffffu}
+  {"SubgroupAvcMotionEstimationChromaINTEL", 5698, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_device_side_avc_motion_estimation, {}, 0xffffffffu, 0xffffffffu},
+  {"FPGAMemoryAttributesINTEL", 5824, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_attributes, {}, 0xffffffffu, 0xffffffffu},
+  {"UnstructuredLoopControlsINTEL", 5886, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_unstructured_loop_controls, {}, 0xffffffffu, 0xffffffffu},
+  {"FPGALoopControlsINTEL", 5888, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {}, 0xffffffffu, 0xffffffffu},
+  {"KernelAttributesINTEL", 5892, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {}, 0xffffffffu, 0xffffffffu},
+  {"FPGAKernelAttributesINTEL", 5897, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {}, 0xffffffffu, 0xffffffffu},
+  {"BlockingPipesINTEL", 5945, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_blocking_pipes, {}, 0xffffffffu, 0xffffffffu},
+  {"FPGARegINTEL", 5948, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_reg, {}, 0xffffffffu, 0xffffffffu}
 };
 
 static const spv_operand_desc_t pygen_variable_RayQueryIntersectionEntries[] = {

+ 4 - 0
3rdparty/spirv-tools/source/fuzz/CMakeLists.txt

@@ -63,6 +63,7 @@ if(SPIRV_BUILD_FUZZER)
         fuzzer_pass_outline_functions.h
         fuzzer_pass_permute_blocks.h
         fuzzer_pass_permute_function_parameters.h
+        fuzzer_pass_push_ids_through_variables.h
         fuzzer_pass_split_blocks.h
         fuzzer_pass_swap_commutable_operands.h
         fuzzer_pass_toggle_access_chain_instruction.h
@@ -111,6 +112,7 @@ if(SPIRV_BUILD_FUZZER)
         transformation_move_block_down.h
         transformation_outline_function.h
         transformation_permute_function_parameters.h
+        transformation_push_id_through_variable.h
         transformation_replace_boolean_constant_with_constant_binary.h
         transformation_replace_constant_with_uniform.h
         transformation_replace_id_with_synonym.h
@@ -159,6 +161,7 @@ if(SPIRV_BUILD_FUZZER)
         fuzzer_pass_outline_functions.cpp
         fuzzer_pass_permute_blocks.cpp
         fuzzer_pass_permute_function_parameters.cpp
+        fuzzer_pass_push_ids_through_variables.cpp
         fuzzer_pass_split_blocks.cpp
         fuzzer_pass_swap_commutable_operands.cpp
         fuzzer_pass_toggle_access_chain_instruction.cpp
@@ -206,6 +209,7 @@ if(SPIRV_BUILD_FUZZER)
         transformation_move_block_down.cpp
         transformation_outline_function.cpp
         transformation_permute_function_parameters.cpp
+        transformation_push_id_through_variable.cpp
         transformation_replace_boolean_constant_with_constant_binary.cpp
         transformation_replace_constant_with_uniform.cpp
         transformation_replace_id_with_synonym.cpp

+ 4 - 0
3rdparty/spirv-tools/source/fuzz/fuzzer.cpp

@@ -46,6 +46,7 @@
 #include "source/fuzz/fuzzer_pass_outline_functions.h"
 #include "source/fuzz/fuzzer_pass_permute_blocks.h"
 #include "source/fuzz/fuzzer_pass_permute_function_parameters.h"
+#include "source/fuzz/fuzzer_pass_push_ids_through_variables.h"
 #include "source/fuzz/fuzzer_pass_split_blocks.h"
 #include "source/fuzz/fuzzer_pass_swap_commutable_operands.h"
 #include "source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h"
@@ -249,6 +250,9 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
     MaybeAddPass<FuzzerPassPermuteFunctionParameters>(
         &passes, ir_context.get(), &transformation_context, &fuzzer_context,
         transformation_sequence_out);
+    MaybeAddPass<FuzzerPassPushIdsThroughVariables>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
     MaybeAddPass<FuzzerPassSplitBlocks>(
         &passes, ir_context.get(), &transformation_context, &fuzzer_context,
         transformation_sequence_out);

+ 3 - 0
3rdparty/spirv-tools/source/fuzz/fuzzer_context.cpp

@@ -62,6 +62,7 @@ const std::pair<uint32_t, uint32_t> kChanceOfMovingBlockDown = {20, 50};
 const std::pair<uint32_t, uint32_t> kChanceOfObfuscatingConstant = {10, 90};
 const std::pair<uint32_t, uint32_t> kChanceOfOutliningFunction = {10, 90};
 const std::pair<uint32_t, uint32_t> kChanceOfPermutingParameters = {30, 90};
+const std::pair<uint32_t, uint32_t> kChanceOfPushingIdThroughVariable = {5, 50};
 const std::pair<uint32_t, uint32_t> kChanceOfReplacingIdWithSynonym = {10, 90};
 const std::pair<uint32_t, uint32_t> kChanceOfSplittingBlock = {40, 95};
 const std::pair<uint32_t, uint32_t> kChanceOfTogglingAccessChainInstruction = {
@@ -157,6 +158,8 @@ FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
       ChooseBetweenMinAndMax(kChanceOfOutliningFunction);
   chance_of_permuting_parameters_ =
       ChooseBetweenMinAndMax(kChanceOfPermutingParameters);
+  chance_of_pushing_id_through_variable_ =
+      ChooseBetweenMinAndMax(kChanceOfPushingIdThroughVariable);
   chance_of_replacing_id_with_synonym_ =
       ChooseBetweenMinAndMax(kChanceOfReplacingIdWithSynonym);
   chance_of_splitting_block_ = ChooseBetweenMinAndMax(kChanceOfSplittingBlock);

+ 4 - 0
3rdparty/spirv-tools/source/fuzz/fuzzer_context.h

@@ -179,6 +179,9 @@ class FuzzerContext {
   uint32_t GetChanceOfPermutingParameters() {
     return chance_of_permuting_parameters_;
   }
+  uint32_t GetChanceOfPushingIdThroughVariable() {
+    return chance_of_pushing_id_through_variable_;
+  }
   uint32_t GetChanceOfReplacingIdWithSynonym() {
     return chance_of_replacing_id_with_synonym_;
   }
@@ -263,6 +266,7 @@ class FuzzerContext {
   uint32_t chance_of_obfuscating_constant_;
   uint32_t chance_of_outlining_function_;
   uint32_t chance_of_permuting_parameters_;
+  uint32_t chance_of_pushing_id_through_variable_;
   uint32_t chance_of_replacing_id_with_synonym_;
   uint32_t chance_of_splitting_block_;
   uint32_t chance_of_toggling_access_chain_instruction_;

+ 36 - 35
3rdparty/spirv-tools/source/fuzz/fuzzer_pass.cpp

@@ -161,25 +161,25 @@ uint32_t FuzzerPass::FindOrCreateBoolType() {
   return result;
 }
 
-uint32_t FuzzerPass::FindOrCreate32BitIntegerType(bool is_signed) {
-  opt::analysis::Integer int_type(32, is_signed);
+uint32_t FuzzerPass::FindOrCreateIntegerType(uint32_t width, bool is_signed) {
+  opt::analysis::Integer int_type(width, is_signed);
   auto existing_id = GetIRContext()->get_type_mgr()->GetId(&int_type);
   if (existing_id) {
     return existing_id;
   }
   auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddTypeInt(result, 32, is_signed));
+  ApplyTransformation(TransformationAddTypeInt(result, width, is_signed));
   return result;
 }
 
-uint32_t FuzzerPass::FindOrCreate32BitFloatType() {
-  opt::analysis::Float float_type(32);
+uint32_t FuzzerPass::FindOrCreateFloatType(uint32_t width) {
+  opt::analysis::Float float_type(width);
   auto existing_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
   if (existing_id) {
     return existing_id;
   }
   auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddTypeFloat(result, 32));
+  ApplyTransformation(TransformationAddTypeFloat(result, width));
   return result;
 }
 
@@ -228,7 +228,7 @@ uint32_t FuzzerPass::FindOrCreateMatrixType(uint32_t column_count,
   assert(row_count >= 2 && row_count <= 4 &&
          "Precondition: row count must be in range [2, 4].");
   uint32_t column_type_id =
-      FindOrCreateVectorType(FindOrCreate32BitFloatType(), row_count);
+      FindOrCreateVectorType(FindOrCreateFloatType(32), row_count);
   opt::analysis::Type* column_type =
       GetIRContext()->get_type_mgr()->GetType(column_type_id);
   opt::analysis::Matrix matrix_type(column_type, column_count);
@@ -257,18 +257,17 @@ uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id,
   return result;
 }
 
-uint32_t FuzzerPass::FindOrCreatePointerTo32BitIntegerType(
-    bool is_signed, SpvStorageClass storage_class) {
-  return FindOrCreatePointerType(FindOrCreate32BitIntegerType(is_signed),
+uint32_t FuzzerPass::FindOrCreatePointerToIntegerType(
+    uint32_t width, bool is_signed, SpvStorageClass storage_class) {
+  return FindOrCreatePointerType(FindOrCreateIntegerType(width, is_signed),
                                  storage_class);
 }
 
-uint32_t FuzzerPass::FindOrCreate32BitIntegerConstant(uint32_t word,
-                                                      bool is_signed) {
-  auto uint32_type_id = FindOrCreate32BitIntegerType(is_signed);
+uint32_t FuzzerPass::FindOrCreateIntegerConstant(
+    const std::vector<uint32_t>& words, uint32_t width, bool is_signed) {
+  auto int_type_id = FindOrCreateIntegerType(width, is_signed);
   opt::analysis::IntConstant int_constant(
-      GetIRContext()->get_type_mgr()->GetType(uint32_type_id)->AsInteger(),
-      {word});
+      GetIRContext()->get_type_mgr()->GetType(int_type_id)->AsInteger(), words);
   auto existing_constant =
       GetIRContext()->get_constant_mgr()->FindConstant(&int_constant);
   if (existing_constant) {
@@ -279,15 +278,15 @@ uint32_t FuzzerPass::FindOrCreate32BitIntegerConstant(uint32_t word,
   }
   auto result = GetFuzzerContext()->GetFreshId();
   ApplyTransformation(
-      TransformationAddConstantScalar(result, uint32_type_id, {word}));
+      TransformationAddConstantScalar(result, int_type_id, words));
   return result;
 }
 
-uint32_t FuzzerPass::FindOrCreate32BitFloatConstant(uint32_t word) {
-  auto float_type_id = FindOrCreate32BitFloatType();
+uint32_t FuzzerPass::FindOrCreateFloatConstant(
+    const std::vector<uint32_t>& words, uint32_t width) {
+  auto float_type_id = FindOrCreateFloatType(width);
   opt::analysis::FloatConstant float_constant(
-      GetIRContext()->get_type_mgr()->GetType(float_type_id)->AsFloat(),
-      {word});
+      GetIRContext()->get_type_mgr()->GetType(float_type_id)->AsFloat(), words);
   auto existing_constant =
       GetIRContext()->get_constant_mgr()->FindConstant(&float_constant);
   if (existing_constant) {
@@ -298,7 +297,7 @@ uint32_t FuzzerPass::FindOrCreate32BitFloatConstant(uint32_t word) {
   }
   auto result = GetFuzzerContext()->GetFreshId();
   ApplyTransformation(
-      TransformationAddConstantScalar(result, float_type_id, {word}));
+      TransformationAddConstantScalar(result, float_type_id, words));
   return result;
 }
 
@@ -330,16 +329,10 @@ uint32_t FuzzerPass::FindOrCreateConstant(const std::vector<uint32_t>& words,
     assert(words.size() == 1);
     return FindOrCreateBoolConstant(words[0]);
   } else if (const auto* integer = type->AsInteger()) {
-    assert(integer->width() == 32 && words.size() == 1 &&
-           "Integer must have 32-bit width");
-    return FindOrCreate32BitIntegerConstant(words[0], integer->IsSigned());
+    return FindOrCreateIntegerConstant(words, integer->width(),
+                                       integer->IsSigned());
   } else if (const auto* floating = type->AsFloat()) {
-    // Assertions are not evaluated in release builds so |floating|
-    // variable will be unused.
-    (void)floating;
-    assert(floating->width() == 32 && words.size() == 1 &&
-           "Floating point number must have 32-bit width");
-    return FindOrCreate32BitFloatConstant(words[0]);
+    return FindOrCreateFloatConstant(words, floating->width());
   }
 
   // This assertion will fail in debug build but not in release build
@@ -436,11 +429,19 @@ uint32_t FuzzerPass::FindOrCreateZeroConstant(
   switch (type_instruction->opcode()) {
     case SpvOpTypeBool:
       return FindOrCreateBoolConstant(false);
-    case SpvOpTypeFloat:
-      return FindOrCreate32BitFloatConstant(0);
-    case SpvOpTypeInt:
-      return FindOrCreate32BitIntegerConstant(
-          0, type_instruction->GetSingleWordInOperand(1) != 0);
+    case SpvOpTypeFloat: {
+      auto width = type_instruction->GetSingleWordInOperand(0);
+      auto num_words = (width + 32 - 1) / 32;
+      return FindOrCreateFloatConstant(std::vector<uint32_t>(num_words, 0),
+                                       width);
+    }
+    case SpvOpTypeInt: {
+      auto width = type_instruction->GetSingleWordInOperand(0);
+      auto num_words = (width + 32 - 1) / 32;
+      return FindOrCreateIntegerConstant(
+          std::vector<uint32_t>(num_words, 0), width,
+          type_instruction->GetSingleWordInOperand(1));
+    }
     case SpvOpTypeArray: {
       return GetZeroConstantForHomogeneousComposite(
           *type_instruction, type_instruction->GetSingleWordInOperand(0),

+ 28 - 24
3rdparty/spirv-tools/source/fuzz/fuzzer_pass.h

@@ -107,14 +107,15 @@ class FuzzerPass {
   // not exist, a transformation is applied to add it.
   uint32_t FindOrCreateBoolType();
 
-  // Returns the id of an OpTypeInt instruction, with width 32 and signedness
-  // specified by |is_signed|.  If such an instruction does not exist, a
-  // transformation is applied to add it.
-  uint32_t FindOrCreate32BitIntegerType(bool is_signed);
+  // Returns the id of an OpTypeInt instruction, with width and signedness
+  // specified by |width| and |is_signed|, respectively.  If such an instruction
+  // does not exist, a transformation is applied to add it.
+  uint32_t FindOrCreateIntegerType(uint32_t width, bool is_signed);
 
-  // Returns the id of an OpTypeFloat instruction, with width 32.  If such an
-  // instruction does not exist, a transformation is applied to add it.
-  uint32_t FindOrCreate32BitFloatType();
+  // Returns the id of an OpTypeFloat instruction, with width specified by
+  // |width|.  If such an instruction does not exist, a transformation is
+  // applied to add it.
+  uint32_t FindOrCreateFloatType(uint32_t width);
 
   // Returns the id of an OpTypeFunction %<return_type_id> %<...argument_id>
   // instruction. If such an instruction doesn't exist, a transformation
@@ -141,23 +142,26 @@ class FuzzerPass {
   uint32_t FindOrCreatePointerType(uint32_t base_type_id,
                                    SpvStorageClass storage_class);
 
-  // Returns the id of an OpTypePointer instruction, with a 32-bit integer base
-  // type of signedness specified by |is_signed|.  If the pointer type or
-  // required integer base type do not exist, transformations are applied to add
-  // them.
-  uint32_t FindOrCreatePointerTo32BitIntegerType(bool is_signed,
-                                                 SpvStorageClass storage_class);
-
-  // Returns the id of an OpConstant instruction, with 32-bit integer type of
-  // signedness specified by |is_signed|, with |word| as its value.  If either
-  // the required integer type or the constant do not exist, transformations are
-  // applied to add them.
-  uint32_t FindOrCreate32BitIntegerConstant(uint32_t word, bool is_signed);
-
-  // Returns the id of an OpConstant instruction, with 32-bit floating-point
-  // type, with |word| as its value.  If either the required floating-point type
-  // or the constant do not exist, transformations are applied to add them.
-  uint32_t FindOrCreate32BitFloatConstant(uint32_t word);
+  // Returns the id of an OpTypePointer instruction, with a integer base
+  // type of width and signedness specified by |width| and |is_signed|,
+  // respectively.  If the pointer type or required integer base type do not
+  // exist, transformations are applied to add them.
+  uint32_t FindOrCreatePointerToIntegerType(uint32_t width, bool is_signed,
+                                            SpvStorageClass storage_class);
+
+  // Returns the id of an OpConstant instruction, with a integer type of
+  // width and signedness specified by |width| and |is_signed|, respectively,
+  // with |words| as its value.  If either the required integer type or the
+  // constant do not exist, transformations are applied to add them.
+  uint32_t FindOrCreateIntegerConstant(const std::vector<uint32_t>& words,
+                                       uint32_t width, bool is_signed);
+
+  // Returns the id of an OpConstant instruction, with a floating-point
+  // type of width specified by |width|, with |words| as its value.  If either
+  // the required floating-point type or the constant do not exist,
+  // transformations are applied to add them.
+  uint32_t FindOrCreateFloatConstant(const std::vector<uint32_t>& words,
+                                     uint32_t width);
 
   // Returns the id of an OpConstantTrue or OpConstantFalse instruction,
   // according to |value|.  If either the required instruction or the bool

+ 2 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.cpp

@@ -137,8 +137,8 @@ void FuzzerPassAddAccessChains::Apply() {
           //  using clamping to ensure they are in-bounds.
           uint32_t index_value =
               GetFuzzerContext()->GetRandomIndexForAccessChain(bound);
-          index_ids.push_back(FindOrCreate32BitIntegerConstant(
-              index_value, GetFuzzerContext()->ChooseEven()));
+          index_ids.push_back(FindOrCreateIntegerConstant(
+              {index_value}, 32, GetFuzzerContext()->ChooseEven()));
           switch (subobject_type->opcode()) {
             case SpvOpTypeArray:
             case SpvOpTypeMatrix:

+ 5 - 5
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.cpp

@@ -53,13 +53,13 @@ void FuzzerPassAddCompositeTypes::MaybeAddMissingVectorTypes() {
     return FindOrCreateBoolType();
   };
   std::function<uint32_t()> float_type_supplier = [this]() -> uint32_t {
-    return FindOrCreate32BitFloatType();
+    return FindOrCreateFloatType(32);
   };
   std::function<uint32_t()> int_type_supplier = [this]() -> uint32_t {
-    return FindOrCreate32BitIntegerType(true);
+    return FindOrCreateIntegerType(32, true);
   };
   std::function<uint32_t()> uint_type_supplier = [this]() -> uint32_t {
-    return FindOrCreate32BitIntegerType(false);
+    return FindOrCreateIntegerType(32, false);
   };
 
   // Consider each of the base types with which we can make vectors.
@@ -96,8 +96,8 @@ void FuzzerPassAddCompositeTypes::MaybeAddMissingMatrixTypes() {
 void FuzzerPassAddCompositeTypes::AddNewArrayType() {
   ApplyTransformation(TransformationAddTypeArray(
       GetFuzzerContext()->GetFreshId(), ChooseScalarOrCompositeType(),
-      FindOrCreate32BitIntegerConstant(
-          GetFuzzerContext()->GetRandomSizeForNewArray(), false)));
+      FindOrCreateIntegerConstant(
+          {GetFuzzerContext()->GetRandomSizeForNewArray()}, 32, false)));
 }
 
 void FuzzerPassAddCompositeTypes::AddNewStructType() {

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.cpp

@@ -60,7 +60,7 @@ void FuzzerPassAddLoads::Apply() {
                   if (!instruction->result_id() || !instruction->type_id()) {
                     return false;
                   }
-                  switch (instruction->result_id()) {
+                  switch (instruction->opcode()) {
                     case SpvOpConstantNull:
                     case SpvOpUndef:
                       // Do not allow loading from a null or undefined pointer;

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.cpp

@@ -72,7 +72,7 @@ void FuzzerPassAddStores::Apply() {
                     // Read only: cannot store to it.
                     return false;
                   }
-                  switch (instruction->result_id()) {
+                  switch (instruction->opcode()) {
                     case SpvOpConstantNull:
                     case SpvOpUndef:
                       // Do not allow storing to a null or undefined pointer;

+ 12 - 13
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp

@@ -326,8 +326,8 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
       new_result_id = GetFuzzerContext()->GetFreshId();
       ApplyTransformation(TransformationAddTypeArray(
           new_result_id, original_id_to_donated_id->at(component_type_id),
-          FindOrCreate32BitIntegerConstant(
-              GetFuzzerContext()->GetRandomSizeForNewArray(), false)));
+          FindOrCreateIntegerConstant(
+              {GetFuzzerContext()->GetRandomSizeForNewArray()}, 32, false)));
     } break;
     case SpvOpTypeStruct: {
       // Similar to SpvOpTypeArray.
@@ -982,19 +982,19 @@ void FuzzerPassDonateModules::AddLivesafeFunction(
   // Various types and constants must be in place for a function to be made
   // live-safe.  Add them if not already present.
   FindOrCreateBoolType();  // Needed for comparisons
-  FindOrCreatePointerTo32BitIntegerType(
-      false, SpvStorageClassFunction);  // Needed for adding loop limiters
-  FindOrCreate32BitIntegerConstant(
-      0, false);  // Needed for initializing loop limiters
-  FindOrCreate32BitIntegerConstant(
-      1, false);  // Needed for incrementing loop limiters
+  FindOrCreatePointerToIntegerType(
+      32, false, SpvStorageClassFunction);  // Needed for adding loop limiters
+  FindOrCreateIntegerConstant({0}, 32,
+                              false);  // Needed for initializing loop limiters
+  FindOrCreateIntegerConstant({1}, 32,
+                              false);  // Needed for incrementing loop limiters
 
   // Get a fresh id for the variable that will be used as a loop limiter.
   const uint32_t loop_limiter_variable_id = GetFuzzerContext()->GetFreshId();
   // Choose a random loop limit, and add the required constant to the
   // module if not already there.
-  const uint32_t loop_limit = FindOrCreate32BitIntegerConstant(
-      GetFuzzerContext()->GetRandomLoopLimit(), false);
+  const uint32_t loop_limit = FindOrCreateIntegerConstant(
+      {GetFuzzerContext()->GetRandomLoopLimit()}, 32, false);
 
   // Consider every loop header in the function to donate, and create a
   // structure capturing the ids to be used for manipulating the loop
@@ -1080,7 +1080,6 @@ void FuzzerPassDonateModules::AddLivesafeFunction(
             auto index_type_inst = donor_ir_context->get_def_use_mgr()->GetDef(
                 index_inst->type_id());
             assert(index_type_inst->opcode() == SpvOpTypeInt);
-            assert(index_type_inst->GetSingleWordInOperand(0) == 32);
             opt::analysis::Integer* index_int_type =
                 donor_ir_context->get_type_mgr()
                     ->GetType(index_type_inst->result_id())
@@ -1089,8 +1088,8 @@ void FuzzerPassDonateModules::AddLivesafeFunction(
               // We will have to clamp this index, so we need a constant
               // whose value is one less than the bound, to compare
               // against and to use as the clamped value.
-              FindOrCreate32BitIntegerConstant(bound - 1,
-                                               index_int_type->IsSigned());
+              FindOrCreateIntegerConstant({bound - 1}, 32,
+                                          index_int_type->IsSigned());
             }
             should_be_composite_type =
                 TransformationAddFunction::FollowCompositeIndex(

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp

@@ -361,7 +361,7 @@ void FuzzerPassObfuscateConstants::ObfuscateScalarConstant(
   // Make sure the module has OpConstant instructions for each index used to
   // access a uniform.
   for (auto index : uniform_descriptor.index()) {
-    FindOrCreate32BitIntegerConstant(index, true);
+    FindOrCreateIntegerConstant({index}, 32, true);
   }
 
   // Make sure the module has OpTypePointer that points to the element type of

+ 109 - 0
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp

@@ -0,0 +1,109 @@
+// Copyright (c) 2020 André Perez Maselco
+//
+// 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/fuzz/fuzzer_pass_push_ids_through_variables.h"
+
+#include "source/fuzz/fuzzer_util.h"
+#include "source/fuzz/instruction_descriptor.h"
+#include "source/fuzz/transformation_push_id_through_variable.h"
+
+namespace spvtools {
+namespace fuzz {
+
+FuzzerPassPushIdsThroughVariables::FuzzerPassPushIdsThroughVariables(
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
+    FuzzerContext* fuzzer_context,
+    protobufs::TransformationSequence* transformations)
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
+
+FuzzerPassPushIdsThroughVariables::~FuzzerPassPushIdsThroughVariables() =
+    default;
+
+void FuzzerPassPushIdsThroughVariables::Apply() {
+  ForEachInstructionWithInstructionDescriptor(
+      [this](opt::Function* function, opt::BasicBlock* block,
+             opt::BasicBlock::iterator instruction_iterator,
+             const protobufs::InstructionDescriptor& instruction_descriptor)
+          -> void {
+        assert(instruction_iterator->opcode() ==
+                   instruction_descriptor.target_instruction_opcode() &&
+               "The opcode of the instruction we might insert before must be "
+               "the same as the opcode in the descriptor for the instruction");
+
+        // Randomly decide whether to try pushing an id through a variable.
+        if (!GetFuzzerContext()->ChoosePercentage(
+                GetFuzzerContext()->GetChanceOfPushingIdThroughVariable())) {
+          return;
+        }
+
+        // The block containing the instruction we are going to insert before
+        // must be reachable.
+        if (!fuzzerutil::BlockIsReachableInItsFunction(GetIRContext(), block)) {
+          return;
+        }
+
+        // It must be valid to insert OpStore and OpLoad instructions
+        // before the instruction to insert before.
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                SpvOpStore, instruction_iterator) ||
+            !fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                SpvOpLoad, instruction_iterator)) {
+          return;
+        }
+
+        // Randomly decides whether a global or local variable will be added.
+        auto variable_storage_class = GetFuzzerContext()->ChooseEven()
+                                          ? SpvStorageClassPrivate
+                                          : SpvStorageClassFunction;
+
+        // Gets the available basic and pointer types.
+        auto basic_type_ids_and_pointers =
+            GetAvailableBasicTypesAndPointers(variable_storage_class);
+        auto& basic_types = basic_type_ids_and_pointers.first;
+        uint32_t basic_type_id =
+            basic_types[GetFuzzerContext()->RandomIndex(basic_types)];
+
+        // Looks for ids that we might wish to consider pushing through a
+        // variable.
+        std::vector<opt::Instruction*> value_instructions =
+            FindAvailableInstructions(
+                function, block, instruction_iterator,
+                [basic_type_id](opt::IRContext* /*unused*/,
+                                opt::Instruction* instruction) -> bool {
+                  if (!instruction->result_id() || !instruction->type_id()) {
+                    return false;
+                  }
+                  return instruction->type_id() == basic_type_id;
+                });
+
+        if (value_instructions.empty()) {
+          return;
+        }
+
+        // If the pointer type does not exist, then create it.
+        FindOrCreatePointerType(basic_type_id, variable_storage_class);
+
+        // Applies the push id through variable transformation.
+        ApplyTransformation(TransformationPushIdThroughVariable(
+            value_instructions[GetFuzzerContext()->RandomIndex(
+                                   value_instructions)]
+                ->result_id(),
+            GetFuzzerContext()->GetFreshId(), GetFuzzerContext()->GetFreshId(),
+            variable_storage_class, instruction_descriptor));
+      });
+}
+
+}  // namespace fuzz
+}  // namespace spvtools

+ 41 - 0
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_push_ids_through_variables.h

@@ -0,0 +1,41 @@
+// Copyright (c) 2020 André Perez Maselco
+//
+// 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_FUZZ_FUZZER_PASS_PUSH_IDS_THROUGH_VARIABLES_H_
+#define SOURCE_FUZZ_FUZZER_PASS_PUSH_IDS_THROUGH_VARIABLES_H_
+
+#include "source/fuzz/fuzzer_pass.h"
+
+namespace spvtools {
+namespace fuzz {
+
+// Adds instructions to the module that store existing ids into fresh variables
+// and immediately load from said variables into new ids, thus creating synonyms
+// between the existing and fresh ids.
+class FuzzerPassPushIdsThroughVariables : public FuzzerPass {
+ public:
+  FuzzerPassPushIdsThroughVariables(
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
+      FuzzerContext* fuzzer_context,
+      protobufs::TransformationSequence* transformations);
+
+  ~FuzzerPassPushIdsThroughVariables();
+
+  void Apply() override;
+};
+
+}  // namespace fuzz
+}  // namespace spvtools
+
+#endif  // SOURCE_FUZZ_FUZZER_PASS_PUSH_IDS_THROUGH_VARIABLES_H_

+ 25 - 0
3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto

@@ -375,6 +375,7 @@ message Transformation {
     TransformationAddConstantNull add_constant_null = 44;
     TransformationComputeDataSynonymFactClosure compute_data_synonym_fact_closure = 45;
     TransformationAdjustBranchWeights adjust_branch_weights = 46;
+    TransformationPushIdThroughVariable push_id_through_variable = 47;
     // Add additional option using the next available number.
   }
 }
@@ -983,6 +984,30 @@ message TransformationPermuteFunctionParameters {
 
 }
 
+message TransformationPushIdThroughVariable {
+
+  // A transformation that makes |value_synonym_id| and |value_id| to be
+  // synonymous by storing |value_id| into |variable_id| and
+  // loading |variable_id| to |value_synonym_id|.
+
+  // The value to be stored.
+  uint32 value_id = 1;
+
+  // A fresh id for the result of the load instruction.
+  uint32 value_synonym_id = 2;
+
+  // A fresh id for the variable to be stored to.
+  uint32 variable_id = 3;
+
+  // The variable storage class (global or local).
+  uint32 variable_storage_class = 4;
+
+  // A descriptor for an instruction which the new OpStore
+  // and OpLoad instructions might be inserted before.
+  InstructionDescriptor instruction_descriptor = 5;
+
+}
+
 message TransformationReplaceBooleanConstantWithConstantBinary {
 
   // A transformation to capture replacing a use of a boolean constant with

+ 4 - 0
3rdparty/spirv-tools/source/fuzz/transformation.cpp

@@ -51,6 +51,7 @@
 #include "source/fuzz/transformation_move_block_down.h"
 #include "source/fuzz/transformation_outline_function.h"
 #include "source/fuzz/transformation_permute_function_parameters.h"
+#include "source/fuzz/transformation_push_id_through_variable.h"
 #include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h"
 #include "source/fuzz/transformation_replace_constant_with_uniform.h"
 #include "source/fuzz/transformation_replace_id_with_synonym.h"
@@ -163,6 +164,9 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
         kPermuteFunctionParameters:
       return MakeUnique<TransformationPermuteFunctionParameters>(
           message.permute_function_parameters());
+    case protobufs::Transformation::TransformationCase::kPushIdThroughVariable:
+      return MakeUnique<TransformationPushIdThroughVariable>(
+          message.push_id_through_variable());
     case protobufs::Transformation::TransformationCase::
         kReplaceBooleanConstantWithConstantBinary:
       return MakeUnique<TransformationReplaceBooleanConstantWithConstantBinary>(

+ 159 - 0
3rdparty/spirv-tools/source/fuzz/transformation_push_id_through_variable.cpp

@@ -0,0 +1,159 @@
+// Copyright (c) 2020 André Perez Maselco
+//
+// 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/fuzz/transformation_push_id_through_variable.h"
+
+#include "source/fuzz/fuzzer_util.h"
+#include "source/fuzz/instruction_descriptor.h"
+
+namespace spvtools {
+namespace fuzz {
+
+TransformationPushIdThroughVariable::TransformationPushIdThroughVariable(
+    const spvtools::fuzz::protobufs::TransformationPushIdThroughVariable&
+        message)
+    : message_(message) {}
+
+TransformationPushIdThroughVariable::TransformationPushIdThroughVariable(
+    uint32_t value_id, uint32_t value_synonym_id, uint32_t variable_id,
+    uint32_t variable_storage_class,
+    const protobufs::InstructionDescriptor& instruction_descriptor) {
+  message_.set_value_id(value_id);
+  message_.set_value_synonym_id(value_synonym_id);
+  message_.set_variable_id(variable_id);
+  message_.set_variable_storage_class(variable_storage_class);
+  *message_.mutable_instruction_descriptor() = instruction_descriptor;
+}
+
+bool TransformationPushIdThroughVariable::IsApplicable(
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
+  // |message_.value_synonym_id| and |message_.variable_id| must be fresh.
+  if (!fuzzerutil::IsFreshId(ir_context, message_.value_synonym_id()) ||
+      !fuzzerutil::IsFreshId(ir_context, message_.variable_id())) {
+    return false;
+  }
+
+  // The instruction to insert before must be defined.
+  auto instruction_to_insert_before =
+      FindInstruction(message_.instruction_descriptor(), ir_context);
+  if (!instruction_to_insert_before) {
+    return false;
+  }
+
+  // It must be valid to insert the OpStore and OpLoad instruction before it.
+  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
+          SpvOpStore, instruction_to_insert_before) ||
+      !fuzzerutil::CanInsertOpcodeBeforeInstruction(
+          SpvOpLoad, instruction_to_insert_before)) {
+    return false;
+  }
+
+  // The instruction to insert before must belong to a reachable block.
+  auto basic_block = ir_context->get_instr_block(instruction_to_insert_before);
+  if (!fuzzerutil::BlockIsReachableInItsFunction(ir_context, basic_block)) {
+    return false;
+  }
+
+  // The value instruction must be defined and have a type.
+  auto value_instruction =
+      ir_context->get_def_use_mgr()->GetDef(message_.value_id());
+  if (!value_instruction || !value_instruction->type_id()) {
+    return false;
+  }
+
+  // A pointer type instruction pointing to the value type must be defined.
+  auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
+      ir_context, value_instruction->type_id(),
+      static_cast<SpvStorageClass>(message_.variable_storage_class()));
+  if (!pointer_type_id) {
+    return false;
+  }
+
+  // |message_.variable_storage_class| must be private or function.
+  assert((message_.variable_storage_class() == SpvStorageClassPrivate ||
+          message_.variable_storage_class() == SpvStorageClassFunction) &&
+         "The variable storage class must be private or function.");
+
+  // |message_.value_id| must be available at the insertion point.
+  return fuzzerutil::IdIsAvailableBeforeInstruction(
+      ir_context, instruction_to_insert_before, message_.value_id());
+}
+
+void TransformationPushIdThroughVariable::Apply(
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
+  auto value_instruction =
+      ir_context->get_def_use_mgr()->GetDef(message_.value_id());
+
+  // A pointer type instruction pointing to the value type must be defined.
+  auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
+      ir_context, value_instruction->type_id(),
+      static_cast<SpvStorageClass>(message_.variable_storage_class()));
+  assert(pointer_type_id && "The required pointer type must be available.");
+
+  // Adds whether a global or local variable.
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.variable_id());
+  if (message_.variable_storage_class() == SpvStorageClassPrivate) {
+    ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+        ir_context, SpvOpVariable, pointer_type_id, message_.variable_id(),
+        opt::Instruction::OperandList(
+            {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassPrivate}}})));
+  } else {
+    ir_context
+        ->get_instr_block(
+            FindInstruction(message_.instruction_descriptor(), ir_context))
+        ->GetParent()
+        ->begin()
+        ->begin()
+        ->InsertBefore(MakeUnique<opt::Instruction>(
+            ir_context, SpvOpVariable, pointer_type_id, message_.variable_id(),
+            opt::Instruction::OperandList({{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                            {SpvStorageClassFunction}}})));
+  }
+
+  // Stores value id to variable id.
+  FindInstruction(message_.instruction_descriptor(), ir_context)
+      ->InsertBefore(MakeUnique<opt::Instruction>(
+          ir_context, SpvOpStore, 0, 0,
+          opt::Instruction::OperandList(
+              {{SPV_OPERAND_TYPE_ID, {message_.variable_id()}},
+               {SPV_OPERAND_TYPE_ID, {message_.value_id()}}})));
+
+  // Loads variable id to value synonym id.
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.value_synonym_id());
+  FindInstruction(message_.instruction_descriptor(), ir_context)
+      ->InsertBefore(MakeUnique<opt::Instruction>(
+          ir_context, SpvOpLoad, value_instruction->type_id(),
+          message_.value_synonym_id(),
+          opt::Instruction::OperandList(
+              {{SPV_OPERAND_TYPE_ID, {message_.variable_id()}}})));
+
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+
+  // Adds the fact that |message_.value_synonym_id|
+  // and |message_.value_id| are synonymous.
+  transformation_context->GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(message_.value_synonym_id(), {}),
+      MakeDataDescriptor(message_.value_id(), {}), ir_context);
+}
+
+protobufs::Transformation TransformationPushIdThroughVariable::ToMessage()
+    const {
+  protobufs::Transformation result;
+  *result.mutable_push_id_through_variable() = message_;
+  return result;
+}
+
+}  // namespace fuzz
+}  // namespace spvtools

+ 64 - 0
3rdparty/spirv-tools/source/fuzz/transformation_push_id_through_variable.h

@@ -0,0 +1,64 @@
+// Copyright (c) 2020 André Perez Maselco
+//
+// 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_FUZZ_TRANSFORMATION_PUSH_ID_THROUGH_VARIABLE_H_
+#define SOURCE_FUZZ_TRANSFORMATION_PUSH_ID_THROUGH_VARIABLE_H_
+
+#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
+#include "source/opt/ir_context.h"
+
+namespace spvtools {
+namespace fuzz {
+
+class TransformationPushIdThroughVariable : public Transformation {
+ public:
+  explicit TransformationPushIdThroughVariable(
+      const protobufs::TransformationPushIdThroughVariable& message);
+
+  TransformationPushIdThroughVariable(
+      uint32_t value_id, uint32_t value_synonym_fresh_id,
+      uint32_t variable_fresh_id, uint32_t variable_storage_class,
+      const protobufs::InstructionDescriptor& instruction_descriptor);
+
+  // - |message_.value_id| must be an instruction result id that has the same
+  //   type as the pointee type of |message_.pointer_id|
+  // - |message_.value_synonym_id| must be fresh
+  // - |message_.variable_id| must be fresh
+  // - |message_.variable_storage_class| must be either StorageClassPrivate or
+  //   StorageClassFunction
+  // - |message_.instruction_descriptor| must identify an instruction
+  //   which it is valid to insert the OpStore and OpLoad instructions before it
+  //   and must be belongs to a reachable block.
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
+
+  // Stores |value_id| to |variable_id|, loads |variable_id| to
+  // |value_synonym_id| and adds the fact that |value_synonym_id| and |value_id|
+  // are synonymous.
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
+
+  protobufs::Transformation ToMessage() const override;
+
+ private:
+  protobufs::TransformationPushIdThroughVariable message_;
+};
+
+}  // namespace fuzz
+}  // namespace spvtools
+
+#endif  // SOURCE_FUZZ_TRANSFORMATION_PUSH_ID_THROUGH_VARIABLE_H_

+ 8 - 1
3rdparty/spirv-tools/source/val/validate_extensions.cpp

@@ -2300,7 +2300,14 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
             ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
         if (validate_parent != SPV_SUCCESS) return validate_parent;
         CHECK_OPERAND("Linkage Name", SpvOpString, 11);
-        CHECK_OPERAND("Size", SpvOpConstant, 12);
+        if (!DoesDebugInfoOperandMatchExpectation(
+                _,
+                [](OpenCLDebugInfo100Instructions dbg_inst) {
+                  return dbg_inst == OpenCLDebugInfo100DebugInfoNone;
+                },
+                inst, 12)) {
+          CHECK_OPERAND("Size", SpvOpConstant, 12);
+        }
         for (uint32_t word_index = 14; word_index < num_words; ++word_index) {
           if (!DoesDebugInfoOperandMatchExpectation(
                   _,

+ 15 - 3
3rdparty/spirv-tools/source/val/validate_image.cpp

@@ -160,6 +160,17 @@ bool IsValidLodOperand(const ValidationState_t& _, SpvOp opcode) {
   }
 }
 
+bool IsValidGatherLodBiasAMD(const ValidationState_t& _, SpvOp opcode) {
+  switch (opcode) {
+    case SpvOpImageGather:
+    case SpvOpImageSparseGather:
+      return _.HasCapability(SpvCapabilityImageGatherBiasLodAMD);
+    default:
+      break;
+  }
+  return false;
+}
+
 // Returns true if the opcode is a Image instruction which applies
 // homogenous projection to the coordinates.
 bool IsProj(SpvOp opcode) {
@@ -260,11 +271,12 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
   const bool is_implicit_lod = IsImplicitLod(opcode);
   const bool is_explicit_lod = IsExplicitLod(opcode);
   const bool is_valid_lod_operand = IsValidLodOperand(_, opcode);
+  const bool is_valid_gather_lod_bias_amd = IsValidGatherLodBiasAMD(_, opcode);
 
   // The checks should be done in the order of definition of OperandImage.
 
   if (mask & SpvImageOperandsBiasMask) {
-    if (!is_implicit_lod) {
+    if (!is_implicit_lod && !is_valid_gather_lod_bias_amd) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Bias can only be used with ImplicitLod opcodes";
     }
@@ -290,7 +302,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
 
   if (mask & SpvImageOperandsLodMask) {
     if (!is_valid_lod_operand && opcode != SpvOpImageFetch &&
-        opcode != SpvOpImageSparseFetch) {
+        opcode != SpvOpImageSparseFetch && !is_valid_gather_lod_bias_amd) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Lod can only be used with ExplicitLod opcodes "
              << "and OpImageFetch";
@@ -303,7 +315,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
     }
 
     const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
-    if (is_explicit_lod) {
+    if (is_explicit_lod || is_valid_gather_lod_bias_amd) {
       if (!_.IsFloatScalarType(type_id)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Image Operand Lod to be float scalar when used "

Some files were not shown because too many files changed in this diff