瀏覽代碼

Updated spirv-tools.

Бранимир Караџић 6 年之前
父節點
當前提交
d5b4179ce9
共有 86 個文件被更改,包括 10751 次插入173 次删除
  1. 2 0
      3rdparty/spirv-tools/Android.mk
  2. 4 1
      3rdparty/spirv-tools/BUILD.gn
  3. 1 1
      3rdparty/spirv-tools/CONTRIBUTING.md
  4. 1 1
      3rdparty/spirv-tools/DEPS
  5. 3 3
      3rdparty/spirv-tools/README.md
  6. 0 0
      3rdparty/spirv-tools/docs/downloads.md
  7. 0 0
      3rdparty/spirv-tools/docs/projects.md
  8. 0 0
      3rdparty/spirv-tools/docs/syntax.md
  9. 1 1
      3rdparty/spirv-tools/include/generated/build-version.inc
  10. 2 1
      3rdparty/spirv-tools/include/generated/enum_string_mapping.inc
  11. 1 0
      3rdparty/spirv-tools/include/generated/extension_enum.inc
  12. 11 11
      3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc
  13. 5 0
      3rdparty/spirv-tools/include/spirv-tools/libspirv.h
  14. 5 0
      3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp
  15. 7 0
      3rdparty/spirv-tools/source/fuzz/CMakeLists.txt
  16. 4 0
      3rdparty/spirv-tools/source/fuzz/fuzzer.cpp
  17. 3 0
      3rdparty/spirv-tools/source/fuzz/fuzzer_context.cpp
  18. 4 0
      3rdparty/spirv-tools/source/fuzz/fuzzer_context.h
  19. 3 3
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.cpp
  20. 3 3
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.cpp
  21. 108 0
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
  22. 42 0
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.h
  23. 66 46
      3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp
  24. 28 0
      3rdparty/spirv-tools/source/fuzz/id_use_descriptor.cpp
  25. 6 0
      3rdparty/spirv-tools/source/fuzz/id_use_descriptor.h
  26. 34 16
      3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto
  27. 31 2
      3rdparty/spirv-tools/source/fuzz/replayer.cpp
  28. 2 1
      3rdparty/spirv-tools/source/fuzz/replayer.h
  29. 14 10
      3rdparty/spirv-tools/source/fuzz/shrinker.cpp
  30. 2 1
      3rdparty/spirv-tools/source/fuzz/shrinker.h
  31. 4 0
      3rdparty/spirv-tools/source/fuzz/transformation.cpp
  32. 155 0
      3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.cpp
  33. 72 0
      3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.h
  34. 10 13
      3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp
  35. 4 3
      3rdparty/spirv-tools/source/opt/function.cpp
  36. 50 16
      3rdparty/spirv-tools/source/opt/ir_builder.h
  37. 1 1
      3rdparty/spirv-tools/source/opt/optimizer.cpp
  38. 18 1
      3rdparty/spirv-tools/source/opt/wrap_opkill.cpp
  39. 4 0
      3rdparty/spirv-tools/source/opt/wrap_opkill.h
  40. 6 0
      3rdparty/spirv-tools/source/spirv_fuzzer_options.cpp
  41. 3 0
      3rdparty/spirv-tools/source/spirv_fuzzer_options.h
  42. 19 0
      3rdparty/spirv-tools/source/val/validate.cpp
  43. 1 1
      3rdparty/spirv-tools/source/val/validate.h
  44. 34 8
      3rdparty/spirv-tools/source/val/validate_conversion.cpp
  45. 24 4
      3rdparty/spirv-tools/source/val/validate_decorations.cpp
  46. 13 0
      3rdparty/spirv-tools/source/val/validate_memory.cpp
  47. 0 1
      3rdparty/spirv-tools/source/val/validate_type.cpp
  48. 12 2
      3rdparty/spirv-tools/test/fuzz/CMakeLists.txt
  49. 16 0
      3rdparty/spirv-tools/test/fuzz/fuzz_test_util.cpp
  50. 7 0
      3rdparty/spirv-tools/test/fuzz/fuzz_test_util.h
  51. 1 1
      3rdparty/spirv-tools/test/fuzz/fuzzer_replayer_test.cpp
  52. 2 1
      3rdparty/spirv-tools/test/fuzz/fuzzer_shrinker_test.cpp
  53. 139 0
      3rdparty/spirv-tools/test/fuzz/transformation_add_dead_continue_test.cpp
  54. 569 0
      3rdparty/spirv-tools/test/fuzz/transformation_replace_id_with_synonym_test.cpp
  55. 51 0
      3rdparty/spirv-tools/test/opt/copy_prop_array_test.cpp
  56. 57 5
      3rdparty/spirv-tools/test/opt/wrap_opkill_test.cpp
  57. 1 0
      3rdparty/spirv-tools/test/val/CMakeLists.txt
  58. 165 9
      3rdparty/spirv-tools/test/val/val_conversion_test.cpp
  59. 239 0
      3rdparty/spirv-tools/test/val/val_decoration_test.cpp
  60. 76 0
      3rdparty/spirv-tools/test/val/val_entry_point.cpp
  61. 95 1
      3rdparty/spirv-tools/test/val/val_memory_test.cpp
  62. 41 3
      3rdparty/spirv-tools/tools/fuzz/fuzz.cpp
  63. 25 0
      3rdparty/spirv-tools/tools/sva/.eslintrc.json
  64. 6 0
      3rdparty/spirv-tools/tools/sva/.gitignore
  65. 41 0
      3rdparty/spirv-tools/tools/sva/README.md
  66. 32 0
      3rdparty/spirv-tools/tools/sva/bin/sva.js
  67. 1 0
      3rdparty/spirv-tools/tools/sva/mocha.opts
  68. 25 0
      3rdparty/spirv-tools/tools/sva/package.json
  69. 7 0
      3rdparty/spirv-tools/tools/sva/rollup.config.js
  70. 98 0
      3rdparty/spirv-tools/tools/sva/src/assembler.js
  71. 165 0
      3rdparty/spirv-tools/tools/sva/src/assembler_test.js
  72. 141 0
      3rdparty/spirv-tools/tools/sva/src/ast.js
  73. 363 0
      3rdparty/spirv-tools/tools/sva/src/lexer.js
  74. 191 0
      3rdparty/spirv-tools/tools/sva/src/lexer_test.js
  75. 277 0
      3rdparty/spirv-tools/tools/sva/src/parser.js
  76. 464 0
      3rdparty/spirv-tools/tools/sva/src/parser_test.js
  77. 4567 0
      3rdparty/spirv-tools/tools/sva/src/spirv.data.js
  78. 40 0
      3rdparty/spirv-tools/tools/sva/src/sva.js
  79. 55 0
      3rdparty/spirv-tools/tools/sva/src/token.js
  80. 18 0
      3rdparty/spirv-tools/tools/sva/tests/empty_main.spv_asm
  81. 23 0
      3rdparty/spirv-tools/tools/sva/tests/index.html
  82. 30 0
      3rdparty/spirv-tools/tools/sva/tests/simple.spv_asm
  83. 119 0
      3rdparty/spirv-tools/tools/sva/tools/process_grammar.rb
  84. 1778 0
      3rdparty/spirv-tools/tools/sva/yarn.lock
  85. 1 1
      3rdparty/spirv-tools/tools/util/cli_consumer.h
  86. 2 1
      3rdparty/spirv-tools/utils/check_copyright.py

+ 2 - 0
3rdparty/spirv-tools/Android.mk

@@ -250,6 +250,8 @@ $(LOCAL_PATH)/source/ext_inst.cpp: \
 	$(1)/spv-amd-shader-ballot.insts.inc \
 	$(1)/spv-amd-shader-explicit-vertex-parameter.insts.inc \
 	$(1)/spv-amd-shader-trinary-minmax.insts.inc
+$(LOCAL_PATH)/source/opt/amd_ext_to_khr.cpp: \
+	$(1)/spv-amd-shader-ballot.insts.inc
 endef
 $(eval $(call gen_spvtools_grammar_tables,$(SPVTOOLS_OUT_PATH)))
 

+ 4 - 1
3rdparty/spirv-tools/BUILD.gn

@@ -288,7 +288,10 @@ config("spvtools_internal_config") {
   configs = [ ":spvtools_public_config" ]
 
   if (is_clang) {
-    cflags = [ "-Wno-implicit-fallthrough" ]
+    cflags = [
+      "-Wno-implicit-fallthrough",
+      "-Wno-newline-eof",
+    ]
   }
 }
 

+ 1 - 1
3rdparty/spirv-tools/CONTRIBUTING.md

@@ -4,7 +4,7 @@
 
 We organize known future work in GitHub projects. See [Tracking SPIRV-Tools work
 with GitHub
-projects](https://github.com/KhronosGroup/SPIRV-Tools/blob/master/projects.md)
+projects](https://github.com/KhronosGroup/SPIRV-Tools/blob/master/docs/projects.md)
 for more.
 
 To report a new bug or request a new feature, please file a GitHub issue. Please

+ 1 - 1
3rdparty/spirv-tools/DEPS

@@ -6,7 +6,7 @@ vars = {
   'effcee_revision': 'b83b58d177b797edd1f94c5f10837f2cc2863f0a',
   'googletest_revision': '2f42d769ad1b08742f7ccb5ad4dd357fc5ff248c',
   're2_revision': 'e356bd3f80e0c15c1050323bb5a2d0f8ea4845f4',
-  'spirv_headers_revision': '123dc278f204f8e833e1a88d31c46d0edf81d4b2',
+  'spirv_headers_revision': '601d738723ac381741311c6c98c36d6170be14a2',
 }
 
 deps = {

+ 3 - 3
3rdparty/spirv-tools/README.md

@@ -26,7 +26,7 @@ headers, and XML registry.
 <img alt="MacOS" src="kokoro/img/macos.png" width="20px" height="20px" hspace="2px"/>[![MacOS Build Status](https://storage.googleapis.com/spirv-tools/badges/build_status_macos_clang_release.svg)](https://storage.googleapis.com/spirv-tools/badges/build_link_macos_clang_release.html)
 <img alt="Windows" src="kokoro/img/windows.png" width="20px" height="20px" hspace="2px"/>[![Windows Build Status](https://storage.googleapis.com/spirv-tools/badges/build_status_windows_release.svg)](https://storage.googleapis.com/spirv-tools/badges/build_link_windows_vs2017_release.html)
 
-[More downloads](downloads.md)
+[More downloads](docs/downloads.md)
 
 ## Versioning SPIRV-Tools
 
@@ -59,7 +59,7 @@ version.  An API call reports the software version as a C-style string.
   IDs or types is performed, except to check literal arguments to
   `OpConstant`, `OpSpecConstant`, and `OpSwitch`.
 
-See [`syntax.md`](syntax.md) for the assembly language syntax.
+See [`docs/syntax.md`](docs/syntax.md) for the assembly language syntax.
 
 ### Validator
 
@@ -171,7 +171,7 @@ specific work is tracked via issues and sometimes in one of the
 (To provide feedback on the SPIR-V _specification_, file an issue on the
 [SPIRV-Headers][spirv-headers] GitHub repository.)
 
-See [`projects.md`](projects.md) to see how we use the
+See [`docs/projects.md`](docs/projects.md) to see how we use the
 [GitHub Project
 feature](https://help.github.com/articles/tracking-the-progress-of-your-work-with-projects/)
 to organize planned and in-progress work.

+ 0 - 0
3rdparty/spirv-tools/downloads.md → 3rdparty/spirv-tools/docs/downloads.md


+ 0 - 0
3rdparty/spirv-tools/projects.md → 3rdparty/spirv-tools/docs/projects.md


+ 0 - 0
3rdparty/spirv-tools/syntax.md → 3rdparty/spirv-tools/docs/syntax.md


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

@@ -1 +1 @@
-"v2019.5-dev", "SPIRV-Tools v2019.5-dev v2019.4-51-g1e146e8a"
+"v2019.5-dev", "SPIRV-Tools v2019.5-dev v2019.4-71-g6b072126"

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


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

@@ -29,6 +29,7 @@ kSPV_KHR_device_group,
 kSPV_KHR_float_controls,
 kSPV_KHR_multiview,
 kSPV_KHR_no_integer_wrap_decoration,
+kSPV_KHR_physical_storage_buffer,
 kSPV_KHR_post_depth_coverage,
 kSPV_KHR_shader_atomic_counter_ops,
 kSPV_KHR_shader_ballot,

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

@@ -97,7 +97,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_EXT_descriptor_indexing
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_fully_covered[] = {spvtools::Extension::kSPV_EXT_fragment_fully_covered};
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate[] = {spvtools::Extension::kSPV_EXT_fragment_invocation_density, spvtools::Extension::kSPV_NV_shading_rate};
 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_EXT_physical_storage_buffer[] = {spvtools::Extension::kSPV_EXT_physical_storage_buffer};
+static const spvtools::Extension pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer[] = {spvtools::Extension::kSPV_EXT_physical_storage_buffer, spvtools::Extension::kSPV_KHR_physical_storage_buffer};
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_stencil_export[] = {spvtools::Extension::kSPV_EXT_shader_stencil_export};
 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};
@@ -267,8 +267,8 @@ static const spv_operand_desc_t pygen_variable_AddressingModelEntries[] = {
   {"Logical", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"Physical32", 1, 1, pygen_variable_caps_Addresses, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"Physical64", 2, 1, pygen_variable_caps_Addresses, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
-  {"PhysicalStorageBuffer64", 5348, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 1, pygen_variable_exts_SPV_EXT_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
-  {"PhysicalStorageBuffer64EXT", 5348, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 1, pygen_variable_exts_SPV_EXT_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}
+  {"PhysicalStorageBuffer64", 5348, 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},
+  {"PhysicalStorageBuffer64EXT", 5348, 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}
 };
 
 static const spv_operand_desc_t pygen_variable_MemoryModelEntries[] = {
@@ -358,8 +358,8 @@ static const spv_operand_desc_t pygen_variable_StorageClassEntries[] = {
   {"HitAttributeNV", 5339, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
   {"IncomingRayPayloadNV", 5342, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
   {"ShaderRecordBufferNV", 5343, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
-  {"PhysicalStorageBuffer", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 1, pygen_variable_exts_SPV_EXT_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
-  {"PhysicalStorageBufferEXT", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 1, pygen_variable_exts_SPV_EXT_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 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}
 };
 
 static const spv_operand_desc_t pygen_variable_DimEntries[] = {
@@ -561,10 +561,10 @@ static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
   {"PerVertexNV", 5285, 1, pygen_variable_caps_FragmentBarycentricNV, 1, pygen_variable_exts_SPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
   {"NonUniform", 5300, 1, pygen_variable_caps_ShaderNonUniform, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"NonUniformEXT", 5300, 1, pygen_variable_caps_ShaderNonUniform, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
-  {"RestrictPointer", 5355, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 1, pygen_variable_exts_SPV_EXT_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
-  {"RestrictPointerEXT", 5355, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 1, pygen_variable_exts_SPV_EXT_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
-  {"AliasedPointer", 5356, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 1, pygen_variable_exts_SPV_EXT_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
-  {"AliasedPointerEXT", 5356, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 1, pygen_variable_exts_SPV_EXT_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
+  {"RestrictPointer", 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},
+  {"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},
   {"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},
@@ -846,8 +846,8 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
   {"VulkanMemoryModelKHR", 5345, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_vulkan_memory_model, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"VulkanMemoryModelDeviceScope", 5346, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_vulkan_memory_model, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"VulkanMemoryModelDeviceScopeKHR", 5346, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_vulkan_memory_model, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
-  {"PhysicalStorageBufferAddresses", 5347, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
-  {"PhysicalStorageBufferAddressesEXT", 5347, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
+  {"PhysicalStorageBufferAddresses", 5347, 1, pygen_variable_caps_Shader, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
+  {"PhysicalStorageBufferAddressesEXT", 5347, 1, pygen_variable_caps_Shader, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"ComputeDerivativeGroupLinearNV", 5350, 0, nullptr, 1, pygen_variable_exts_SPV_NV_compute_shader_derivatives, {}, 0xffffffffu, 0xffffffffu},
   {"CooperativeMatrixNV", 5357, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_NV_cooperative_matrix, {}, 0xffffffffu, 0xffffffffu},
   {"FragmentShaderSampleInterlockEXT", 5363, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu},

+ 5 - 0
3rdparty/spirv-tools/include/spirv-tools/libspirv.h

@@ -612,6 +612,11 @@ SPIRV_TOOLS_EXPORT spv_fuzzer_options spvFuzzerOptionsCreate();
 // Destroys the given fuzzer options object.
 SPIRV_TOOLS_EXPORT void spvFuzzerOptionsDestroy(spv_fuzzer_options options);
 
+// Enables running the validator after every transformation is applied during
+// a replay.
+SPIRV_TOOLS_EXPORT void spvFuzzerOptionsEnableReplayValidation(
+    spv_fuzzer_options options);
+
 // Sets the seed with which the random number generator used by the fuzzer
 // should be initialized.
 SPIRV_TOOLS_EXPORT void spvFuzzerOptionsSetRandomSeed(

+ 5 - 0
3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp

@@ -214,6 +214,11 @@ class FuzzerOptions {
     return options_;
   }
 
+  // See spvFuzzerOptionsEnableReplayValidation.
+  void enable_replay_validation() {
+    spvFuzzerOptionsEnableReplayValidation(options_);
+  }
+
   // See spvFuzzerOptionsSetRandomSeed.
   void set_random_seed(uint32_t seed) {
     spvFuzzerOptionsSetRandomSeed(options_, seed);

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

@@ -13,6 +13,9 @@
 # limitations under the License.
 
 if(SPIRV_BUILD_FUZZER)
+
+  file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/protobufs)
+
   set(PROTOBUF_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/protobufs/spvtoolsfuzz.proto)
 
   add_custom_command(
@@ -34,6 +37,7 @@ if(SPIRV_BUILD_FUZZER)
         fuzzer_pass_add_dead_breaks.h
         fuzzer_pass_add_dead_continues.h
         fuzzer_pass_add_useful_constructs.h
+        fuzzer_pass_apply_id_synonyms.h
         fuzzer_pass_copy_objects.h
         fuzzer_pass_obfuscate_constants.h
         fuzzer_pass_permute_blocks.h
@@ -58,6 +62,7 @@ if(SPIRV_BUILD_FUZZER)
         transformation_move_block_down.h
         transformation_replace_boolean_constant_with_constant_binary.h
         transformation_replace_constant_with_uniform.h
+          transformation_replace_id_with_synonym.h
         transformation_split_block.h
         uniform_buffer_element_descriptor.h
         ${CMAKE_CURRENT_BINARY_DIR}/protobufs/spvtoolsfuzz.pb.h
@@ -70,6 +75,7 @@ if(SPIRV_BUILD_FUZZER)
         fuzzer_pass_add_dead_breaks.cpp
         fuzzer_pass_add_dead_continues.cpp
         fuzzer_pass_add_useful_constructs.cpp
+        fuzzer_pass_apply_id_synonyms.cpp
         fuzzer_pass_copy_objects.cpp
         fuzzer_pass_obfuscate_constants.cpp
         fuzzer_pass_permute_blocks.cpp
@@ -93,6 +99,7 @@ if(SPIRV_BUILD_FUZZER)
         transformation_move_block_down.cpp
         transformation_replace_boolean_constant_with_constant_binary.cpp
         transformation_replace_constant_with_uniform.cpp
+        transformation_replace_id_with_synonym.cpp
         transformation_split_block.cpp
         uniform_buffer_element_descriptor.cpp
         ${CMAKE_CURRENT_BINARY_DIR}/protobufs/spvtoolsfuzz.pb.cc

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

@@ -22,6 +22,7 @@
 #include "source/fuzz/fuzzer_pass_add_dead_breaks.h"
 #include "source/fuzz/fuzzer_pass_add_dead_continues.h"
 #include "source/fuzz/fuzzer_pass_add_useful_constructs.h"
+#include "source/fuzz/fuzzer_pass_apply_id_synonyms.h"
 #include "source/fuzz/fuzzer_pass_copy_objects.h"
 #include "source/fuzz/fuzzer_pass_obfuscate_constants.h"
 #include "source/fuzz/fuzzer_pass_permute_blocks.h"
@@ -111,6 +112,9 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
   FuzzerPassCopyObjects(ir_context.get(), &fact_manager, &fuzzer_context,
                         transformation_sequence_out)
       .Apply();
+  FuzzerPassApplyIdSynonyms(ir_context.get(), &fact_manager, &fuzzer_context,
+                            transformation_sequence_out)
+      .Apply();
   FuzzerPassSplitBlocks(ir_context.get(), &fact_manager, &fuzzer_context,
                         transformation_sequence_out)
       .Apply();

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

@@ -29,6 +29,7 @@ const uint32_t kDefaultChanceOfAddingDeadContinue = 20;
 const uint32_t kDefaultChanceOfCopyingObject = 20;
 const uint32_t kDefaultChanceOfMovingBlockDown = 25;
 const uint32_t kDefaultChanceOfObfuscatingConstant = 20;
+const uint32_t kDefaultChanceOfReplacingIdWithSynonym = 20;
 const uint32_t kDefaultChanceOfSplittingBlock = 20;
 
 // Default functions for controlling how deep to go during recursive
@@ -52,6 +53,8 @@ FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
       chance_of_copying_object_(kDefaultChanceOfCopyingObject),
       chance_of_moving_block_down_(kDefaultChanceOfMovingBlockDown),
       chance_of_obfuscating_constant_(kDefaultChanceOfObfuscatingConstant),
+      chance_of_replacing_id_with_synonym_(
+          kDefaultChanceOfReplacingIdWithSynonym),
       chance_of_splitting_block_(kDefaultChanceOfSplittingBlock),
       go_deeper_in_constant_obfuscation_(
           kDefaultGoDeeperInConstantObfuscation) {}

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

@@ -66,6 +66,9 @@ class FuzzerContext {
   uint32_t GetChanceOfObfuscatingConstant() {
     return chance_of_obfuscating_constant_;
   }
+  uint32_t GetChanceOfReplacingIdWithSynonym() {
+    return chance_of_replacing_id_with_synonym_;
+  }
   uint32_t GetChanceOfSplittingBlock() { return chance_of_splitting_block_; }
 
   // Functions to control how deeply to recurse.
@@ -87,6 +90,7 @@ class FuzzerContext {
   uint32_t chance_of_copying_object_;
   uint32_t chance_of_moving_block_down_;
   uint32_t chance_of_obfuscating_constant_;
+  uint32_t chance_of_replacing_id_with_synonym_;
   uint32_t chance_of_splitting_block_;
 
   // Functions to determine with what probability to go deeper when generating

+ 3 - 3
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.cpp

@@ -47,9 +47,9 @@ void FuzzerPassAddDeadBreaks::Apply() {
     // ones that turn out to be no good.
     for (auto& block : function) {
       for (auto merge_block_id : merge_block_ids) {
-        // TODO(afd): right now we completely ignore OpPhi instructions at
-        //  merge blocks.  This will lead to interesting opportunities being
-        //  missed.
+        // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2856): right
+        //  now we completely ignore OpPhi instructions at merge blocks.  This
+        //  will lead to interesting opportunities being missed.
         auto candidate_transformation = TransformationAddDeadBreak(
             block.id(), merge_block_id, GetFuzzerContext()->ChooseEven(), {});
         if (candidate_transformation.IsApplicable(GetIRContext(),

+ 3 - 3
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.cpp

@@ -36,9 +36,9 @@ void FuzzerPassAddDeadContinues::Apply() {
       // node turns out to be inappropriate (e.g. by not being in a loop) the
       // precondition for the transformation will fail and it will be ignored.
       //
-      // TODO(afd): right now we completely ignore OpPhi instructions at
-      //  merge blocks.  This will lead to interesting opportunities being
-      //  missed.
+      // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2856): right
+      //  now we completely ignore OpPhi instructions at continue targets.
+      //  This will lead to interesting opportunities being missed.
       auto candidate_transformation = TransformationAddDeadContinue(
           block.id(), GetFuzzerContext()->ChooseEven(), {});
       // Probabilistically decide whether to apply the transformation in the

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

@@ -0,0 +1,108 @@
+// Copyright (c) 2019 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/fuzz/fuzzer_pass_apply_id_synonyms.h"
+
+#include "source/fuzz/id_use_descriptor.h"
+#include "source/fuzz/transformation_replace_id_with_synonym.h"
+
+namespace spvtools {
+namespace fuzz {
+
+FuzzerPassApplyIdSynonyms::FuzzerPassApplyIdSynonyms(
+    opt::IRContext* ir_context, FactManager* fact_manager,
+    FuzzerContext* fuzzer_context,
+    protobufs::TransformationSequence* transformations)
+    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+
+FuzzerPassApplyIdSynonyms::~FuzzerPassApplyIdSynonyms() = default;
+
+void FuzzerPassApplyIdSynonyms::Apply() {
+  std::vector<TransformationReplaceIdWithSynonym> transformations_to_apply;
+
+  for (auto id_with_known_synonyms :
+       GetFactManager()->GetIdsForWhichSynonymsAreKnown()) {
+    GetIRContext()->get_def_use_mgr()->ForEachUse(
+        id_with_known_synonyms,
+        [this, id_with_known_synonyms, &transformations_to_apply](
+            opt::Instruction* use_inst, uint32_t use_index) -> void {
+          auto block_containing_use = GetIRContext()->get_instr_block(use_inst);
+          // The use might not be in a block; e.g. it could be a decoration.
+          if (!block_containing_use) {
+            return;
+          }
+          if (!GetFuzzerContext()->ChoosePercentage(
+                  GetFuzzerContext()->GetChanceOfReplacingIdWithSynonym())) {
+            return;
+          }
+
+          std::vector<const protobufs::DataDescriptor*> synonyms_to_try;
+          for (auto& data_descriptor :
+               GetFactManager()->GetSynonymsForId(id_with_known_synonyms)) {
+            synonyms_to_try.push_back(&data_descriptor);
+          }
+          while (!synonyms_to_try.empty()) {
+            auto synonym_index =
+                GetFuzzerContext()->RandomIndex(synonyms_to_try);
+            auto synonym_to_try = synonyms_to_try[synonym_index];
+            synonyms_to_try.erase(synonyms_to_try.begin() + synonym_index);
+            assert(synonym_to_try->index().empty() &&
+                   "Right now we only support id == id synonyms; supporting "
+                   "e.g. id == index-into-vector will come later");
+
+            if (!TransformationReplaceIdWithSynonym::
+                    ReplacingUseWithSynonymIsOk(GetIRContext(), use_inst,
+                                                use_index, *synonym_to_try)) {
+              continue;
+            }
+
+            // |use_index| is the absolute index of the operand.  We require
+            // the index of the operand restricted to input operands only, so
+            // we subtract the number of non-input operands from |use_index|.
+            uint32_t number_of_non_input_operands =
+                use_inst->NumOperands() - use_inst->NumInOperands();
+            TransformationReplaceIdWithSynonym replace_id_transformation(
+                transformation::MakeIdUseDescriptorFromUse(
+                    GetIRContext(), use_inst,
+                    use_index - number_of_non_input_operands),
+                *synonym_to_try, 0);
+            // The transformation should be applicable by construction.
+            assert(replace_id_transformation.IsApplicable(GetIRContext(),
+                                                          *GetFactManager()));
+            // We cannot actually apply the transformation here, as this would
+            // change the analysis results that are being depended on for usage
+            // iteration.  We instead store them up and apply them at the end
+            // of the method.
+            transformations_to_apply.push_back(replace_id_transformation);
+            break;
+          }
+        });
+  }
+
+  for (auto& replace_id_transformation : transformations_to_apply) {
+    // Even though replacing id uses with synonyms may lead to new instructions
+    // (to compute indices into composites), as these instructions will generate
+    // ids, their presence should not affect the id use descriptors that were
+    // computed during the creation of transformations. Thus transformations
+    // should not disable one another.
+    assert(replace_id_transformation.IsApplicable(GetIRContext(),
+                                                  *GetFactManager()));
+    replace_id_transformation.Apply(GetIRContext(), GetFactManager());
+    *GetTransformations()->add_transformation() =
+        replace_id_transformation.ToMessage();
+  }
+}
+
+}  // namespace fuzz
+}  // namespace spvtools

+ 42 - 0
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.h

@@ -0,0 +1,42 @@
+// Copyright (c) 2019 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_FUZZ_FUZZER_PASS_APPLY_ID_SYNONYMS_
+#define SOURCE_FUZZ_FUZZER_PASS_APPLY_ID_SYNONYMS_
+
+#include "source/fuzz/fuzzer_pass.h"
+
+#include "source/opt/ir_context.h"
+
+namespace spvtools {
+namespace fuzz {
+
+// A pass that replaces ids with other ids, or accesses into structures, that
+// are known to hold the same values.
+class FuzzerPassApplyIdSynonyms : public FuzzerPass {
+ public:
+  FuzzerPassApplyIdSynonyms(opt::IRContext* ir_context,
+                            FactManager* fact_manager,
+                            FuzzerContext* fuzzer_context,
+                            protobufs::TransformationSequence* transformations);
+
+  ~FuzzerPassApplyIdSynonyms() override;
+
+  void Apply() override;
+};
+
+}  // namespace fuzz
+}  // namespace spvtools
+
+#endif  // SOURCE_FUZZ_FUZZER_PASS_APPLY_ID_SYNONYMS_

+ 66 - 46
3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp

@@ -205,6 +205,7 @@ opt::BasicBlock::iterator GetIteratorForBaseInstructionAndOffset(
   return nullptr;
 }
 
+// Returns the ids of all successors of |block|
 std::vector<uint32_t> GetSuccessors(opt::BasicBlock* block) {
   std::vector<uint32_t> result;
   switch (block->terminator()->opcode()) {
@@ -226,6 +227,41 @@ std::vector<uint32_t> GetSuccessors(opt::BasicBlock* block) {
   return result;
 }
 
+// The FindBypassedBlocks method and its helpers perform a depth-first search;
+// this struct represents an element of the stack used during depth-first
+// search.
+struct FindBypassedBlocksDfsStackNode {
+  opt::BasicBlock* block;  // The block that is being explored
+  bool handled_merge;  // We visit merge blocks before successors; this field
+                       // tracks whether we have yet processed the merge block
+                       // (if any) associated with the block
+  uint32_t next_successor;  // The next as-yet unexplored successor of this
+                            // block; exploration of a block is complete when
+                            // this field's value reaches the successor count
+};
+
+// Helper method for the depth-first-search routine that collects blocks that a
+// new break or continue control flow graph edge will bypass.
+void HandleSuccessorDuringSearchForBypassedBlocks(
+    opt::BasicBlock* successor, bool new_blocks_will_be_bypassed,
+    std::set<uint32_t>* already_visited,
+    std::set<opt::BasicBlock*>* bypassed_blocks,
+    std::vector<FindBypassedBlocksDfsStackNode>* dfs_stack) {
+  if (already_visited->count(successor->id()) == 0) {
+    // This is a new block; mark it as visited so that we don't regard it as new
+    // in the future, and push it on to the stack for exploration.
+    already_visited->insert(successor->id());
+    dfs_stack->push_back({successor, false, 0});
+    if (new_blocks_will_be_bypassed) {
+      // We are in the region of the control-flow graph consisting of blocks
+      // that the new edge will bypass, so grab this block.
+      bypassed_blocks->insert(successor);
+    }
+  }
+}
+
+// Determines those block that will be bypassed by a break or continue edge from
+// |bb_from| to |bb_to|.
 void FindBypassedBlocks(opt::IRContext* context, opt::BasicBlock* bb_from,
                         opt::BasicBlock* bb_to,
                         std::set<opt::BasicBlock*>* bypassed_blocks) {
@@ -240,51 +276,40 @@ void FindBypassedBlocks(opt::IRContext* context, opt::BasicBlock* bb_from,
   // visited in the sub-search rooted at |bb_from|. (As an optimization, the
   // search terminates as soon as exploration of |bb_from| has completed.)
 
-  // This represents a basic block in a partial state of exploration.  As we
-  // wish to visit merge blocks in advance of regular successors, we track them
-  // separately.
-  struct StackNode {
-    opt::BasicBlock* block;
-    bool handled_merge;
-    std::vector<uint32_t> successors;
-    uint32_t next_successor;
-  };
-
   auto enclosing_function = bb_from->GetParent();
 
   // The set of block ids already visited during search.  We put |bb_to| in
   // there initially so that search automatically backtracks when this block is
   // reached.
-  std::set<uint32_t> visited;
-  visited.insert(bb_to->id());
+  std::set<uint32_t> already_visited;
+  already_visited.insert(bb_to->id());
 
-  // Tracks when we are in the region of blocks that are to be grabbed; we flip
-  // this to 'true' once we reach |bb_from| and have finished searching its
-  // merge block (in the case that it happens to be a header.
-  bool interested = false;
+  // Tracks when we are in the region of blocks that the new edge would bypass;
+  // we flip this to 'true' once we reach |bb_from| and have finished searching
+  // its merge block (in the case that it happens to be a header.
+  bool new_blocks_will_be_bypassed = false;
 
-  std::vector<StackNode> dfs_stack;
+  std::vector<FindBypassedBlocksDfsStackNode> dfs_stack;
   opt::BasicBlock* entry_block = enclosing_function->entry().get();
-  dfs_stack.push_back({entry_block, false, GetSuccessors(entry_block), 0});
+  dfs_stack.push_back({entry_block, false, 0});
   while (!dfs_stack.empty()) {
-    StackNode* node = &dfs_stack.back();
+    auto node_index = dfs_stack.size() - 1;
 
     // First make sure we search the merge block associated ith this block, if
     // there is one.
-    if (!node->handled_merge) {
-      node->handled_merge = true;
-      if (node->block->MergeBlockIdIfAny()) {
-        opt::BasicBlock* merge_block =
-            context->cfg()->block(node->block->MergeBlockIdIfAny());
+    if (!dfs_stack[node_index].handled_merge) {
+      dfs_stack[node_index].handled_merge = true;
+      if (dfs_stack[node_index].block->MergeBlockIdIfAny()) {
+        opt::BasicBlock* merge_block = context->cfg()->block(
+            dfs_stack[node_index].block->MergeBlockIdIfAny());
         // A block can only be the merge block for one header, so this block
         // should only be in |visited| if it is |bb_to|, which we put into
         // |visited| in advance.
-        assert(visited.count(merge_block->id()) == 0 || merge_block == bb_to);
-        if (visited.count(merge_block->id()) == 0) {
-          visited.insert(merge_block->id());
-          dfs_stack.push_back(
-              {merge_block, false, GetSuccessors(merge_block), 0});
-        }
+        assert(already_visited.count(merge_block->id()) == 0 ||
+               merge_block == bb_to);
+        HandleSuccessorDuringSearchForBypassedBlocks(
+            merge_block, new_blocks_will_be_bypassed, &already_visited,
+            bypassed_blocks, &dfs_stack);
       }
       continue;
     }
@@ -292,28 +317,23 @@ void FindBypassedBlocks(opt::IRContext* context, opt::BasicBlock* bb_from,
     // If we find |bb_from|, we are interested in grabbing previously unseen
     // successor blocks (by this point we will have already searched the merge
     // block associated with |bb_from|, if there is one.
-    if (node->block == bb_from) {
-      interested = true;
+    if (dfs_stack[node_index].block == bb_from) {
+      new_blocks_will_be_bypassed = true;
     }
 
     // Consider the next unexplored successor.
-    if (node->next_successor < node->successors.size()) {
-      uint32_t successor_id = node->successors[node->next_successor];
-      if (visited.count(successor_id) == 0) {
-        visited.insert(successor_id);
-        opt::BasicBlock* successor_block = context->cfg()->block(successor_id);
-        if (interested) {
-          // If we're in the region of interest, grab this block.
-          bypassed_blocks->insert(successor_block);
-        }
-        dfs_stack.push_back(
-            {successor_block, false, GetSuccessors(successor_block), 0});
-      }
-      node->next_successor++;
+    auto successors = GetSuccessors(dfs_stack[node_index].block);
+    if (dfs_stack[node_index].next_successor < successors.size()) {
+      HandleSuccessorDuringSearchForBypassedBlocks(
+          context->cfg()->block(
+              successors[dfs_stack[node_index].next_successor]),
+          new_blocks_will_be_bypassed, &already_visited, bypassed_blocks,
+          &dfs_stack);
+      dfs_stack[node_index].next_successor++;
     } else {
       // We have finished exploring |node|.  If it is |bb_from|, we can
       // terminate search -- we have grabbed all the relevant blocks.
-      if (node->block == bb_from) {
+      if (dfs_stack[node_index].block == bb_from) {
         break;
       }
       dfs_stack.pop_back();

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

@@ -78,5 +78,33 @@ protobufs::IdUseDescriptor transformation::MakeIdUseDescriptor(
   return result;
 }
 
+protobufs::IdUseDescriptor transformation::MakeIdUseDescriptorFromUse(
+    opt::IRContext* context, opt::Instruction* inst,
+    uint32_t in_operand_index) {
+  auto in_operand = inst->GetInOperand(in_operand_index);
+  assert(in_operand.type == SPV_OPERAND_TYPE_ID);
+  auto id_of_interest = in_operand.words[0];
+
+  auto block = context->get_instr_block(inst);
+  uint32_t base_instruction_result_id = block->id();
+  uint32_t num_opcodes_to_ignore = 0;
+  for (auto& inst_in_block : *block) {
+    if (inst_in_block.HasResultId()) {
+      base_instruction_result_id = inst_in_block.result_id();
+      num_opcodes_to_ignore = 0;
+    }
+    if (&inst_in_block == inst) {
+      return MakeIdUseDescriptor(id_of_interest, inst->opcode(),
+                                 in_operand_index, base_instruction_result_id,
+                                 num_opcodes_to_ignore);
+    }
+    if (inst_in_block.opcode() == inst->opcode()) {
+      num_opcodes_to_ignore++;
+    }
+  }
+  assert(false && "No matching instruction was found.");
+  return protobufs::IdUseDescriptor();
+}
+
 }  // namespace fuzz
 }  // namespace spvtools

+ 6 - 0
3rdparty/spirv-tools/source/fuzz/id_use_descriptor.h

@@ -35,6 +35,12 @@ protobufs::IdUseDescriptor MakeIdUseDescriptor(
     uint32_t in_operand_index, uint32_t base_instruction_result_id,
     uint32_t num_opcodes_to_ignore);
 
+// Given an id use, represented by the instruction |inst| that uses the id, and
+// the input operand index |in_operand_index| associated with the usage, returns
+// an IdUseDescriptor that represents the use.
+protobufs::IdUseDescriptor MakeIdUseDescriptorFromUse(
+    opt::IRContext* context, opt::Instruction* inst, uint32_t in_operand_index);
+
 }  // namespace transformation
 }  // namespace fuzz
 }  // namespace spvtools

+ 34 - 16
3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto

@@ -172,6 +172,7 @@ message Transformation {
     TransformationReplaceConstantWithUniform replace_constant_with_uniform = 11;
     TransformationAddDeadContinue add_dead_continue = 12;
     TransformationCopyObject copy_object = 13;
+    TransformationReplaceIdWithSynonym replace_id_with_synonym = 14;
     // Add additional option using the next available number.
   }
 }
@@ -325,9 +326,31 @@ message TransformationMoveBlockDown {
   uint32 block_id = 1;
 }
 
+message TransformationReplaceBooleanConstantWithConstantBinary {
+
+  // A transformation to capture replacing a use of a boolean constant with
+  // binary operation on two constant values
+
+  // A descriptor for the boolean constant id we would like to replace
+  IdUseDescriptor id_use_descriptor = 1;
+
+  // Id for the constant to be used on the LHS of the comparision
+  uint32 lhs_id = 2;
+
+  // Id for the constant to be used on the RHS of the comparision
+  uint32 rhs_id = 3;
+
+  // Opcode for binary operator
+  uint32 opcode = 4;
+
+  // Id that will store the result of the binary operation instruction
+  uint32 fresh_id_for_binary_operation = 5;
+
+}
+
 message TransformationReplaceConstantWithUniform {
 
-  // Replaces a use of a constant id with the the result of a load from an
+  // Replaces a use of a constant id with the result of a load from an
   // element of uniform buffer known to hold the same value as the constant
 
   // A descriptor for the id we would like to replace
@@ -344,26 +367,21 @@ message TransformationReplaceConstantWithUniform {
 
 }
 
-message TransformationReplaceBooleanConstantWithConstantBinary {
+message TransformationReplaceIdWithSynonym {
 
-  // A transformation to capture replacing a use of a boolean constant with
-  // binary operation on two constant values
+  // Replaces an id use with something known to be synonymous with that id use,
+  // e.g. because it was obtained via applying OpCopyObject
 
-  // A descriptor for the boolean constant id we would like to replace
+  // Identifies the id use that is to be replaced
   IdUseDescriptor id_use_descriptor = 1;
 
-  // Id for the constant to be used on the LHS of the comparision
-  uint32 lhs_id = 2;
-
-  // Id for the constant to be used on the RHS of the comparision
-  uint32 rhs_id = 3;
-
-  // Opcode for binary operator
-  uint32 opcode = 4;
-
-  // Id that will store the result of the binary operation instruction
-  uint32 fresh_id_for_binary_operation = 5;
+  // Identifies the data with which the id use is expected to be synonymous
+  DataDescriptor data_descriptor = 2;
 
+  // In the case that a temporary is required to express the synonym (e.g. to
+  // obtain an element of a vector, provides a fresh id for the temporary;
+  // should be set to 0 if no temporary is required
+  uint32 fresh_id_for_temporary = 3;
 }
 
 message TransformationSplitBlock {

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

@@ -37,13 +37,18 @@ namespace spvtools {
 namespace fuzz {
 
 struct Replayer::Impl {
-  explicit Impl(spv_target_env env) : target_env(env) {}
+  explicit Impl(spv_target_env env, bool validate)
+      : target_env(env), validate_during_replay(validate) {}
 
   const spv_target_env target_env;  // Target environment.
   MessageConsumer consumer;         // Message consumer.
+
+  const bool validate_during_replay;  // Controls whether the validator should
+                                      // be run after every replay step.
 };
 
-Replayer::Replayer(spv_target_env env) : impl_(MakeUnique<Impl>(env)) {}
+Replayer::Replayer(spv_target_env env, bool validate_during_replay)
+    : impl_(MakeUnique<Impl>(env, validate_during_replay)) {}
 
 Replayer::~Replayer() = default;
 
@@ -80,6 +85,13 @@ Replayer::ReplayerResultStatus Replayer::Run(
       impl_->target_env, impl_->consumer, binary_in.data(), binary_in.size());
   assert(ir_context);
 
+  // For replay validation, we track the last valid SPIR-V binary that was
+  // observed. Initially this is the input binary.
+  std::vector<uint32_t> last_valid_binary;
+  if (impl_->validate_during_replay) {
+    last_valid_binary = binary_in;
+  }
+
   FactManager fact_manager;
   fact_manager.AddFacts(impl_->consumer, initial_facts, ir_context.get());
 
@@ -93,6 +105,23 @@ Replayer::ReplayerResultStatus Replayer::Run(
       // sequence of transformations that were applied.
       transformation->Apply(ir_context.get(), &fact_manager);
       *transformation_sequence_out->add_transformation() = message;
+
+      if (impl_->validate_during_replay) {
+        std::vector<uint32_t> binary_to_validate;
+        ir_context->module()->ToBinary(&binary_to_validate, false);
+
+        // Check whether the latest transformation led to a valid binary.
+        if (!tools.Validate(&binary_to_validate[0],
+                            binary_to_validate.size())) {
+          impl_->consumer(SPV_MSG_INFO, nullptr, {},
+                          "Binary became invalid during replay (set a "
+                          "breakpoint to inspect); stopping.");
+          return Replayer::ReplayerResultStatus::kReplayValidationFailure;
+        }
+
+        // The binary was valid, so it becomes the latest valid binary.
+        last_valid_binary = std::move(binary_to_validate);
+      }
     }
   }
 

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/replayer.h

@@ -33,10 +33,11 @@ class Replayer {
     kComplete,
     kFailedToCreateSpirvToolsInterface,
     kInitialBinaryInvalid,
+    kReplayValidationFailure,
   };
 
   // Constructs a replayer from the given target environment.
-  explicit Replayer(spv_target_env env);
+  explicit Replayer(spv_target_env env, bool validate_during_replay);
 
   // Disables copy/move constructor/assignment operations.
   Replayer(const Replayer&) = delete;

+ 14 - 10
3rdparty/spirv-tools/source/fuzz/shrinker.cpp

@@ -60,16 +60,20 @@ protobufs::TransformationSequence RemoveChunk(
 }  // namespace
 
 struct Shrinker::Impl {
-  explicit Impl(spv_target_env env, uint32_t limit)
-      : target_env(env), step_limit(limit) {}
-
-  const spv_target_env target_env;  // Target environment.
-  MessageConsumer consumer;         // Message consumer.
-  const uint32_t step_limit;        // Step limit for reductions.
+  explicit Impl(spv_target_env env, uint32_t limit, bool validate)
+      : target_env(env), step_limit(limit), validate_during_replay(validate) {}
+
+  const spv_target_env target_env;    // Target environment.
+  MessageConsumer consumer;           // Message consumer.
+  const uint32_t step_limit;          // Step limit for reductions.
+  const bool validate_during_replay;  // Determines whether to check for
+                                      // validity during the replaying of
+                                      // transformations.
 };
 
-Shrinker::Shrinker(spv_target_env env, uint32_t step_limit)
-    : impl_(MakeUnique<Impl>(env, step_limit)) {}
+Shrinker::Shrinker(spv_target_env env, uint32_t step_limit,
+                   bool validate_during_replay)
+    : impl_(MakeUnique<Impl>(env, step_limit, validate_during_replay)) {}
 
 Shrinker::~Shrinker() = default;
 
@@ -109,7 +113,7 @@ Shrinker::ShrinkerResultStatus Shrinker::Run(
   // succeeds, (b) get the binary that results from running these
   // transformations, and (c) get the subsequence of the initial transformations
   // that actually apply (in principle this could be a strict subsequence).
-  if (Replayer(impl_->target_env)
+  if (Replayer(impl_->target_env, impl_->validate_during_replay)
           .Run(binary_in, initial_facts, transformation_sequence_in,
                &current_best_binary, &current_best_transformations) !=
       Replayer::ReplayerResultStatus::kComplete) {
@@ -180,7 +184,7 @@ Shrinker::ShrinkerResultStatus Shrinker::Run(
       // transformations inapplicable.
       std::vector<uint32_t> next_binary;
       protobufs::TransformationSequence next_transformation_sequence;
-      if (Replayer(impl_->target_env)
+      if (Replayer(impl_->target_env, false)
               .Run(binary_in, initial_facts, transformations_with_chunk_removed,
                    &next_binary, &next_transformation_sequence) !=
           Replayer::ReplayerResultStatus::kComplete) {

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/shrinker.h

@@ -50,7 +50,8 @@ class Shrinker {
       const std::vector<uint32_t>& binary, uint32_t counter)>;
 
   // Constructs a shrinker from the given target environment.
-  Shrinker(spv_target_env env, uint32_t step_limit);
+  Shrinker(spv_target_env env, uint32_t step_limit,
+           bool validate_during_replay);
 
   // Disables copy/move constructor/assignment operations.
   Shrinker(const Shrinker&) = delete;

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

@@ -29,6 +29,7 @@
 #include "transformation_move_block_down.h"
 #include "transformation_replace_boolean_constant_with_constant_binary.h"
 #include "transformation_replace_constant_with_uniform.h"
+#include "transformation_replace_id_with_synonym.h"
 #include "transformation_split_block.h"
 
 namespace spvtools {
@@ -72,6 +73,9 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
         kReplaceConstantWithUniform:
       return MakeUnique<TransformationReplaceConstantWithUniform>(
           message.replace_constant_with_uniform());
+    case protobufs::Transformation::TransformationCase::kReplaceIdWithSynonym:
+      return MakeUnique<TransformationReplaceIdWithSynonym>(
+          message.replace_id_with_synonym());
     case protobufs::Transformation::TransformationCase::kSplitBlock:
       return MakeUnique<TransformationSplitBlock>(message.split_block());
     case protobufs::Transformation::TRANSFORMATION_NOT_SET:

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

@@ -0,0 +1,155 @@
+// Copyright (c) 2019 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/fuzz/transformation_replace_id_with_synonym.h"
+
+#include <algorithm>
+
+#include "source/fuzz/data_descriptor.h"
+#include "source/fuzz/fuzzer_util.h"
+#include "source/fuzz/id_use_descriptor.h"
+
+namespace spvtools {
+namespace fuzz {
+
+TransformationReplaceIdWithSynonym::TransformationReplaceIdWithSynonym(
+    const spvtools::fuzz::protobufs::TransformationReplaceIdWithSynonym&
+        message)
+    : message_(message) {}
+
+TransformationReplaceIdWithSynonym::TransformationReplaceIdWithSynonym(
+    protobufs::IdUseDescriptor id_use_descriptor,
+    protobufs::DataDescriptor data_descriptor,
+    uint32_t fresh_id_for_temporary) {
+  assert(fresh_id_for_temporary == 0 && data_descriptor.index().size() == 0 &&
+         "At present we do not support making an id that is synonymous with an "
+         "index into a composite.");
+  *message_.mutable_id_use_descriptor() = std::move(id_use_descriptor);
+  *message_.mutable_data_descriptor() = std::move(data_descriptor);
+  message_.set_fresh_id_for_temporary(fresh_id_for_temporary);
+}
+
+bool TransformationReplaceIdWithSynonym::IsApplicable(
+    spvtools::opt::IRContext* context,
+    const spvtools::fuzz::FactManager& fact_manager) const {
+  auto id_of_interest = message_.id_use_descriptor().id_of_interest();
+
+  // Does the fact manager know about the synonym?
+  if (fact_manager.GetIdsForWhichSynonymsAreKnown().count(id_of_interest) ==
+      0) {
+    return false;
+  }
+
+  auto available_synonyms = fact_manager.GetSynonymsForId(id_of_interest);
+  if (std::find_if(available_synonyms.begin(), available_synonyms.end(),
+                   [this](protobufs::DataDescriptor dd) -> bool {
+                     return DataDescriptorEquals()(&dd,
+                                                   &message_.data_descriptor());
+                   }) == available_synonyms.end()) {
+    return false;
+  }
+
+  auto use_instruction =
+      transformation::FindInstruction(message_.id_use_descriptor(), context);
+  if (!use_instruction) {
+    return false;
+  }
+
+  if (!ReplacingUseWithSynonymIsOk(
+          context, use_instruction,
+          message_.id_use_descriptor().in_operand_index(),
+          message_.data_descriptor())) {
+    return false;
+  }
+
+  assert(message_.fresh_id_for_temporary() == 0);
+  assert(message_.data_descriptor().index().empty());
+
+  return true;
+}
+
+void TransformationReplaceIdWithSynonym::Apply(
+    spvtools::opt::IRContext* context,
+    spvtools::fuzz::FactManager* /*unused*/) const {
+  assert(message_.data_descriptor().index().empty());
+  auto instruction_to_change =
+      transformation::FindInstruction(message_.id_use_descriptor(), context);
+  instruction_to_change->SetInOperand(
+      message_.id_use_descriptor().in_operand_index(),
+      {message_.data_descriptor().object()});
+  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+}
+
+protobufs::Transformation TransformationReplaceIdWithSynonym::ToMessage()
+    const {
+  protobufs::Transformation result;
+  *result.mutable_replace_id_with_synonym() = message_;
+  return result;
+}
+
+bool TransformationReplaceIdWithSynonym::ReplacingUseWithSynonymIsOk(
+    opt::IRContext* context, opt::Instruction* use_instruction,
+    uint32_t use_in_operand_index, const protobufs::DataDescriptor& synonym) {
+  auto defining_instruction =
+      context->get_def_use_mgr()->GetDef(synonym.object());
+
+  if (use_instruction == defining_instruction) {
+    // If we have an instruction:
+    //   %a = OpCopyObject %t %b
+    // then we know %a and %b are synonymous, but we do *not* want to turn
+    // this into:
+    //   %a = OpCopyObject %t %a
+    // We require this special case because an instruction dominates itself.
+    return false;
+  }
+
+  if (use_instruction->opcode() == SpvOpAccessChain &&
+      use_in_operand_index > 0) {
+    // This is an access chain index.  If the object being accessed has
+    // pointer-to-struct type then we cannot replace the use with a synonym, as
+    // the use needs to be an OpConstant.
+    auto object_being_accessed = context->get_def_use_mgr()->GetDef(
+        use_instruction->GetSingleWordInOperand(0));
+    auto pointer_type =
+        context->get_type_mgr()->GetType(object_being_accessed->type_id());
+    assert(pointer_type->AsPointer());
+    if (pointer_type->AsPointer()->pointee_type()->AsStruct()) {
+      return false;
+    }
+  }
+
+  // We now need to check that replacing the use with the synonym will respect
+  // dominance rules - i.e. the synonym needs to dominate the use.
+  auto dominator_analysis = context->GetDominatorAnalysis(
+      context->get_instr_block(use_instruction)->GetParent());
+  if (use_instruction->opcode() == SpvOpPhi) {
+    // In the case where the use is an operand to OpPhi, it is actually the
+    // *parent* block associated with the operand that must be dominated by the
+    // synonym.
+    auto parent_block =
+        use_instruction->GetSingleWordInOperand(use_in_operand_index + 1);
+    if (!dominator_analysis->Dominates(
+            context->get_instr_block(defining_instruction)->id(),
+            parent_block)) {
+      return false;
+    }
+  } else if (!dominator_analysis->Dominates(defining_instruction,
+                                            use_instruction)) {
+    return false;
+  }
+  return true;
+}
+
+}  // namespace fuzz
+}  // namespace spvtools

+ 72 - 0
3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.h

@@ -0,0 +1,72 @@
+// Copyright (c) 2019 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_FUZZ_TRANSFORMATION_REPLACE_ID_WITH_SYNONYM_H_
+#define SOURCE_FUZZ_TRANSFORMATION_REPLACE_ID_WITH_SYNONYM_H_
+
+#include "source/fuzz/fact_manager.h"
+#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/fuzz/transformation.h"
+#include "source/opt/ir_context.h"
+
+namespace spvtools {
+namespace fuzz {
+
+class TransformationReplaceIdWithSynonym : public Transformation {
+ public:
+  explicit TransformationReplaceIdWithSynonym(
+      const protobufs::TransformationReplaceIdWithSynonym& message);
+
+  TransformationReplaceIdWithSynonym(
+      protobufs::IdUseDescriptor id_use_descriptor,
+      protobufs::DataDescriptor data_descriptor,
+      uint32_t fresh_id_for_temporary);
+
+  // - The fact manager must know that the id identified by
+  //   |message_.id_use_descriptor| is synonomous with
+  //   |message_.data_descriptor|.
+  // - Replacing the id in |message_.id_use_descriptor| by the synonym in
+  //   |message_.data_descriptor| must respect SPIR-V's rules about uses being
+  //   dominated by their definitions.
+  // - The id must not be an index into an access chain whose base object has
+  //   struct type, as such indices must be constants.
+  // - |fresh_id_for_temporary| must be 0.
+  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2855): the
+  //  motivation for the temporary is to support the case where an id is
+  //  synonymous with an element of a composite.  Until support for that is
+  //  implemented, 0 records that no temporary is needed.
+  bool IsApplicable(opt::IRContext* context,
+                    const FactManager& fact_manager) const override;
+
+  // Replaces the use identified by |message_.id_use_descriptor| with the
+  // synonymous id identified by |message_.data_descriptor|.
+  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2855): in due
+  //  course it will also be necessary to add an additional instruction to pull
+  //  the synonym out of a composite.
+  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+
+  protobufs::Transformation ToMessage() const override;
+
+  static bool ReplacingUseWithSynonymIsOk(
+      opt::IRContext* context, opt::Instruction* use_instruction,
+      uint32_t use_in_operand_index, const protobufs::DataDescriptor& synonym);
+
+ private:
+  protobufs::TransformationReplaceIdWithSynonym message_;
+};
+
+}  // namespace fuzz
+}  // namespace spvtools
+
+#endif  // SOURCE_FUZZ_TRANSFORMATION_REPLACE_ID_WITH_SYNONYM_H_

+ 10 - 13
3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp

@@ -306,8 +306,7 @@ CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct(
   analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
   const analysis::Constant* last_access =
       const_mgr->FindDeclaredConstant(memory_object->AccessChain().back());
-  if (!last_access ||
-      (!last_access->AsIntConstant() && !last_access->AsNullConstant())) {
+  if (!last_access || !last_access->type()->AsInteger()) {
     return nullptr;
   }
 
@@ -340,7 +339,7 @@ CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct(
 
     last_access =
         const_mgr->FindDeclaredConstant(member_object->AccessChain().back());
-    if (!last_access || !last_access->AsIntConstant()) {
+    if (!last_access || !last_access->type()->AsInteger()) {
       return nullptr;
     }
 
@@ -368,8 +367,7 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) {
   } else if (const analysis::Array* array_type = result_type->AsArray()) {
     const analysis::Constant* length_const =
         const_mgr->FindDeclaredConstant(array_type->LengthId());
-    assert(length_const->AsIntConstant());
-    number_of_elements = length_const->AsIntConstant()->GetU32();
+    number_of_elements = length_const->GetU32();
   } else if (const analysis::Vector* vector_type = result_type->AsVector()) {
     number_of_elements = vector_type->element_count();
   } else if (const analysis::Matrix* matrix_type = result_type->AsMatrix()) {
@@ -401,7 +399,7 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) {
 
   const analysis::Constant* last_access =
       const_mgr->FindDeclaredConstant(memory_object->AccessChain().back());
-  if (!last_access || !last_access->AsIntConstant()) {
+  if (!last_access || !last_access->type()->AsInteger()) {
     return nullptr;
   }
 
@@ -449,7 +447,7 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) {
     const analysis::Constant* current_last_access =
         const_mgr->FindDeclaredConstant(
             current_memory_object->AccessChain().back());
-    if (!current_last_access || !current_last_access->AsIntConstant()) {
+    if (!current_last_access || !current_last_access->type()->AsInteger()) {
       return nullptr;
     }
 
@@ -513,7 +511,7 @@ bool CopyPropagateArrays::CanUpdateUses(Instruction* original_ptr_inst,
           const analysis::Constant* index_const =
               const_mgr->FindDeclaredConstant(use->GetSingleWordInOperand(i));
           if (index_const) {
-            access_chain.push_back(index_const->AsIntConstant()->GetU32());
+            access_chain.push_back(index_const->GetU32());
           } else {
             // Variable index means the type is a type where every element
             // is the same type.  Use element 0 to get the type.
@@ -613,7 +611,7 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst,
           const analysis::Constant* index_const =
               const_mgr->FindDeclaredConstant(use->GetSingleWordInOperand(i));
           if (index_const) {
-            access_chain.push_back(index_const->AsIntConstant()->GetU32());
+            access_chain.push_back(index_const->GetU32());
           } else {
             // Variable index means the type is an type where every element
             // is the same type.  Use element 0 to get the type.
@@ -749,8 +747,8 @@ uint32_t CopyPropagateArrays::MemoryObject::GetNumberOfMembers() {
     const analysis::Constant* length_const =
         context->get_constant_mgr()->FindDeclaredConstant(
             array_type->LengthId());
-    assert(length_const->AsIntConstant());
-    return length_const->AsIntConstant()->GetU32();
+    assert(length_const->type()->AsInteger());
+    return length_const->GetU32();
   } else if (const analysis::Vector* vector_type = type->AsVector()) {
     return vector_type->element_count();
   } else if (const analysis::Matrix* matrix_type = type->AsMatrix()) {
@@ -776,8 +774,7 @@ std::vector<uint32_t> CopyPropagateArrays::MemoryObject::GetAccessIds() const {
     if (!element_index_const) {
       access_indices.push_back(0);
     } else {
-      assert(element_index_const->AsIntConstant());
-      access_indices.push_back(element_index_const->AsIntConstant()->GetU32());
+      access_indices.push_back(element_index_const->GetU32());
     }
   }
   return access_indices;

+ 4 - 3
3rdparty/spirv-tools/source/opt/function.cpp

@@ -13,13 +13,14 @@
 // limitations under the License.
 
 #include "source/opt/function.h"
-#include "function.h"
-#include "ir_context.h"
 
-#include <source/util/bit_vector.h>
 #include <ostream>
 #include <sstream>
 
+#include "function.h"
+#include "ir_context.h"
+#include "source/util/bit_vector.h"
+
 namespace spvtools {
 namespace opt {
 

+ 50 - 16
3rdparty/spirv-tools/source/opt/ir_builder.h

@@ -59,27 +59,43 @@ class InstructionBuilder {
                            preserved_analyses) {}
 
   Instruction* AddNullaryOp(uint32_t type_id, SpvOp opcode) {
-    // TODO(1841): Handle id overflow.
-    std::unique_ptr<Instruction> newUnOp(new Instruction(
-        GetContext(), opcode, type_id,
-        opcode == SpvOpReturn ? 0 : GetContext()->TakeNextId(), {}));
-    return AddInstruction(std::move(newUnOp));
+    uint32_t result_id = 0;
+    if (type_id != 0) {
+      result_id = GetContext()->TakeNextId();
+      if (result_id == 0) {
+        return nullptr;
+      }
+    }
+    std::unique_ptr<Instruction> new_inst(
+        new Instruction(GetContext(), opcode, type_id, result_id, {}));
+    return AddInstruction(std::move(new_inst));
   }
 
   Instruction* AddUnaryOp(uint32_t type_id, SpvOp opcode, uint32_t operand1) {
-    // TODO(1841): Handle id overflow.
+    uint32_t result_id = 0;
+    if (type_id != 0) {
+      result_id = GetContext()->TakeNextId();
+      if (result_id == 0) {
+        return nullptr;
+      }
+    }
     std::unique_ptr<Instruction> newUnOp(new Instruction(
-        GetContext(), opcode, type_id, GetContext()->TakeNextId(),
+        GetContext(), opcode, type_id, result_id,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand1}}}));
     return AddInstruction(std::move(newUnOp));
   }
 
   Instruction* AddBinaryOp(uint32_t type_id, SpvOp opcode, uint32_t operand1,
                            uint32_t operand2) {
-    // TODO(1841): Handle id overflow.
+    uint32_t result_id = 0;
+    if (type_id != 0) {
+      result_id = GetContext()->TakeNextId();
+      if (result_id == 0) {
+        return nullptr;
+      }
+    }
     std::unique_ptr<Instruction> newBinOp(new Instruction(
-        GetContext(), opcode, type_id,
-        opcode == SpvOpStore ? 0 : GetContext()->TakeNextId(),
+        GetContext(), opcode, type_id, opcode == SpvOpStore ? 0 : result_id,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand1}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand2}}}));
     return AddInstruction(std::move(newBinOp));
@@ -87,9 +103,15 @@ class InstructionBuilder {
 
   Instruction* AddTernaryOp(uint32_t type_id, SpvOp opcode, uint32_t operand1,
                             uint32_t operand2, uint32_t operand3) {
-    // TODO(1841): Handle id overflow.
+    uint32_t result_id = 0;
+    if (type_id != 0) {
+      result_id = GetContext()->TakeNextId();
+      if (result_id == 0) {
+        return nullptr;
+      }
+    }
     std::unique_ptr<Instruction> newTernOp(new Instruction(
-        GetContext(), opcode, type_id, GetContext()->TakeNextId(),
+        GetContext(), opcode, type_id, result_id,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand1}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand2}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand3}}}));
@@ -99,9 +121,15 @@ class InstructionBuilder {
   Instruction* AddQuadOp(uint32_t type_id, SpvOp opcode, uint32_t operand1,
                          uint32_t operand2, uint32_t operand3,
                          uint32_t operand4) {
-    // TODO(1841): Handle id overflow.
+    uint32_t result_id = 0;
+    if (type_id != 0) {
+      result_id = GetContext()->TakeNextId();
+      if (result_id == 0) {
+        return nullptr;
+      }
+    }
     std::unique_ptr<Instruction> newQuadOp(new Instruction(
-        GetContext(), opcode, type_id, GetContext()->TakeNextId(),
+        GetContext(), opcode, type_id, result_id,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand1}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand2}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand3}},
@@ -111,9 +139,15 @@ class InstructionBuilder {
 
   Instruction* AddIdLiteralOp(uint32_t type_id, SpvOp opcode, uint32_t id,
                               uint32_t uliteral) {
-    // TODO(1841): Handle id overflow.
+    uint32_t result_id = 0;
+    if (type_id != 0) {
+      result_id = GetContext()->TakeNextId();
+      if (result_id == 0) {
+        return nullptr;
+      }
+    }
     std::unique_ptr<Instruction> newBinOp(new Instruction(
-        GetContext(), opcode, type_id, GetContext()->TakeNextId(),
+        GetContext(), opcode, type_id, result_id,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {uliteral}}}));
     return AddInstruction(std::move(newBinOp));

+ 1 - 1
3rdparty/spirv-tools/source/opt/optimizer.cpp

@@ -21,12 +21,12 @@
 #include <utility>
 #include <vector>
 
-#include <source/spirv_optimizer_options.h>
 #include "source/opt/build_module.h"
 #include "source/opt/graphics_robust_access_pass.h"
 #include "source/opt/log.h"
 #include "source/opt/pass_manager.h"
 #include "source/opt/passes.h"
+#include "source/spirv_optimizer_options.h"
 #include "source/util/make_unique.h"
 #include "source/util/string_utils.h"
 

+ 18 - 1
3rdparty/spirv-tools/source/opt/wrap_opkill.cpp

@@ -59,7 +59,14 @@ bool WrapOpKill::ReplaceWithFunctionCall(Instruction* inst) {
   if (ir_builder.AddFunctionCall(GetVoidTypeId(), func_id, {}) == nullptr) {
     return false;
   }
-  ir_builder.AddUnreachable();
+
+  uint32_t return_type_id = GetOwningFunctionsReturnType(inst);
+  if (return_type_id != GetVoidTypeId()) {
+    Instruction* undef = ir_builder.AddNullaryOp(return_type_id, SpvOpUndef);
+    ir_builder.AddUnaryOp(0, SpvOpReturnValue, undef->result_id());
+  } else {
+    ir_builder.AddNullaryOp(0, SpvOpReturn);
+  }
   context()->KillInst(inst);
   return true;
 }
@@ -147,5 +154,15 @@ uint32_t WrapOpKill::GetOpKillFuncId() {
   return opkill_function_->result_id();
 }
 
+uint32_t WrapOpKill::GetOwningFunctionsReturnType(Instruction* inst) {
+  BasicBlock* bb = context()->get_instr_block(inst);
+  if (bb == nullptr) {
+    return 0;
+  }
+
+  Function* func = bb->GetParent();
+  return func->type_id();
+}
+
 }  // namespace opt
 }  // namespace spvtools

+ 4 - 0
3rdparty/spirv-tools/source/opt/wrap_opkill.h

@@ -56,6 +56,10 @@ class WrapOpKill : public Pass {
   // function could not be generated.
   uint32_t GetOpKillFuncId();
 
+  // Returns the id of the return type for the function that contains |inst|.
+  // Returns 0 if |inst| is not in a function.
+  uint32_t GetOwningFunctionsReturnType(Instruction* inst);
+
   // The id of the void type.  If its value is 0, then the void type has not
   // been found or created yet.
   uint32_t void_type_id_;

+ 6 - 0
3rdparty/spirv-tools/source/spirv_fuzzer_options.cpp

@@ -22,6 +22,7 @@ const uint32_t kDefaultStepLimit = 250;
 spv_fuzzer_options_t::spv_fuzzer_options_t()
     : has_random_seed(false),
       random_seed(0),
+      replay_validation_enabled(false),
       shrinker_step_limit(kDefaultStepLimit) {}
 
 SPIRV_TOOLS_EXPORT spv_fuzzer_options spvFuzzerOptionsCreate() {
@@ -32,6 +33,11 @@ SPIRV_TOOLS_EXPORT void spvFuzzerOptionsDestroy(spv_fuzzer_options options) {
   delete options;
 }
 
+SPIRV_TOOLS_EXPORT void spvFuzzerOptionsEnableReplayValidation(
+    spv_fuzzer_options options) {
+  options->replay_validation_enabled = true;
+}
+
 SPIRV_TOOLS_EXPORT void spvFuzzerOptionsSetRandomSeed(
     spv_fuzzer_options options, uint32_t seed) {
   options->has_random_seed = true;

+ 3 - 0
3rdparty/spirv-tools/source/spirv_fuzzer_options.h

@@ -29,6 +29,9 @@ struct spv_fuzzer_options_t {
   bool has_random_seed;
   uint32_t random_seed;
 
+  // See spvFuzzerOptionsEnableReplayValidation.
+  bool replay_validation_enabled;
+
   // See spvFuzzerOptionsSetShrinkerStepLimit.
   uint32_t shrinker_step_limit;
 };

+ 19 - 0
3rdparty/spirv-tools/source/val/validate.cpp

@@ -272,6 +272,7 @@ spv_result_t ValidateBinaryUsingContextAndValidationState(
     return error;
   }
 
+  std::vector<Instruction*> visited_entry_points;
   for (auto& instruction : vstate->ordered_instructions()) {
     {
       // In order to do this work outside of Process Instruction we need to be
@@ -293,6 +294,24 @@ spv_result_t ValidateBinaryUsingContextAndValidationState(
 
         vstate->RegisterEntryPoint(entry_point, execution_model,
                                    std::move(desc));
+
+        if (visited_entry_points.size() > 0) {
+          for (const Instruction* check_inst : visited_entry_points) {
+            const auto check_execution_model =
+                check_inst->GetOperandAs<SpvExecutionModel>(0);
+            const char* check_str = reinterpret_cast<const char*>(
+                check_inst->words().data() + inst->operand(2).offset);
+            const std::string check_name(check_str);
+
+            if (desc.name == check_name &&
+                execution_model == check_execution_model) {
+              return vstate->diag(SPV_ERROR_INVALID_DATA, inst)
+                     << "2 Entry points cannot share the same name and "
+                        "ExecutionMode.";
+            }
+          }
+        }
+        visited_entry_points.push_back(inst);
       }
       if (inst->opcode() == SpvOpFunctionCall) {
         if (!vstate->in_function_body()) {

+ 1 - 1
3rdparty/spirv-tools/source/val/validate.h

@@ -208,7 +208,7 @@ spv_result_t MiscPass(ValidationState_t& _, const Instruction* inst);
 spv_result_t ValidateExecutionLimitations(ValidationState_t& _,
                                           const Instruction* inst);
 
-/// Validates restricted  uses of 8- and 16-bit types.
+/// Validates restricted uses of 8- and 16-bit types.
 ///
 /// Validates shaders that uses 8- or 16-bit storage capabilities, but not full
 /// capabilities only have appropriate uses of those types.

+ 34 - 8
3rdparty/spirv-tools/source/val/validate_conversion.cpp

@@ -18,6 +18,7 @@
 
 #include "source/diagnostic.h"
 #include "source/opcode.h"
+#include "source/spirv_constant.h"
 #include "source/val/instruction.h"
 #include "source/val/validation_state.h"
 
@@ -467,15 +468,40 @@ spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
                << "Expected input to be a pointer or int or float vector "
                << "or scalar: " << spvOpcodeString(opcode);
 
-      if (result_is_pointer && !input_is_pointer && !input_is_int_scalar)
-        return _.diag(SPV_ERROR_INVALID_DATA, inst)
-               << "Expected input to be a pointer or int scalar if Result Type "
-               << "is pointer: " << spvOpcodeString(opcode);
+      if (_.version() >= SPV_SPIRV_VERSION_WORD(1, 5) ||
+          _.HasExtension(kSPV_KHR_physical_storage_buffer)) {
+        const bool result_is_int_vector = _.IsIntVectorType(result_type);
+        const bool result_has_int32 =
+            _.ContainsSizedIntOrFloatType(result_type, SpvOpTypeInt, 32);
+        const bool input_is_int_vector = _.IsIntVectorType(input_type);
+        const bool input_has_int32 =
+            _.ContainsSizedIntOrFloatType(input_type, SpvOpTypeInt, 32);
+        if (result_is_pointer && !input_is_pointer && !input_is_int_scalar &&
+            !(input_is_int_vector && input_has_int32))
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "Expected input to be a pointer, int scalar or 32-bit int "
+                    "vector if Result Type is pointer: "
+                 << spvOpcodeString(opcode);
 
-      if (input_is_pointer && !result_is_pointer && !result_is_int_scalar)
-        return _.diag(SPV_ERROR_INVALID_DATA, inst)
-               << "Pointer can only be converted to another pointer or int "
-               << "scalar: " << spvOpcodeString(opcode);
+        if (input_is_pointer && !result_is_pointer && !result_is_int_scalar &&
+            !(result_is_int_vector && result_has_int32))
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "Pointer can only be converted to another pointer, int "
+                    "scalar or 32-bit int vector: "
+                 << spvOpcodeString(opcode);
+      } else {
+        if (result_is_pointer && !input_is_pointer && !input_is_int_scalar)
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "Expected input to be a pointer or int scalar if Result "
+                    "Type is pointer: "
+                 << spvOpcodeString(opcode);
+
+        if (input_is_pointer && !result_is_pointer && !result_is_int_scalar)
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "Pointer can only be converted to another pointer or int "
+                    "scalar: "
+                 << spvOpcodeString(opcode);
+      }
 
       if (!result_is_pointer && !input_is_pointer) {
         const uint32_t result_size =

+ 24 - 4
3rdparty/spirv-tools/source/val/validate_decorations.cpp

@@ -942,6 +942,7 @@ spv_result_t CheckDecorationsOfBuffers(ValidationState_t& vstate) {
           id = id_inst->GetOperandAs<uint32_t>(1u);
           id_inst = vstate.FindDef(id);
         }
+        // Struct requirement is checked on variables so just move on here.
         if (SpvOpTypeStruct != id_inst->opcode()) continue;
         MemberConstraints constraints;
         ComputeMemberConstraintsForStruct(&constraints, id, LayoutConstraints(),
@@ -952,15 +953,18 @@ spv_result_t CheckDecorationsOfBuffers(ValidationState_t& vstate) {
                     : (push_constant ? "PushConstant" : "StorageBuffer");
 
         if (spvIsVulkanEnv(vstate.context()->target_env)) {
-          if (storage_buffer &&
-              hasDecoration(id, SpvDecorationBufferBlock, vstate)) {
+          const bool block = hasDecoration(id, SpvDecorationBlock, vstate);
+          const bool buffer_block =
+              hasDecoration(id, SpvDecorationBufferBlock, vstate);
+          if (storage_buffer && buffer_block) {
             return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                    << "Storage buffer id '" << var_id
                    << " In Vulkan, BufferBlock is disallowed on variables in "
                       "the StorageBuffer storage class";
           }
-          // Vulkan 14.5.1: Check Block decoration for PushConstant variables.
-          if (push_constant && !hasDecoration(id, SpvDecorationBlock, vstate)) {
+          // Vulkan 14.5.1/2: Check Block decoration for PushConstant, Uniform
+          // and StorageBuffer variables. Uniform can also use BufferBlock.
+          if (push_constant && !block) {
             return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
                    << "PushConstant id '" << id
                    << "' is missing Block decoration.\n"
@@ -968,6 +972,22 @@ spv_result_t CheckDecorationsOfBuffers(ValidationState_t& vstate) {
                    << "Such variables must be identified with a Block "
                       "decoration";
           }
+          if (storage_buffer && !block) {
+            return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
+                   << "StorageBuffer id '" << id
+                   << "' is missing Block decoration.\n"
+                   << "From Vulkan spec, section 14.5.2:\n"
+                   << "Such variables must be identified with a Block "
+                      "decoration";
+          }
+          if (uniform && !block && !buffer_block) {
+            return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
+                   << "Uniform id '" << id
+                   << "' is missing Block or BufferBlock decoration.\n"
+                   << "From Vulkan spec, section 14.5.2:\n"
+                   << "Such variables must be identified with a Block or "
+                      "BufferBlock decoration";
+          }
           // Vulkan 14.5.2: Check DescriptorSet and Binding decoration for
           // Uniform and StorageBuffer variables.
           if (uniform || storage_buffer) {

+ 13 - 0
3rdparty/spirv-tools/source/val/validate_memory.cpp

@@ -536,6 +536,19 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
                << "this type";
       }
     }
+
+    if (storage_class == SpvStorageClassStorageBuffer) {
+      if (!IsAllowedTypeOrArrayOfSame(_, pointee, {SpvOpTypeStruct})) {
+        return _.diag(SPV_ERROR_INVALID_ID, inst)
+               << "StorageBuffer OpVariable <id> '" << _.getIdName(inst->id())
+               << "' has illegal type.\n"
+               << "From Vulkan spec, section 14.5.2:\n"
+               << "Variables identified with the StorageBuffer storage class "
+                  "are used to access transparent buffer backed resources. "
+                  "Such variables must be typed as OpTypeStruct, or an array "
+                  "of this type";
+      }
+    }
   }
 
   // WebGPU & Vulkan Appendix A: Check that if contains initializer, then

+ 0 - 1
3rdparty/spirv-tools/source/val/validate_type.cpp

@@ -191,7 +191,6 @@ spv_result_t ValidateTypeRuntimeArray(ValidationState_t& _,
 }
 
 bool ContainsOpaqueType(ValidationState_t& _, const Instruction* str) {
-return false;
   const size_t elem_type_index = 1;
   uint32_t elem_type_id;
   Instruction* elem_type;

+ 12 - 2
3rdparty/spirv-tools/test/fuzz/CMakeLists.txt

@@ -17,8 +17,6 @@ if (${SPIRV_BUILD_FUZZER})
   set(SOURCES
           fuzz_test_util.h
 
-          fuzzer_replayer_test.cpp
-          fuzzer_shrinker_test.cpp
           fact_manager_test.cpp
           fuzz_test_util.cpp
           fuzzer_pass_add_useful_constructs_test.cpp
@@ -34,9 +32,21 @@ if (${SPIRV_BUILD_FUZZER})
           transformation_move_block_down_test.cpp
           transformation_replace_boolean_constant_with_constant_binary_test.cpp
           transformation_replace_constant_with_uniform_test.cpp
+          transformation_replace_id_with_synonym_test.cpp
           transformation_split_block_test.cpp
           uniform_buffer_element_descriptor_test.cpp)
 
+  if (${SPIRV_ENABLE_LONG_FUZZER_TESTS})
+    # These are long-running tests that depend on random seeds.  We do not want
+    # to run them during regular whole-project CI because they may reveal
+    # spirv-fuzz bugs in changes that are totally unrelated to spirv-fuzz,
+    # which would be counfounding.  Instead, they should be run regularly but
+    # separately.
+    set(SOURCES ${SOURCES}
+            fuzzer_replayer_test.cpp
+            fuzzer_shrinker_test.cpp)
+  endif()
+
   add_spvtools_unittest(TARGET fuzz
         SRCS ${SOURCES}
         LIBS SPIRV-Tools-fuzz

+ 16 - 0
3rdparty/spirv-tools/test/fuzz/fuzz_test_util.cpp

@@ -16,6 +16,8 @@
 
 #include <iostream>
 
+#include "tools/io.h"
+
 namespace spvtools {
 namespace fuzz {
 
@@ -89,5 +91,19 @@ std::string ToString(spv_target_env env, const std::vector<uint32_t>& binary) {
   return result;
 }
 
+void DumpShader(opt::IRContext* context, const char* filename) {
+  std::vector<uint32_t> binary;
+  context->module()->ToBinary(&binary, false);
+  DumpShader(binary, filename);
+}
+
+void DumpShader(const std::vector<uint32_t>& binary, const char* filename) {
+  auto write_file_succeeded =
+      WriteFile(filename, "wb", &binary[0], binary.size());
+  if (!write_file_succeeded) {
+    std::cerr << "Failed to dump shader" << std::endl;
+  }
+}
+
 }  // namespace fuzz
 }  // namespace spvtools

+ 7 - 0
3rdparty/spirv-tools/test/fuzz/fuzz_test_util.h

@@ -93,6 +93,13 @@ const spvtools::MessageConsumer kConsoleMessageConsumer =
   }
 };
 
+// Dumps the SPIRV-V module in |context| to file |filename|. Useful for
+// interactive debugging.
+void DumpShader(opt::IRContext* context, const char* filename);
+
+// Dumps |binary| to file |filename|. Useful for interactive debugging.
+void DumpShader(const std::vector<uint32_t>& binary, const char* filename);
+
 }  // namespace fuzz
 }  // namespace spvtools
 

+ 1 - 1
3rdparty/spirv-tools/test/fuzz/fuzzer_replayer_test.cpp

@@ -54,7 +54,7 @@ void RunFuzzerAndReplayer(const std::string& shader,
     std::vector<uint32_t> replayer_binary_out;
     protobufs::TransformationSequence replayer_transformation_sequence_out;
 
-    Replayer replayer(env);
+    Replayer replayer(env, true);
     replayer.SetMessageConsumer(kSilentConsumer);
     auto replayer_result_status = replayer.Run(
         binary_in, initial_facts, fuzzer_transformation_sequence_out,

+ 2 - 1
3rdparty/spirv-tools/test/fuzz/fuzzer_shrinker_test.cpp

@@ -125,7 +125,7 @@ void RunAndCheckShrinker(
     const std::vector<uint32_t>& expected_binary_out,
     uint32_t expected_transformations_out_size, uint32_t step_limit) {
   // Run the shrinker.
-  Shrinker shrinker(target_env, step_limit);
+  Shrinker shrinker(target_env, step_limit, true);
   shrinker.SetMessageConsumer(kSilentConsumer);
 
   std::vector<uint32_t> binary_out;
@@ -158,6 +158,7 @@ void RunFuzzerAndShrinker(const std::string& shader,
 
   std::vector<uint32_t> binary_in;
   SpirvTools t(env);
+  t.SetMessageConsumer(kConsoleMessageConsumer);
   ASSERT_TRUE(t.Assemble(shader, &binary_in, kFuzzAssembleOption));
   ASSERT_TRUE(t.Validate(binary_in));
 

+ 139 - 0
3rdparty/spirv-tools/test/fuzz/transformation_add_dead_continue_test.cpp

@@ -1249,6 +1249,145 @@ TEST(TransformationAddDeadContinueTest, RespectDominanceRules3) {
   ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
 }
 
+TEST(TransformationAddDeadContinueTest, Miscellaneous1) {
+  // A miscellaneous test that exposed a bug in spirv-fuzz.
+
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main" %586 %623
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+               OpMemberDecorate %34 0 Offset 0
+               OpDecorate %34 Block
+               OpDecorate %36 DescriptorSet 0
+               OpDecorate %36 Binding 0
+               OpDecorate %586 BuiltIn FragCoord
+               OpMemberDecorate %591 0 Offset 0
+               OpDecorate %591 Block
+               OpDecorate %593 DescriptorSet 0
+               OpDecorate %593 Binding 1
+               OpDecorate %623 Location 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypePointer Function %6
+          %9 = OpConstant %6 0
+         %16 = OpConstant %6 2
+         %17 = OpTypeBool
+         %27 = OpTypeFloat 32
+         %28 = OpTypeVector %27 2
+         %29 = OpTypeMatrix %28 2
+         %30 = OpTypePointer Private %29
+         %31 = OpVariable %30 Private
+         %34 = OpTypeStruct %27
+         %35 = OpTypePointer Uniform %34
+         %36 = OpVariable %35 Uniform
+         %37 = OpTypePointer Uniform %27
+         %40 = OpTypePointer Private %27
+         %43 = OpConstant %6 1
+         %62 = OpConstant %6 3
+         %64 = OpTypeVector %27 3
+         %65 = OpTypeMatrix %64 2
+         %66 = OpTypePointer Private %65
+         %67 = OpVariable %66 Private
+         %92 = OpConstant %6 4
+         %94 = OpTypeVector %27 4
+         %95 = OpTypeMatrix %94 2
+         %96 = OpTypePointer Private %95
+         %97 = OpVariable %96 Private
+        %123 = OpTypeMatrix %28 3
+        %124 = OpTypePointer Private %123
+        %125 = OpVariable %124 Private
+        %151 = OpTypeMatrix %64 3
+        %152 = OpTypePointer Private %151
+        %153 = OpVariable %152 Private
+        %179 = OpTypeMatrix %94 3
+        %180 = OpTypePointer Private %179
+        %181 = OpVariable %180 Private
+        %207 = OpTypeMatrix %28 4
+        %208 = OpTypePointer Private %207
+        %209 = OpVariable %208 Private
+        %235 = OpTypeMatrix %64 4
+        %236 = OpTypePointer Private %235
+        %237 = OpVariable %236 Private
+        %263 = OpTypeMatrix %94 4
+        %264 = OpTypePointer Private %263
+        %265 = OpVariable %264 Private
+        %275 = OpTypeInt 32 0
+        %276 = OpConstant %275 9
+        %277 = OpTypeArray %27 %276
+        %278 = OpTypePointer Function %277
+        %280 = OpConstant %27 0
+        %281 = OpTypePointer Function %27
+        %311 = OpConstant %27 16
+        %448 = OpConstant %6 5
+        %482 = OpConstant %6 6
+        %516 = OpConstant %6 7
+        %550 = OpConstant %6 8
+        %585 = OpTypePointer Input %94
+        %586 = OpVariable %585 Input
+        %587 = OpConstant %275 0
+        %588 = OpTypePointer Input %27
+        %591 = OpTypeStruct %28
+        %592 = OpTypePointer Uniform %591
+        %593 = OpVariable %592 Uniform
+        %596 = OpConstant %27 3
+        %601 = OpConstant %275 1
+        %617 = OpConstant %6 9
+        %622 = OpTypePointer Output %94
+        %623 = OpVariable %622 Output
+        %628 = OpConstant %27 1
+        %634 = OpConstantComposite %94 %280 %280 %280 %628
+        %635 = OpUndef %6
+        %636 = OpUndef %17
+        %637 = OpUndef %27
+        %638 = OpUndef %64
+        %639 = OpUndef %94
+        %640 = OpConstantTrue %17
+        %736 = OpConstantFalse %17
+        %642 = OpVariable %37 Uniform
+        %643 = OpVariable %40 Private
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpBranch %164
+        %164 = OpLabel
+               OpLoopMerge %166 %167 None
+               OpBranch %165
+        %165 = OpLabel
+               OpBranch %172
+        %172 = OpLabel
+               OpSelectionMerge %174 None
+               OpBranchConditional %640 %174 %174
+        %174 = OpLabel
+        %785 = OpCopyObject %6 %43
+               OpBranch %167
+        %167 = OpLabel
+        %190 = OpIAdd %6 %9 %785
+               OpBranchConditional %640 %164 %166
+        %166 = OpLabel
+               OpBranch %196
+        %196 = OpLabel
+               OpBranch %194
+        %194 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+
+  // This transformation would shortcut the part of the loop body that defines
+  // an id used in the continue target.
+  auto bad_transformation = TransformationAddDeadContinue(165, false, {});
+  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+}
+
 }  // namespace
 }  // namespace fuzz
 }  // namespace spvtools

+ 569 - 0
3rdparty/spirv-tools/test/fuzz/transformation_replace_id_with_synonym_test.cpp

@@ -0,0 +1,569 @@
+// Copyright (c) 2019 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/fuzz/transformation_replace_id_with_synonym.h"
+#include "source/fuzz/data_descriptor.h"
+#include "source/fuzz/id_use_descriptor.h"
+#include "test/fuzz/fuzz_test_util.h"
+
+namespace spvtools {
+namespace fuzz {
+namespace {
+
+// The following shader was obtained from this GLSL, which was then optimized
+// with spirv-opt -O and manually edited to include some uses of OpCopyObject
+// (to introduce id synonyms).
+//
+// #version 310 es
+//
+// precision highp int;
+// precision highp float;
+//
+// layout(set = 0, binding = 0) uniform buf {
+//   int a;
+//   int b;
+//   int c;
+// };
+//
+// layout(location = 0) out vec4 color;
+//
+// void main() {
+//   int x = a;
+//   float f = 0.0;
+//   while (x < b) {
+//     switch(x % 4) {
+//       case 0:
+//         color[0] = f;
+//         break;
+//       case 1:
+//         color[1] = f;
+//         break;
+//       case 2:
+//         color[2] = f;
+//         break;
+//       case 3:
+//         color[3] = f;
+//         break;
+//       default:
+//         break;
+//     }
+//     if (x > c) {
+//       x++;
+//     } else {
+//       x += 2;
+//     }
+//   }
+//   color[0] += color[1] + float(x);
+// }
+const std::string kComplexShader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main" %42
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+               OpName %4 "main"
+               OpName %9 "buf"
+               OpMemberName %9 0 "a"
+               OpMemberName %9 1 "b"
+               OpMemberName %9 2 "c"
+               OpName %11 ""
+               OpName %42 "color"
+               OpMemberDecorate %9 0 Offset 0
+               OpMemberDecorate %9 1 Offset 4
+               OpMemberDecorate %9 2 Offset 8
+               OpDecorate %9 Block
+               OpDecorate %11 DescriptorSet 0
+               OpDecorate %11 Binding 0
+               OpDecorate %42 Location 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %9 = OpTypeStruct %6 %6 %6
+         %10 = OpTypePointer Uniform %9
+         %11 = OpVariable %10 Uniform
+         %12 = OpConstant %6 0
+         %13 = OpTypePointer Uniform %6
+         %16 = OpTypeFloat 32
+         %19 = OpConstant %16 0
+         %26 = OpConstant %6 1
+         %29 = OpTypeBool
+         %32 = OpConstant %6 4
+         %40 = OpTypeVector %16 4
+         %41 = OpTypePointer Output %40
+         %42 = OpVariable %41 Output
+         %44 = OpTypeInt 32 0
+         %45 = OpConstant %44 0
+         %46 = OpTypePointer Output %16
+         %50 = OpConstant %44 1
+         %54 = OpConstant %44 2
+         %58 = OpConstant %44 3
+         %64 = OpConstant %6 2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+        %209 = OpCopyObject %6 %12
+         %14 = OpAccessChain %13 %11 %12
+         %15 = OpLoad %6 %14
+        %200 = OpCopyObject %6 %15
+               OpBranch %20
+         %20 = OpLabel
+         %84 = OpPhi %6 %15 %5 %86 %69
+         %27 = OpAccessChain %13 %11 %26
+         %28 = OpLoad %6 %27
+        %207 = OpCopyObject %6 %84
+        %201 = OpCopyObject %6 %15
+         %30 = OpSLessThan %29 %84 %28
+               OpLoopMerge %22 %69 None
+               OpBranchConditional %30 %21 %22
+         %21 = OpLabel
+         %33 = OpSMod %6 %84 %32
+        %208 = OpCopyObject %6 %33
+               OpSelectionMerge %39 None
+               OpSwitch %33 %38 0 %34 1 %35 2 %36 3 %37
+         %38 = OpLabel
+        %202 = OpCopyObject %6 %15
+               OpBranch %39
+         %34 = OpLabel
+        %210 = OpCopyObject %16 %19
+         %47 = OpAccessChain %46 %42 %45
+               OpStore %47 %19
+               OpBranch %39
+         %35 = OpLabel
+         %51 = OpAccessChain %46 %42 %50
+               OpStore %51 %19
+               OpBranch %39
+         %36 = OpLabel
+        %204 = OpCopyObject %44 %54
+         %55 = OpAccessChain %46 %42 %54
+        %203 = OpCopyObject %46 %55
+               OpStore %55 %19
+               OpBranch %39
+         %37 = OpLabel
+         %59 = OpAccessChain %46 %42 %58
+               OpStore %59 %19
+               OpBranch %39
+         %39 = OpLabel
+        %300 = OpIAdd %6 %15 %15
+         %65 = OpAccessChain %13 %11 %64
+         %66 = OpLoad %6 %65
+         %67 = OpSGreaterThan %29 %84 %66
+               OpSelectionMerge %69 None
+               OpBranchConditional %67 %68 %72
+         %68 = OpLabel
+         %71 = OpIAdd %6 %84 %26
+               OpBranch %69
+         %72 = OpLabel
+         %74 = OpIAdd %6 %84 %64
+        %205 = OpCopyObject %6 %74
+               OpBranch %69
+         %69 = OpLabel
+         %86 = OpPhi %6 %71 %68 %74 %72
+        %301 = OpPhi %6 %71 %68 %15 %72
+               OpBranch %20
+         %22 = OpLabel
+         %75 = OpAccessChain %46 %42 %50
+         %76 = OpLoad %16 %75
+         %78 = OpConvertSToF %16 %84
+         %80 = OpAccessChain %46 %42 %45
+        %206 = OpCopyObject %16 %78
+         %81 = OpLoad %16 %80
+         %79 = OpFAdd %16 %76 %78
+         %82 = OpFAdd %16 %81 %79
+               OpStore %80 %82
+               OpReturn
+               OpFunctionEnd
+)";
+
+protobufs::Fact MakeFact(uint32_t id, uint32_t copy_id) {
+  protobufs::FactIdSynonym id_synonym_fact;
+  id_synonym_fact.set_id(id);
+  id_synonym_fact.mutable_data_descriptor()->set_object(copy_id);
+  protobufs::Fact result;
+  *result.mutable_id_synonym_fact() = id_synonym_fact;
+  return result;
+}
+
+// Equips the fact manager with synonym facts for the above shader.
+void SetUpIdSynonyms(FactManager* fact_manager, opt::IRContext* context) {
+  fact_manager->AddFact(MakeFact(15, 200), context);
+  fact_manager->AddFact(MakeFact(15, 201), context);
+  fact_manager->AddFact(MakeFact(15, 202), context);
+  fact_manager->AddFact(MakeFact(55, 203), context);
+  fact_manager->AddFact(MakeFact(54, 204), context);
+  fact_manager->AddFact(MakeFact(74, 205), context);
+  fact_manager->AddFact(MakeFact(78, 206), context);
+  fact_manager->AddFact(MakeFact(84, 207), context);
+  fact_manager->AddFact(MakeFact(33, 208), context);
+  fact_manager->AddFact(MakeFact(12, 209), context);
+  fact_manager->AddFact(MakeFact(19, 210), context);
+}
+
+TEST(TransformationReplaceIdWithSynonymTest, IllegalTransformations) {
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context =
+      BuildModule(env, consumer, kComplexShader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+  SetUpIdSynonyms(&fact_manager, context.get());
+
+  // %202 cannot replace %15 as in-operand 0 of %300, since %202 does not
+  // dominate %300.
+  auto synonym_does_not_dominate_use = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(15, SpvOpIAdd, 0, 300, 0),
+      MakeDataDescriptor(202, {}), 0);
+  ASSERT_FALSE(
+      synonym_does_not_dominate_use.IsApplicable(context.get(), fact_manager));
+
+  // %202 cannot replace %15 as in-operand 2 of %301, since this is the OpPhi's
+  // incoming value for block %72, and %202 does not dominate %72.
+  auto synonym_does_not_dominate_use_op_phi =
+      TransformationReplaceIdWithSynonym(
+          transformation::MakeIdUseDescriptor(15, SpvOpPhi, 2, 301, 0),
+          MakeDataDescriptor(202, {}), 0);
+  ASSERT_FALSE(synonym_does_not_dominate_use_op_phi.IsApplicable(context.get(),
+                                                                 fact_manager));
+
+  // %200 is not a synonym for %84
+  auto id_in_use_is_not_synonymous = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(84, SpvOpSGreaterThan, 0, 67, 0),
+      MakeDataDescriptor(200, {}), 0);
+  ASSERT_FALSE(
+      id_in_use_is_not_synonymous.IsApplicable(context.get(), fact_manager));
+
+  // %86 is not a synonym for anything (and in particular not for %74)
+  auto id_has_no_synonyms = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(86, SpvOpPhi, 2, 84, 0),
+      MakeDataDescriptor(74, {}), 0);
+  ASSERT_FALSE(id_has_no_synonyms.IsApplicable(context.get(), fact_manager));
+
+  // This would lead to %207 = 'OpCopyObject %type %207' if it were allowed
+  auto synonym_use_is_in_synonym_definition =
+      TransformationReplaceIdWithSynonym(
+          transformation::MakeIdUseDescriptor(84, SpvOpCopyObject, 0, 207, 0),
+          MakeDataDescriptor(207, {}), 0);
+  ASSERT_FALSE(synonym_use_is_in_synonym_definition.IsApplicable(context.get(),
+                                                                 fact_manager));
+
+  // The id use descriptor does not lead to a use (%84 is not used in the
+  // definition of %207)
+  auto bad_id_use_descriptor = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(84, SpvOpCopyObject, 0, 200, 0),
+      MakeDataDescriptor(207, {}), 0);
+  ASSERT_FALSE(bad_id_use_descriptor.IsApplicable(context.get(), fact_manager));
+
+  // This replacement would lead to an access chain into a struct using a
+  // non-constant index.
+  auto bad_access_chain = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(12, SpvOpAccessChain, 1, 14, 0),
+      MakeDataDescriptor(209, {}), 0);
+  ASSERT_FALSE(bad_access_chain.IsApplicable(context.get(), fact_manager));
+}
+
+TEST(TransformationReplaceIdWithSynonymTest, LegalTransformations) {
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context =
+      BuildModule(env, consumer, kComplexShader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+  SetUpIdSynonyms(&fact_manager, context.get());
+
+  auto global_constant_synonym = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(19, SpvOpStore, 1, 47, 0),
+      MakeDataDescriptor(210, {}), 0);
+  ASSERT_TRUE(
+      global_constant_synonym.IsApplicable(context.get(), fact_manager));
+  global_constant_synonym.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  auto replace_vector_access_chain_index = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(54, SpvOpAccessChain, 1, 55, 0),
+      MakeDataDescriptor(204, {}), 0);
+  ASSERT_TRUE(replace_vector_access_chain_index.IsApplicable(context.get(),
+                                                             fact_manager));
+  replace_vector_access_chain_index.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  // This is an interesting case because it replaces something that is being
+  // copied with something that is already a synonym.
+  auto regular_replacement = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(15, SpvOpCopyObject, 0, 202, 0),
+      MakeDataDescriptor(201, {}), 0);
+  ASSERT_TRUE(regular_replacement.IsApplicable(context.get(), fact_manager));
+  regular_replacement.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  auto regular_replacement2 = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(55, SpvOpStore, 0, 203, 0),
+      MakeDataDescriptor(203, {}), 0);
+  ASSERT_TRUE(regular_replacement2.IsApplicable(context.get(), fact_manager));
+  regular_replacement2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  auto good_op_phi = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(74, SpvOpPhi, 2, 86, 0),
+      MakeDataDescriptor(205, {}), 0);
+  ASSERT_TRUE(good_op_phi.IsApplicable(context.get(), fact_manager));
+  good_op_phi.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  const std::string after_transformation = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main" %42
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+               OpName %4 "main"
+               OpName %9 "buf"
+               OpMemberName %9 0 "a"
+               OpMemberName %9 1 "b"
+               OpMemberName %9 2 "c"
+               OpName %11 ""
+               OpName %42 "color"
+               OpMemberDecorate %9 0 Offset 0
+               OpMemberDecorate %9 1 Offset 4
+               OpMemberDecorate %9 2 Offset 8
+               OpDecorate %9 Block
+               OpDecorate %11 DescriptorSet 0
+               OpDecorate %11 Binding 0
+               OpDecorate %42 Location 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %9 = OpTypeStruct %6 %6 %6
+         %10 = OpTypePointer Uniform %9
+         %11 = OpVariable %10 Uniform
+         %12 = OpConstant %6 0
+         %13 = OpTypePointer Uniform %6
+         %16 = OpTypeFloat 32
+         %19 = OpConstant %16 0
+         %26 = OpConstant %6 1
+         %29 = OpTypeBool
+         %32 = OpConstant %6 4
+         %40 = OpTypeVector %16 4
+         %41 = OpTypePointer Output %40
+         %42 = OpVariable %41 Output
+         %44 = OpTypeInt 32 0
+         %45 = OpConstant %44 0
+         %46 = OpTypePointer Output %16
+         %50 = OpConstant %44 1
+         %54 = OpConstant %44 2
+         %58 = OpConstant %44 3
+         %64 = OpConstant %6 2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+        %209 = OpCopyObject %6 %12
+         %14 = OpAccessChain %13 %11 %12
+         %15 = OpLoad %6 %14
+        %200 = OpCopyObject %6 %15
+               OpBranch %20
+         %20 = OpLabel
+         %84 = OpPhi %6 %15 %5 %86 %69
+         %27 = OpAccessChain %13 %11 %26
+         %28 = OpLoad %6 %27
+        %207 = OpCopyObject %6 %84
+        %201 = OpCopyObject %6 %15
+         %30 = OpSLessThan %29 %84 %28
+               OpLoopMerge %22 %69 None
+               OpBranchConditional %30 %21 %22
+         %21 = OpLabel
+         %33 = OpSMod %6 %84 %32
+        %208 = OpCopyObject %6 %33
+               OpSelectionMerge %39 None
+               OpSwitch %33 %38 0 %34 1 %35 2 %36 3 %37
+         %38 = OpLabel
+        %202 = OpCopyObject %6 %201
+               OpBranch %39
+         %34 = OpLabel
+        %210 = OpCopyObject %16 %19
+         %47 = OpAccessChain %46 %42 %45
+               OpStore %47 %210
+               OpBranch %39
+         %35 = OpLabel
+         %51 = OpAccessChain %46 %42 %50
+               OpStore %51 %19
+               OpBranch %39
+         %36 = OpLabel
+        %204 = OpCopyObject %44 %54
+         %55 = OpAccessChain %46 %42 %204
+        %203 = OpCopyObject %46 %55
+               OpStore %203 %19
+               OpBranch %39
+         %37 = OpLabel
+         %59 = OpAccessChain %46 %42 %58
+               OpStore %59 %19
+               OpBranch %39
+         %39 = OpLabel
+        %300 = OpIAdd %6 %15 %15
+         %65 = OpAccessChain %13 %11 %64
+         %66 = OpLoad %6 %65
+         %67 = OpSGreaterThan %29 %84 %66
+               OpSelectionMerge %69 None
+               OpBranchConditional %67 %68 %72
+         %68 = OpLabel
+         %71 = OpIAdd %6 %84 %26
+               OpBranch %69
+         %72 = OpLabel
+         %74 = OpIAdd %6 %84 %64
+        %205 = OpCopyObject %6 %74
+               OpBranch %69
+         %69 = OpLabel
+         %86 = OpPhi %6 %71 %68 %205 %72
+        %301 = OpPhi %6 %71 %68 %15 %72
+               OpBranch %20
+         %22 = OpLabel
+         %75 = OpAccessChain %46 %42 %50
+         %76 = OpLoad %16 %75
+         %78 = OpConvertSToF %16 %84
+         %80 = OpAccessChain %46 %42 %45
+        %206 = OpCopyObject %16 %78
+         %81 = OpLoad %16 %80
+         %79 = OpFAdd %16 %76 %78
+         %82 = OpFAdd %16 %81 %79
+               OpStore %80 %82
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+}
+
+TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfVariables) {
+  // The following SPIR-V comes from this GLSL, with object copies added:
+  //
+  // #version 310 es
+  //
+  // precision highp int;
+  //
+  // int g;
+  //
+  // void main() {
+  //   int l;
+  //   l = g;
+  //   g = l;
+  // }
+  const std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+               OpName %4 "main"
+               OpName %8 "l"
+               OpName %10 "g"
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypePointer Function %6
+          %9 = OpTypePointer Private %6
+         %10 = OpVariable %9 Private
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+          %8 = OpVariable %7 Function
+        %100 = OpCopyObject %9 %10
+        %101 = OpCopyObject %7 %8
+         %11 = OpLoad %6 %10
+               OpStore %8 %11
+         %12 = OpLoad %6 %8
+               OpStore %10 %12
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+
+  fact_manager.AddFact(MakeFact(10, 100), context.get());
+  fact_manager.AddFact(MakeFact(8, 101), context.get());
+
+  // Replace %10 with %100 in:
+  // %11 = OpLoad %6 %10
+  auto replacement1 = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(10, SpvOpLoad, 0, 11, 0),
+      MakeDataDescriptor(100, {}), 0);
+  ASSERT_TRUE(replacement1.IsApplicable(context.get(), fact_manager));
+  replacement1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  // Replace %8 with %101 in:
+  // OpStore %8 %11
+  auto replacement2 = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(8, SpvOpStore, 0, 11, 0),
+      MakeDataDescriptor(101, {}), 0);
+  ASSERT_TRUE(replacement2.IsApplicable(context.get(), fact_manager));
+  replacement2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  // Replace %8 with %101 in:
+  // %12 = OpLoad %6 %8
+  auto replacement3 = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(8, SpvOpLoad, 0, 12, 0),
+      MakeDataDescriptor(101, {}), 0);
+  ASSERT_TRUE(replacement3.IsApplicable(context.get(), fact_manager));
+  replacement3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  // Replace %10 with %100 in:
+  // OpStore %10 %12
+  auto replacement4 = TransformationReplaceIdWithSynonym(
+      transformation::MakeIdUseDescriptor(10, SpvOpStore, 0, 12, 0),
+      MakeDataDescriptor(100, {}), 0);
+  ASSERT_TRUE(replacement4.IsApplicable(context.get(), fact_manager));
+  replacement4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  const std::string after_transformation = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+               OpName %4 "main"
+               OpName %8 "l"
+               OpName %10 "g"
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypePointer Function %6
+          %9 = OpTypePointer Private %6
+         %10 = OpVariable %9 Private
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+          %8 = OpVariable %7 Function
+        %100 = OpCopyObject %9 %10
+        %101 = OpCopyObject %7 %8
+         %11 = OpLoad %6 %100
+               OpStore %101 %11
+         %12 = OpLoad %6 %101
+               OpStore %100 %12
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+}
+
+}  // namespace
+}  // namespace fuzz
+}  // namespace spvtools

+ 51 - 0
3rdparty/spirv-tools/test/opt/copy_prop_array_test.cpp

@@ -1571,6 +1571,57 @@ OpFunctionEnd
   SinglePassRunAndCheck<CopyPropagateArrays>(before, after, true, true);
 }
 
+TEST_F(CopyPropArrayPassTest, IndexIsNullConstnat) {
+  const std::string text = R"(
+; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Uniform
+; CHECK: [[null:%\w+]] = OpConstantNull %uint
+; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform__arr_uint_uint_1 [[var]] %uint_0 %uint_0
+; CHECK: OpAccessChain %_ptr_Uniform_uint [[ac1]] [[null]]
+; CHECK-NEXT: OpReturn
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main"
+               OpExecutionMode %main OriginUpperLeft
+               OpSource HLSL 600
+               OpDecorate %myCBuffer DescriptorSet 0
+               OpDecorate %myCBuffer Binding 0
+               OpDecorate %_arr_v4float_uint_1 ArrayStride 16
+               OpMemberDecorate %MyConstantBuffer 0 Offset 0
+               OpMemberDecorate %type_myCBuffer 0 Offset 0
+               OpDecorate %type_myCBuffer Block
+       %uint = OpTypeInt 32 0
+      %int_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+%_arr_v4float_uint_1 = OpTypeArray %uint %uint_1
+%MyConstantBuffer = OpTypeStruct %_arr_v4float_uint_1
+%type_myCBuffer = OpTypeStruct %MyConstantBuffer
+%_ptr_Uniform_type_myCBuffer = OpTypePointer Uniform %type_myCBuffer
+%_arr_v4float_uint_1_0 = OpTypeArray %uint %uint_1
+       %void = OpTypeVoid
+         %19 = OpTypeFunction %void
+%_ptr_Function_v4float = OpTypePointer Function %uint
+%_ptr_Uniform_MyConstantBuffer = OpTypePointer Uniform %MyConstantBuffer
+  %myCBuffer = OpVariable %_ptr_Uniform_type_myCBuffer Uniform
+%_ptr_Function__arr_v4float_uint_1_0 = OpTypePointer Function %_arr_v4float_uint_1_0
+         %23 = OpConstantNull %uint
+       %main = OpFunction %void None %19
+         %24 = OpLabel
+         %25 = OpVariable %_ptr_Function__arr_v4float_uint_1_0 Function
+         %26 = OpAccessChain %_ptr_Uniform_MyConstantBuffer %myCBuffer %int_0
+         %27 = OpLoad %MyConstantBuffer %26
+         %28 = OpCompositeExtract %_arr_v4float_uint_1 %27 0
+         %29 = OpCompositeExtract %uint %28 0
+         %30 = OpCompositeConstruct %_arr_v4float_uint_1_0 %29
+               OpStore %25 %30
+         %31 = OpAccessChain %_ptr_Function_v4float %25 %23
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<CopyPropagateArrays>(text, true);
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools

+ 57 - 5
3rdparty/spirv-tools/test/opt/wrap_opkill_test.cpp

@@ -31,7 +31,7 @@ TEST_F(WrapOpKillTest, SingleOpKill) {
 ; CHECK: [[orig_kill]] = OpFunction
 ; CHECK-NEXT: OpLabel
 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
-; CHECK-NEXT: OpUnreachable
+; CHECK-NEXT: OpReturn
 ; CHECK: [[new_kill]] = OpFunction
 ; CHECK-NEXT: OpLabel
 ; CHECK-NEXT: OpKill
@@ -83,10 +83,10 @@ TEST_F(WrapOpKillTest, MultipleOpKillInSameFunc) {
 ; CHECK-NEXT: OpBranchConditional
 ; CHECK-NEXT: OpLabel
 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
-; CHECK-NEXT: OpUnreachable
+; CHECK-NEXT: OpReturn
 ; CHECK-NEXT: OpLabel
 ; CHECK-NEXT: OpFunctionCall %void [[new_kill]]
-; CHECK-NEXT: OpUnreachable
+; CHECK-NEXT: OpReturn
 ; CHECK: [[new_kill]] = OpFunction
 ; CHECK-NEXT: OpLabel
 ; CHECK-NEXT: OpKill
@@ -143,11 +143,11 @@ TEST_F(WrapOpKillTest, MultipleOpKillInDifferentFunc) {
 ; CHECK: [[orig_kill1]] = OpFunction
 ; CHECK-NEXT: OpLabel
 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
-; CHECK-NEXT: OpUnreachable
+; CHECK-NEXT: OpReturn
 ; CHECK: [[orig_kill2]] = OpFunction
 ; CHECK-NEXT: OpLabel
 ; CHECK-NEXT: OpFunctionCall %void [[new_kill]]
-; CHECK-NEXT: OpUnreachable
+; CHECK-NEXT: OpReturn
 ; CHECK: [[new_kill]] = OpFunction
 ; CHECK-NEXT: OpLabel
 ; CHECK-NEXT: OpKill
@@ -193,6 +193,58 @@ TEST_F(WrapOpKillTest, MultipleOpKillInDifferentFunc) {
   SinglePassRunAndMatch<WrapOpKill>(text, true);
 }
 
+TEST_F(WrapOpKillTest, FuncWithReturnValue) {
+  const std::string text = R"(
+; CHECK: OpEntryPoint Fragment [[main:%\w+]]
+; CHECK: [[main]] = OpFunction
+; CHECK: OpFunctionCall %int [[orig_kill:%\w+]]
+; CHECK: [[orig_kill]] = OpFunction
+; CHECK-NEXT: OpLabel
+; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
+; CHECK-NEXT: [[undef:%\w+]] = OpUndef %int
+; CHECK-NEXT: OpReturnValue [[undef]]
+; CHECK: [[new_kill]] = OpFunction
+; CHECK-NEXT: OpLabel
+; CHECK-NEXT: OpKill
+; CHECK-NEXT: OpFunctionEnd
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main"
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 330
+               OpName %main "main"
+       %void = OpTypeVoid
+          %5 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+  %func_type = OpTypeFunction %int
+       %bool = OpTypeBool
+       %true = OpConstantTrue %bool
+       %main = OpFunction %void None %5
+          %8 = OpLabel
+               OpBranch %9
+          %9 = OpLabel
+               OpLoopMerge %10 %11 None
+               OpBranch %12
+         %12 = OpLabel
+               OpBranchConditional %true %13 %10
+         %13 = OpLabel
+               OpBranch %11
+         %11 = OpLabel
+         %14 = OpFunctionCall %int %kill_
+               OpBranch %9
+         %10 = OpLabel
+               OpReturn
+               OpFunctionEnd
+      %kill_ = OpFunction %int None %func_type
+         %15 = OpLabel
+               OpKill
+               OpFunctionEnd
+  )";
+
+  SinglePassRunAndMatch<WrapOpKill>(text, true);
+}
+
 TEST_F(WrapOpKillTest, IdBoundOverflow1) {
   const std::string text = R"(
 OpCapability GeometryStreams

+ 1 - 0
3rdparty/spirv-tools/test/val/CMakeLists.txt

@@ -35,6 +35,7 @@ add_spvtools_unittest(TARGET val_abcde
        val_data_test.cpp
        val_decoration_test.cpp
        val_derivatives_test.cpp
+       val_entry_point.cpp
        val_explicit_reserved_test.cpp
        val_extensions_test.cpp
        val_ext_inst_test.cpp

+ 165 - 9
3rdparty/spirv-tools/test/val/val_conversion_test.cpp

@@ -248,6 +248,8 @@ OpMemoryModel Physical32 OpenCL
 %f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
 %f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4
 
+%u64vec2_01 = OpConstantComposite %u64vec2 %u64_0 %u64_1
+
 %true = OpConstantTrue %bool
 %false = OpConstantFalse %bool
 
@@ -1206,6 +1208,49 @@ TEST_F(ValidateConversion, BitcastSuccess) {
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
+TEST_F(ValidateConversion, BitcastSuccessSPV1p5) {
+  const std::string body = R"(
+%ptr = OpVariable %f32ptr_func Function
+%val1 = OpBitcast %u32 %ptr
+%val2 = OpBitcast %u64 %ptr
+%val3 = OpBitcast %f32ptr_func %u32_1
+%val4 = OpBitcast %f32ptr_wg %u64_1
+%val5 = OpBitcast %f32 %u32_1
+%val6 = OpBitcast %f32vec2 %u32vec2_12
+%val7 = OpBitcast %f32vec2 %u64_1
+%val8 = OpBitcast %f64 %u32vec2_12
+%val9 = OpBitcast %f32vec4 %f64vec2_12
+%val10 = OpBitcast %u32ptr_func %u32vec2_01
+%val11 = OpBitcast %u32vec2 %ptr
+)";
+
+  CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+}
+
+TEST_F(ValidateConversion, BitcastSuccessPhysicalStorageBufferKHR) {
+  const std::string body = R"(
+%ptr = OpVariable %f32ptr_func Function
+%val1 = OpBitcast %u32 %ptr
+%val2 = OpBitcast %u64 %ptr
+%val3 = OpBitcast %f32ptr_func %u32_1
+%val4 = OpBitcast %f32ptr_wg %u64_1
+%val5 = OpBitcast %f32 %u32_1
+%val6 = OpBitcast %f32vec2 %u32vec2_12
+%val7 = OpBitcast %f32vec2 %u64_1
+%val8 = OpBitcast %f64 %u32vec2_12
+%val9 = OpBitcast %f32vec4 %f64vec2_12
+%val10 = OpBitcast %u32ptr_func %u32vec2_01
+%val11 = OpBitcast %u32vec2 %ptr
+)";
+
+  CompileSuccessfully(
+      GenerateKernelCode(body,
+                         "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
+          .c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
 TEST_F(ValidateConversion, BitcastInputHasNoType) {
   const std::string body = R"(
 %val = OpBitcast %u32 %f32
@@ -1249,10 +1294,66 @@ TEST_F(ValidateConversion, BitcastPtrWrongInputType) {
 
   CompileSuccessfully(GenerateKernelCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("Expected input to be a pointer or int scalar if Result Type "
-                "is pointer: Bitcast"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected input to be a pointer or int scalar if "
+                        "Result Type is pointer: Bitcast"));
+}
+
+TEST_F(ValidateConversion, BitcastPtrWrongInputTypeSPV1p5) {
+  const std::string body = R"(
+%val = OpBitcast %u32ptr_func %f32_1
+)";
+
+  CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
+                        "int vector if Result Type is pointer: Bitcast"));
+}
+
+TEST_F(ValidateConversion, BitcastPtrWrongInputTypePhysicalStorageBufferKHR) {
+  const std::string body = R"(
+%val = OpBitcast %u32ptr_func %f32_1
+)";
+
+  CompileSuccessfully(
+      GenerateKernelCode(body,
+                         "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
+          .c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
+                        "int vector if Result Type is pointer: Bitcast"));
+}
+
+TEST_F(ValidateConversion, BitcastPtrWrongInputTypeIntVectorSPV1p5) {
+  const std::string body = R"(
+%val = OpBitcast %u32ptr_func %u64vec2_01
+)";
+
+  CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
+                        "int vector if Result Type is pointer: Bitcast"));
+}
+
+TEST_F(ValidateConversion,
+       BitcastPtrWrongInputTypeIntVectorPhysicalStorageBufferKHR) {
+  const std::string body = R"(
+%val = OpBitcast %u32ptr_func %u64vec2_01
+)";
+
+  CompileSuccessfully(
+      GenerateKernelCode(body,
+                         "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
+          .c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
+                        "int vector if Result Type is pointer: Bitcast"));
 }
 
 TEST_F(ValidateConversion, BitcastPtrWrongResultType) {
@@ -1262,11 +1363,66 @@ TEST_F(ValidateConversion, BitcastPtrWrongResultType) {
 
   CompileSuccessfully(GenerateKernelCode(body).c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "Pointer can only be converted to another pointer or int scalar: "
-          "Bitcast"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Pointer can only be converted to another pointer or "
+                        "int scalar: Bitcast"));
+}
+
+TEST_F(ValidateConversion, BitcastPtrWrongResultTypeSPV1p5) {
+  const std::string body = R"(
+%val = OpBitcast %f32 %f32inp
+)";
+
+  CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Pointer can only be converted to another pointer, int "
+                        "scalar or 32-bit int vector: Bitcast"));
+}
+
+TEST_F(ValidateConversion, BitcastPtrWrongResultTypePhysicalStorageBufferKHR) {
+  const std::string body = R"(
+%val = OpBitcast %f32 %f32inp
+)";
+
+  CompileSuccessfully(
+      GenerateKernelCode(body,
+                         "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
+          .c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Pointer can only be converted to another pointer, int "
+                        "scalar or 32-bit int vector: Bitcast"));
+}
+
+TEST_F(ValidateConversion, BitcastPtrWrongResultTypeIntVectorSPV1p5) {
+  const std::string body = R"(
+%val = OpBitcast %u64vec2 %f32inp
+)";
+
+  CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA,
+            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Pointer can only be converted to another pointer, int "
+                        "scalar or 32-bit int vector: Bitcast"));
+}
+
+TEST_F(ValidateConversion,
+       BitcastPtrWrongResultTypeIntVectorPhysicalStorageBufferKHR) {
+  const std::string body = R"(
+%val = OpBitcast %u64vec2 %f32inp
+)";
+
+  CompileSuccessfully(
+      GenerateKernelCode(body,
+                         "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
+          .c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Pointer can only be converted to another pointer, int "
+                        "scalar or 32-bit int vector: Bitcast"));
 }
 
 TEST_F(ValidateConversion, BitcastDifferentTotalBitWidth) {

+ 239 - 0
3rdparty/spirv-tools/test/val/val_decoration_test.cpp

@@ -6691,6 +6691,245 @@ TEST_F(ValidateDecorations, ComponentDecorationFunctionParameter) {
   EXPECT_THAT(getDiagnosticString(), Eq(""));
 }
 
+TEST_F(ValidateDecorations, VulkanStorageBufferBlock) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_storage_buffer_storage_class"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%struct = OpTypeStruct %uint
+%ptr_ssbo = OpTypePointer StorageBuffer %struct
+%var = OpVariable %ptr_ssbo StorageBuffer
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+}
+
+TEST_F(ValidateDecorations, VulkanStorageBufferMissingBlock) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_storage_buffer_storage_class"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%struct = OpTypeStruct %uint
+%ptr_ssbo = OpTypePointer StorageBuffer %struct
+%var = OpVariable %ptr_ssbo StorageBuffer
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables "
+                        "must be identified with a Block decoration"));
+}
+
+TEST_F(ValidateDecorations, VulkanStorageBufferArrayMissingBlock) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_storage_buffer_storage_class"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%uint_4 = OpConstant %uint 4
+%struct = OpTypeStruct %uint
+%array = OpTypeArray %struct %uint_4
+%ptr_ssbo = OpTypePointer StorageBuffer %array
+%var = OpVariable %ptr_ssbo StorageBuffer
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables "
+                        "must be identified with a Block decoration"));
+}
+
+TEST_F(ValidateDecorations, VulkanStorageBufferRuntimeArrayMissingBlock) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpCapability RuntimeDescriptorArrayEXT
+OpExtension "SPV_EXT_descriptor_indexing"
+OpExtension "SPV_KHR_storage_buffer_storage_class"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%struct = OpTypeStruct %uint
+%array = OpTypeRuntimeArray %struct
+%ptr_ssbo = OpTypePointer StorageBuffer %array
+%var = OpVariable %ptr_ssbo StorageBuffer
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables "
+                        "must be identified with a Block decoration"));
+}
+
+TEST_F(ValidateDecorations, VulkanUniformBlock) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%struct = OpTypeStruct %uint
+%ptr_ubo = OpTypePointer Uniform %struct
+%var = OpVariable %ptr_ubo Uniform
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+}
+
+TEST_F(ValidateDecorations, VulkanUniformBufferBlock) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+OpDecorate %struct BufferBlock
+OpMemberDecorate %struct 0 Offset 0
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%struct = OpTypeStruct %uint
+%ptr_ubo = OpTypePointer Uniform %struct
+%var = OpVariable %ptr_ubo Uniform
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+}
+
+TEST_F(ValidateDecorations, VulkanUniformMissingBlock) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%struct = OpTypeStruct %uint
+%ptr_ubo = OpTypePointer Uniform %struct
+%var = OpVariable %ptr_ubo Uniform
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be "
+                "identified with a Block or BufferBlock decoration"));
+}
+
+TEST_F(ValidateDecorations, VulkanUniformArrayMissingBlock) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%uint_4 = OpConstant %uint 4
+%struct = OpTypeStruct %uint
+%array = OpTypeArray %struct %uint_4
+%ptr_ubo = OpTypePointer Uniform %array
+%var = OpVariable %ptr_ubo Uniform
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be "
+                "identified with a Block or BufferBlock decoration"));
+}
+
+TEST_F(ValidateDecorations, VulkanUniformRuntimeArrayMissingBlock) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpCapability RuntimeDescriptorArrayEXT
+OpExtension "SPV_EXT_descriptor_indexing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%struct = OpTypeStruct %uint
+%array = OpTypeRuntimeArray %struct
+%ptr_ubo = OpTypePointer Uniform %array
+%var = OpVariable %ptr_ubo Uniform
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be "
+                "identified with a Block or BufferBlock decoration"));
+}
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools

+ 76 - 0
3rdparty/spirv-tools/test/val/val_entry_point.cpp

@@ -0,0 +1,76 @@
+// Copyright (c) 2019 Samsung Inc
+//
+// 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 <string>
+
+#include "gmock/gmock.h"
+#include "test/unit_spirv.h"
+#include "test/val/val_fixtures.h"
+
+namespace spvtools {
+namespace {
+
+using ::testing::Eq;
+using ::testing::HasSubstr;
+
+using ValidateEntryPoints = spvtest::ValidateBase<bool>;
+
+TEST_F(ValidateEntryPoints, DuplicateEntryPoints) {
+  const std::string body = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %3 "foo"
+OpEntryPoint GLCompute %4 "foo"
+%1 = OpTypeVoid
+%2 = OpTypeFunction %1
+%3 = OpFunction %1 None %2
+%20 = OpLabel
+OpReturn
+OpFunctionEnd
+%4 = OpFunction %1 None %2
+%21 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Entry points cannot share the same name"));
+}
+
+TEST_F(ValidateEntryPoints, UniqueEntryPoints) {
+  const std::string body = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %3 "foo"
+OpEntryPoint GLCompute %4 "foo2"
+%1 = OpTypeVoid
+%2 = OpTypeFunction %1
+%3 = OpFunction %1 None %2
+%20 = OpLabel
+OpReturn
+OpFunctionEnd
+%4 = OpFunction %1 None %2
+%21 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(body);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+}  // namespace
+}  // namespace spvtools

+ 95 - 1
3rdparty/spirv-tools/test/val/val_memory_test.cpp

@@ -2318,9 +2318,14 @@ OpExtension "SPV_EXT_descriptor_indexing"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %func "func"
 OpExecutionMode %func OriginUpperLeft
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
 %sampler_t = OpTypeSampler
+%uint = OpTypeInt 32 0
 %array_t = OpTypeRuntimeArray %sampler_t
-%array_sb_ptr = OpTypePointer StorageBuffer %array_t
+%struct = OpTypeStruct %uint
+%sb_array_t = OpTypeRuntimeArray %struct
+%array_sb_ptr = OpTypePointer StorageBuffer %sb_array_t
 %2 = OpVariable %array_sb_ptr StorageBuffer
 %array_uc_ptr = OpTypePointer UniformConstant %array_t
 %3 = OpVariable %array_uc_ptr UniformConstant
@@ -4292,6 +4297,95 @@ OpMemberDecorate %block 0 Offset 0
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
 }
 
+TEST_F(ValidateMemory, VulkanStorageBufferNotAStruct) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_storage_buffer_storage_class"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%ptr_ssbo = OpTypePointer StorageBuffer %uint
+%var = OpVariable %ptr_ssbo StorageBuffer
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("From Vulkan spec, section 14.5.2:\nVariables identified with "
+                "the StorageBuffer storage class are used to access "
+                "transparent buffer backed resources. Such variables must be "
+                "typed as OpTypeStruct, or an array of this type"));
+}
+
+TEST_F(ValidateMemory, VulkanStorageBufferRuntimeArrayNotAStruct) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpCapability RuntimeDescriptorArrayEXT
+OpExtension "SPV_KHR_storage_buffer_storage_class"
+OpExtension "SPV_EXT_descriptor_indexing"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%array = OpTypeRuntimeArray %uint
+%ptr_ssbo = OpTypePointer StorageBuffer %array
+%var = OpVariable %ptr_ssbo StorageBuffer
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("From Vulkan spec, section 14.5.2:\nVariables identified with "
+                "the StorageBuffer storage class are used to access "
+                "transparent buffer backed resources. Such variables must be "
+                "typed as OpTypeStruct, or an array of this type"));
+}
+
+TEST_F(ValidateMemory, VulkanStorageBufferArrayNotAStruct) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpExtension "SPV_KHR_storage_buffer_storage_class"
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%uint_4 = OpConstant %uint 4
+%array = OpTypeArray %uint %uint_4
+%ptr_ssbo = OpTypePointer StorageBuffer %array
+%var = OpVariable %ptr_ssbo StorageBuffer
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("From Vulkan spec, section 14.5.2:\nVariables identified with "
+                "the StorageBuffer storage class are used to access "
+                "transparent buffer backed resources. Such variables must be "
+                "typed as OpTypeStruct, or an array of this type"));
+}
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools

+ 41 - 3
3rdparty/spirv-tools/tools/fuzz/fuzz.cpp

@@ -104,6 +104,11 @@ Options (in lexicographical order):
                Path to an interestingness function to guide shrinking: a script
                that returns 0 if and only if a given binary is interesting.
                Required if --shrink is provided; disallowed otherwise.
+  --replay-validation
+               Run the validator after applying each transformation during
+               replay (including the replay that occurs during shrinking).
+               Aborts if an invalid binary is created.  Useful for debugging
+               spirv-fuzz.
   --version
                Display fuzzer version information.
 
@@ -161,6 +166,9 @@ FuzzStatus ParseFlags(int argc, const char** argv, std::string* in_binary_file,
                               sizeof("--interestingness=") - 1)) {
         const auto split_flag = spvtools::utils::SplitFlagArgs(cur_arg);
         *interestingness_function_file = std::string(split_flag.second);
+      } else if (0 == strncmp(cur_arg, "--replay-validation",
+                              sizeof("--replay-validation") - 1)) {
+        fuzzer_options->enable_replay_validation();
       } else if (0 == strncmp(cur_arg, "--shrink=", sizeof("--shrink=") - 1)) {
         const auto split_flag = spvtools::utils::SplitFlagArgs(cur_arg);
         *shrink_transformations_file = std::string(split_flag.second);
@@ -221,6 +229,16 @@ FuzzStatus ParseFlags(int argc, const char** argv, std::string* in_binary_file,
     return {FuzzActions::STOP, 1};
   }
 
+  if (replay_transformations_file->empty() &&
+      shrink_transformations_file->empty() &&
+      static_cast<spv_const_fuzzer_options>(*fuzzer_options)
+          ->replay_validation_enabled) {
+    spvtools::Error(FuzzDiagnostic, nullptr, {},
+                    "The --replay-validation argument can only be used with "
+                    "one of the --replay or --shrink arguments.");
+    return {FuzzActions::STOP, 1};
+  }
+
   if (!replay_transformations_file->empty()) {
     // A replay transformations file was given, thus the tool is being invoked
     // in replay mode.
@@ -278,6 +296,7 @@ bool ParseTransformations(
 }
 
 bool Replay(const spv_target_env& target_env,
+            spv_const_fuzzer_options fuzzer_options,
             const std::vector<uint32_t>& binary_in,
             const spvtools::fuzz::protobufs::FactSequence& initial_facts,
             const std::string& replay_transformations_file,
@@ -289,7 +308,8 @@ bool Replay(const spv_target_env& target_env,
                             &transformation_sequence)) {
     return false;
   }
-  spvtools::fuzz::Replayer replayer(target_env);
+  spvtools::fuzz::Replayer replayer(target_env,
+                                    fuzzer_options->replay_validation_enabled);
   replayer.SetMessageConsumer(spvtools::utils::CLIMessageConsumer);
   auto replay_result_status =
       replayer.Run(binary_in, initial_facts, transformation_sequence,
@@ -313,7 +333,8 @@ bool Shrink(const spv_target_env& target_env,
     return false;
   }
   spvtools::fuzz::Shrinker shrinker(target_env,
-                                    fuzzer_options->shrinker_step_limit);
+                                    fuzzer_options->shrinker_step_limit,
+                                    fuzzer_options->replay_validation_enabled);
   shrinker.SetMessageConsumer(spvtools::utils::CLIMessageConsumer);
 
   spvtools::fuzz::Shrinker::InterestingnessFunction interestingness_function =
@@ -362,6 +383,23 @@ bool Fuzz(const spv_target_env& target_env,
 
 }  // namespace
 
+// Dumps |binary| to file |filename|. Useful for interactive debugging.
+void DumpShader(const std::vector<uint32_t>& binary, const char* filename) {
+  auto write_file_succeeded =
+      WriteFile(filename, "wb", &binary[0], binary.size());
+  if (!write_file_succeeded) {
+    std::cerr << "Failed to dump shader" << std::endl;
+  }
+}
+
+// Dumps the SPIRV-V module in |context| to file |filename|. Useful for
+// interactive debugging.
+void DumpShader(spvtools::opt::IRContext* context, const char* filename) {
+  std::vector<uint32_t> binary;
+  context->module()->ToBinary(&binary, false);
+  DumpShader(binary, filename);
+}
+
 const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_3;
 
 int main(int argc, const char** argv) {
@@ -418,7 +456,7 @@ int main(int argc, const char** argv) {
       }
       break;
     case FuzzActions::REPLAY:
-      if (!Replay(target_env, binary_in, initial_facts,
+      if (!Replay(target_env, fuzzer_options, binary_in, initial_facts,
                   replay_transformations_file, &binary_out,
                   &transformations_applied)) {
         return 1;

+ 25 - 0
3rdparty/spirv-tools/tools/sva/.eslintrc.json

@@ -0,0 +1,25 @@
+{
+    "env": {
+        "browser": true,
+        "es6": true,
+        "node": true,
+        "mocha": true
+    },
+    "extends": "eslint:recommended",
+    "parserOptions": {
+        "ecmaVersion": 2018,
+        "sourceType": "module"
+    },
+    "rules": {
+        "block-scoped-var": "error",
+        "consistent-return": "error",
+        "eqeqeq": ["error", "always"],
+        "indent": [ "error", 2 ],
+        "linebreak-style": [ "error", "unix" ],
+        "no-eval": "error",
+        "no-shadow": "error",
+        "no-shadow-restricted-names": "error",
+        "quotes": [ "error", "double" ],
+        "semi": [ "error", "always" ]
+    }
+}

+ 6 - 0
3rdparty/spirv-tools/tools/sva/.gitignore

@@ -0,0 +1,6 @@
+.DS_Store
+node_modules
+third_party/spirv-headers
+o.sva
+build
+yarn-error.log

+ 41 - 0
3rdparty/spirv-tools/tools/sva/README.md

@@ -0,0 +1,41 @@
+# SVA
+
+SPIR-V Assember for WebGPU. The SPIR-V Assembler is a JavaScript library to
+convert SPIR-V assembly (as produced by spirv-dis in SPIR-V Tools) into a
+SPIR-V binary. The assembler assumes it is generating WebGPU SPIR-V and thus has
+the following limitations.
+
+ * Only 32 bit integers and floats supported
+ * Only GLSL accepted as an extended instruction set
+ * Doesn't support ! syntax for integers
+ * Doesn't support hex encoding for float
+
+```shell
+yarn install
+yarn test
+```
+
+You can also use `yarn watch` to watch all of the files and re-run tests as
+needed.
+
+## Webserver
+Using `yarn serve` will start a webserver on localhost:5000. If you load the
+`tests/index.html` file this will load the SVA files into browser.
+
+## Command Line
+There is a simple assembler binary with can be executed from the command line.
+
+```shell
+yarn sva tests/simple.spv_asm
+```
+
+The above will generate a `o.sva` file in the current directory.
+
+## Update spirv.data.json
+
+If there is a new spirv-headers release update the externals folder checkout
+and then:
+
+```shell
+./tools/process_grammar.rb > src/spirv.data.json
+```

+ 32 - 0
3rdparty/spirv-tools/tools/sva/bin/sva.js

@@ -0,0 +1,32 @@
+#!/usr/bin/env node
+//
+// Copyright 2019 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.
+
+"use strict";
+
+const fs = require("fs");
+
+import SVA from "../src/sva.js";
+
+let input = fs.readFileSync(process.argv[2], "utf-8");
+let u = SVA.assemble(input);
+
+if (typeof u === "string") {
+  console.log(u);
+} else {
+  fs.writeFileSync("o.sva", new Buffer(u.buffer), (err) => {
+    console.log(["ERROR", err]);
+  });
+}

+ 1 - 0
3rdparty/spirv-tools/tools/sva/mocha.opts

@@ -0,0 +1 @@
+--recursive

+ 25 - 0
3rdparty/spirv-tools/tools/sva/package.json

@@ -0,0 +1,25 @@
+{
+  "name": "sva",
+  "version": "0.1.0",
+  "description": "SPIR-V Assembler",
+  "main": "index.js",
+  "author": "dan sinclair <[email protected]>",
+  "license": "Apache-2.0",
+  "private": true,
+  "scripts": {
+    "sva": "node -r esm bin/sva.js",
+    "lint": "eslint --fix --ext .js .",
+    "test": "mocha --require esm src/**/*_test.js",
+    "watch": "mocha --require esm --watch --watch-extension js \"src/**/*_test.js\"",
+    "serve": "serve",
+    "bundle": "rollup -c"
+  },
+  "devDependencies": {
+    "chai": "^4.2.0",
+    "eslint": "^6.3.0",
+    "esm": "^3.2.25",
+    "mocha": "^6.2.0",
+    "rollup": "^1.21.4",
+    "serve": "^11.1.0"
+  }
+}

+ 7 - 0
3rdparty/spirv-tools/tools/sva/rollup.config.js

@@ -0,0 +1,7 @@
+export default {
+  input: 'src/sva.js',
+  output: {
+    file: 'build/sva.js',
+    format: 'esm',
+  }
+}

+ 98 - 0
3rdparty/spirv-tools/tools/sva/src/assembler.js

@@ -0,0 +1,98 @@
+// Copyright 2019 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.
+
+export default class Assembler {
+  static get GENERATOR_ID() { return 0; }
+
+  /**
+   * @param {AST} the AST to build the SPIR-V from
+   */
+  constructor(ast) {
+    this.ast_ = ast;
+  }
+
+  /**
+   * Assembles the AST into binary SPIR-V.
+   * @return {Uint32Array} The SPIR-V binary data.
+   */
+  assemble() {
+    let total_size = 5;
+    for (const inst of this.ast_.instructions()) {
+      total_size += 1;
+      for (const op of inst.operands()) {
+        total_size += op.length();
+      }
+    }
+
+    let u = new Uint32Array(total_size);
+    u[0] = 0x07230203;  // Magic
+    u[1] = 0x00010500;  // Version 1.5
+    u[2] = Assembler.GENERATOR_ID;  // Generator magic number
+    u[3] = this.ast_.getIdBounds();  // ID bounds
+    u[4] = 0;  // Reserved
+
+    let idx = 5;
+    for (const inst of this.ast_.instructions()) {
+      let op_size = 1;
+      for (const op of inst.operands()) {
+        op_size += op.length();
+      }
+
+      u[idx++] = op_size << 16 | inst.opcode();
+      for (const op of inst.operands()) {
+        idx = this.processOp(u, idx, op);
+      }
+    }
+
+    return u;
+  }
+
+  processOp(u, idx, op) {
+    if (op.type() === "string") {
+      let len = 0;
+      let v = 0;
+      for (const ch of op.value()) {
+        v = v | (ch.charCodeAt(0) << (len * 8));
+        len += 1;
+
+        if (len === 4) {
+          u[idx++] = v;
+          len = 0;
+          v = 0;
+        }
+      }
+      // Make sure either the terminating 0 byte is written or the last
+      // partial word is written.
+      u[idx++] = v;
+
+    } else if (op.type() === "float") {
+      // TODO(dsinclair): Handle 64 bit floats ...
+      let b = new ArrayBuffer(4);
+      let f = new Float32Array(b);
+      f[0] = op.value();
+
+      let u2 = new Uint32Array(b);
+
+      u[idx++] = u2[0];
+    } else {
+      u[idx++] = op.value();
+    }
+
+    for (const param of op.params()) {
+      idx = this.processOp(u, idx, param);
+    }
+
+    return idx;
+  }
+}

+ 165 - 0
3rdparty/spirv-tools/tools/sva/src/assembler_test.js

@@ -0,0 +1,165 @@
+// Copyright 2019 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.
+
+import { assert } from "chai";
+import Lexer from "./lexer";
+import Parser from "./parser";
+import grammar from "./spirv.data.js";
+import Assembler from "./assembler";
+
+describe("assembler", () => {
+  it("generates SPIR-V magic number", () => {
+    let input = `; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 6
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main"
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 440
+               OpName %main "main"
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd`;
+    let l = new Lexer(input);
+    let p = new Parser(grammar, l);
+
+    let ast = p.parse();
+    assert.exists(ast, p.error);
+
+    let a = new Assembler(ast);
+    let res = a.assemble();
+    assert.equal(res[0], 0x07230203);
+  });
+
+  it("assembles enumerant params", () => {
+    let input = "OpExecutionMode %main LocalSize 2 3 4";
+
+    let l = new Lexer(input);
+    let p = new Parser(grammar, l);
+
+    let ast = p.parse();
+    assert.exists(ast, p.error);
+
+    let a = new Assembler(ast);
+    let res = a.assemble();
+
+    assert.lengthOf(res, 11);
+    assert.equal(res[5], (6 /* word count */ << 16) | 16 /* opcode */);
+    assert.equal(res[6], 1 /* %main */);
+    assert.equal(res[7], 17 /* LocalSize */);
+    assert.equal(res[8], 2);
+    assert.equal(res[9], 3);
+    assert.equal(res[10], 4);
+  });
+
+  it("assembles float 32 values", () => {
+    let input = `%float = OpTypeFloat 32
+                 %float1 = OpConstant %float 0.400000006`;
+    let l = new Lexer(input);
+    let p = new Parser(grammar, l);
+
+    let ast = p.parse();
+    assert.exists(ast, p.error);
+
+    let a = new Assembler(ast);
+    let res = a.assemble();
+
+    assert.lengthOf(res, 12);
+    assert.equal(res[8], (4 /* word count */ << 16) | 43 /* opcode */);
+    assert.equal(res[9], 1 /* %float */);
+    assert.equal(res[10], 2 /* %float */);
+    assert.equal(res[11], 0x3ecccccd /* 0.400000006 */);
+  });
+
+  describe("strings", () => {
+    it("assembles 'abcd'", () => {
+      let input = `OpName %mains "abcd"`;
+      let l = new Lexer(input);
+      let p = new Parser(grammar, l);
+
+      let ast = p.parse();
+      assert.exists(ast, p.error);
+
+      let a = new Assembler(ast);
+      let res = a.assemble();
+
+      assert.lengthOf(res, 9);
+      assert.equal(res[5], (4 /* word count */ << 16) | 5 /* opcode */);
+      assert.equal(res[6], 1 /* %mains */);
+      assert.equal(res[7], 0x64636261 /* food */);
+      assert.equal(res[8], 0x00000000 /* null byte */);
+    });
+
+    it("assembles 'abcde'", () => {
+      let input = `OpName %mains "abcde"`;
+      let l = new Lexer(input);
+      let p = new Parser(grammar, l);
+
+      let ast = p.parse();
+      assert.exists(ast, p.error);
+
+      let a = new Assembler(ast);
+      let res = a.assemble();
+
+      assert.lengthOf(res, 9);
+      assert.equal(res[5], (4 /* word count */ << 16) | 5 /* opcode */);
+      assert.equal(res[6], 1 /* %mains */);
+      assert.equal(res[7], 0x64636261 /* abcd */);
+      assert.equal(res[8], 0x00000065 /* e */);
+    });
+
+    it("assembles 'abcdef'", () => {
+      let input = `OpName %mains "abcdef"`;
+      let l = new Lexer(input);
+      let p = new Parser(grammar, l);
+
+      let ast = p.parse();
+      assert.exists(ast, p.error);
+
+      let a = new Assembler(ast);
+      let res = a.assemble();
+
+      assert.lengthOf(res, 9);
+      assert.equal(res[5], (4 /* word count */ << 16) | 5 /* opcode */);
+      assert.equal(res[6], 1 /* %mains */);
+      assert.equal(res[7], 0x64636261 /* abcd */);
+      assert.equal(res[8], 0x00006665 /* ef */);
+    });
+
+    it("assembles 'abcdefg'", () => {
+      let input = `OpName %mains "abcdefg"`;
+      let l = new Lexer(input);
+      let p = new Parser(grammar, l);
+
+      let ast = p.parse();
+      assert.exists(ast, p.error);
+
+      let a = new Assembler(ast);
+      let res = a.assemble();
+
+      assert.lengthOf(res, 9);
+      assert.equal(res[5], (4 /* word count */ << 16) | 5 /* opcode */);
+      assert.equal(res[6], 1 /* %mains */);
+      assert.equal(res[7], 0x64636261 /* abcd */);
+      assert.equal(res[8], 0x00676665 /* efg */);
+    });
+  });
+});

+ 141 - 0
3rdparty/spirv-tools/tools/sva/src/ast.js

@@ -0,0 +1,141 @@
+// Copyright 2019 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.
+
+class Module {
+  constructor() {
+    this.instructions_ = [];
+    this.next_id_ = 1;
+
+    /**
+     * Maps {string, hash} where the string is the type name and the hash is:
+     *   type- 'float' or 'int'
+     *   width- number of bits needed to store number
+     *   signed- the sign of the number
+     */
+    this.types_ = {};
+
+    /**
+     * Maps {string, number} where the string is the type name and the number is
+     * the id value.
+     */
+    this.assigned_ids_ = {};
+  }
+
+  instructions() { return this.instructions_; }
+
+  instruction(val) { return this.instructions_[val]; }
+
+  addInstruction(inst) {
+    this.instructions_.push(inst);
+
+    // Record type information
+    if (inst.name() === "OpTypeInt" || inst.name() === "OpTypeFloat") {
+      let is_int = inst.name() === "OpTypeInt";
+
+      this.types_[inst.operand(0).name()] = {
+        type: is_int ? "int" : "float",
+        width: inst.operand(1).value(),
+        signed: is_int ? inst.operand(2).value() : 1
+      };
+    }
+
+    // Record operand result id's
+    inst.operands().forEach((op) => {
+      if (op.rawValue() !== undefined && op.type() === "result_id") {
+        this.next_id_ = Math.max(this.next_id_, op.rawValue() + 1);
+      }
+    });
+  }
+
+  getType(name) { return this.types_[name]; }
+
+  getId(name) {
+    if (this.assigned_ids_[name] !== undefined) {
+      return this.assigned_ids_[name];
+    }
+
+    let next = this.next_id_;
+    this.assigned_ids_[name] = next;
+
+    this.next_id_ += 1;
+    return next;
+  }
+
+  getIdBounds() { return this.next_id_; }
+}
+
+class Instruction {
+  constructor(name, opcode, operands) {
+    this.name_ = name;
+    this.opcode_ = opcode;
+    this.operands_ = operands;
+  }
+
+  name() { return this.name_; }
+
+  opcode() { return this.opcode_; }
+
+  operands() { return this.operands_; }
+
+  operand(val) { return this.operands_[val]; }
+}
+
+class Operand {
+  constructor(mod, name, type, value, params) {
+    this.module_ = mod;
+    this.name_ = name;
+    this.type_ = type;
+    this.value_ = value;
+    this.params_ = params;
+  }
+
+  name() { return this.name_; }
+
+  length() {
+    // Get the value just to force it to be filled.
+    this.value();
+
+    if (this.type_ === "string") {
+      return Math.ceil((this.value_.length + 1) / 4);
+    }
+
+    let size = 1;
+    for (const param of this.params_) {
+      size += param.length();
+    }
+    return size;
+  }
+
+  type() { return this.type_; }
+
+  rawValue() { return this.value_; }
+
+  // This method should only be called on ResultId's after the full parse is
+  // complete. This is because the AST will only have the maximum seen numeric
+  // ResultId when the parse is done.
+  value() {
+    if (this.value_ === undefined) {
+      this.value_ = this.module_.getId(this.name_);
+    }
+    return this.value_;
+  }
+
+  params() { return this.params_; }
+}
+
+export {
+  Module,
+  Instruction,
+  Operand
+};

+ 363 - 0
3rdparty/spirv-tools/tools/sva/src/lexer.js

@@ -0,0 +1,363 @@
+// Copyright 2019 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.
+
+import { Token, TokenType } from "./token.js";
+
+export default class Lexer {
+  /**
+   * @param {String} input The input string to tokenize.
+   */
+  constructor(input) {
+    this.input_ = input;
+    this.len_ = input.length;
+    this.cur_pos_ = 0;
+    this.cur_line_ = 1;
+
+    this.num_regex_ = /^[0-9]+$/;
+    this.alpha_regex_ = /^[a-zA-Z_]+$/;
+    this.op_regex_ = /^Op[A-Z][^\s]*$/;
+    this.hex_regex_ = /^[0-9a-fA-F]$/;
+  }
+
+  /**
+   * Parses the next token from the input stream.
+   * @return {Token} the next token.
+   */
+  next() {
+    this.skipWhitespace();
+    this.skipComments();
+
+    if (this.cur_pos_ >= this.len_)
+      return new Token(TokenType.kEOF, this.cur_line_);
+
+    let n = this.tryHexInteger();
+    if (n !== undefined)
+      return n;
+
+    n = this.tryFloat();
+    if (n !== undefined)
+      return n;
+
+    n = this.tryInteger();
+    if (n !== undefined)
+      return n;
+
+    n = this.tryString();
+    if (n !== undefined)
+      return n;
+
+    n = this.tryOp();
+    if (n !== undefined)
+      return n;
+
+    n = this.tryPunctuation();
+    if (n !== undefined)
+      return n;
+
+    n = this.tryResultId();
+    if (n !== undefined)
+      return n;
+
+    n = this.tryIdent();
+    if (n !== undefined)
+      return n;
+
+    return new Token(TokenType.kError, this.cur_line_, "Failed to match token");
+  }
+
+  is(str) {
+    if (this.len_ <= this.cur_pos_ + (str.length - 1))
+      return false;
+
+    for (let i = 0; i < str.length; ++i) {
+      if (this.input_[this.cur_pos_ + i] !== str[i])
+        return false;
+    }
+
+    return true;
+  }
+
+  isNum(ch) {
+    return ch.match(this.num_regex_);
+  }
+
+  isAlpha(ch) {
+    return ch.match(this.alpha_regex_);
+  }
+
+  isAlphaNum(ch) {
+    return this.isNum(ch) || this.isAlpha(ch);
+  }
+
+  isHex(char) {
+    return char.match(this.hex_regex_);
+  }
+
+  isCurWhitespace() {
+    return this.is(" ") || this.is("\t") || this.is("\r") || this.is("\n");
+  }
+
+  skipWhitespace() {
+    for(;;) {
+      let cur_pos = this.cur_pos_;
+      while (this.cur_pos_ < this.len_ &&
+          this.isCurWhitespace()) {
+        if (this.is("\n"))
+          this.cur_line_ += 1;
+
+        this.cur_pos_ += 1;
+      }
+
+      this.skipComments();
+
+      // Cursor didn't move so no whitespace matched.
+      if (cur_pos === this.cur_pos_)
+        break;
+    }
+  }
+
+  skipComments() {
+    if (!this.is(";"))
+      return;
+
+    while (this.cur_pos_ < this.len_ && !this.is("\n"))
+      this.cur_pos_ += 1;
+  }
+
+  /**
+   * Attempt to parse the next part of the input as a float.
+   * @return {Token|undefined} returns a Token if a float is matched,
+   *                           undefined otherwise.
+   */
+  tryFloat() {
+    let start = this.cur_pos_;
+    let end = start;
+
+    if (this.cur_pos_ >= this.len_)
+      return undefined;
+    if (this.input_[end] === "-")
+      end += 1;
+
+    while (end < this.len_ && this.isNum(this.input_[end]))
+      end += 1;
+
+    // Must have a "." in a float
+    if (end >= this.len_ || this.input_[end] !== ".")
+      return undefined;
+
+    end += 1;
+    while (end < this.len_ && this.isNum(this.input_[end]))
+      end += 1;
+
+    let substr = this.input_.substr(start, end - start);
+    if (substr === "." || substr === "-.")
+      return undefined;
+
+    this.cur_pos_ = end;
+
+    return new Token(TokenType.kFloatLiteral, this.cur_line_, parseFloat(substr));
+  }
+
+  /**
+   * Attempt to parse a hex encoded integer.
+   * @return {Token|undefined} returns a Token if a Hex number is matched,
+   *                           undefined otherwise.
+   */
+  tryHexInteger() {
+    let start = this.cur_pos_;
+    let end = start;
+
+    if (this.cur_pos_ >= this.len_)
+      return undefined;
+    if (end + 2 >= this.len_ || this.input_[end] !== "0" ||
+        this.input_[end + 1] !== "x") {
+      return undefined;
+    }
+
+    end += 2;
+
+    while (end < this.len_ && this.isHex(this.input_[end]))
+      end += 1;
+
+    this.cur_pos_ = end;
+
+    let val = parseInt(this.input_.substr(start, end - start), 16);
+    return new Token(TokenType.kIntegerLiteral, this.cur_line_, val);
+  }
+
+  /**
+   * Attempt to parse an encoded integer.
+   * @return {Token|undefined} returns a Token if a number is matched,
+   *                           undefined otherwise.
+   */
+  tryInteger() {
+    let start = this.cur_pos_;
+    let end = start;
+
+    if (this.cur_pos_ >= this.len_)
+      return undefined;
+    if (this.input_[end] === "-")
+      end += 1;
+
+    if (end >= this.len_ || !this.isNum(this.input_[end]))
+      return undefined;
+
+    while (end < this.len_ && this.isNum(this.input_[end]))
+      end += 1;
+
+    this.cur_pos_ = end;
+
+    let val = parseInt(this.input_.substr(start, end - start), 10);
+    return new Token(TokenType.kIntegerLiteral, this.cur_line_, val);
+  }
+
+  /**
+   * Attempt to parse a result id.
+   * @return {Token|undefined} returns a Token if a result id is matched,
+   *                           undefined otherwise.
+   */
+  tryResultId() {
+    let start = this.cur_pos_;
+    if (start >= this.len_)
+      return undefined;
+    if (!this.is("%"))
+      return undefined;
+
+    start += 1;
+    this.cur_pos_ += 1;
+    while (this.cur_pos_ < this.len_ &&
+        (this.isAlphaNum(this.input_[this.cur_pos_]) || this.is("_"))) {
+      this.cur_pos_ += 1;
+    }
+
+    let ident = this.input_.substr(start, this.cur_pos_ - start);
+    let value = undefined;
+    if (ident.match(this.num_regex_))
+      value = parseInt(ident, 10);
+
+    return new Token(TokenType.kResultId, this.cur_line_, {
+      name: ident,
+      val: value
+    });
+  }
+
+  /**
+   * Attempt to parse an identifier.
+   * @return {Token|undefined} returns a Token if an identifier is matched,
+   *                           undefined otherwise.
+   */
+  tryIdent() {
+    let start = this.cur_pos_;
+    if (start >= this.len_)
+      return undefined;
+
+    while (this.cur_pos_ < this.len_ &&
+        (this.isAlphaNum(this.input_[this.cur_pos_]) || this.is("_"))) {
+      this.cur_pos_ += 1;
+    }
+
+    let ident = this.input_.substr(start, this.cur_pos_ - start);
+    return new Token(TokenType.kIdentifier, this.cur_line_, ident);
+  }
+
+  /**
+   * Attempt to parse an Op command.
+   * @return {Token|undefined} returns a Token if an Op command is matched,
+   *                           undefined otherwise.
+   */
+  tryOp() {
+    let start = this.cur_pos_;
+    if (this.cur_pos_ >= this.len_ || (this.cur_pos_ + 1 >= this.len_))
+      return undefined;
+
+    if (this.input_[this.cur_pos_] !== "O" ||
+        this.input_[this.cur_pos_ + 1] !== "p") {
+      return undefined;
+    }
+
+    while (this.cur_pos_ < this.len_ &&
+        !this.isCurWhitespace()) {
+      this.cur_pos_ += 1;
+    }
+
+    return new Token(TokenType.kOp, this.cur_line_, {
+      name: this.input_.substr(start, this.cur_pos_ - start)
+    });
+  }
+
+  /**
+   * Attempts to match punctuation strings against the input
+   * @return {Token|undefined} Returns the Token for the punctuation or
+   *                           undefined if no matches found.
+   */
+  tryPunctuation() {
+    let type = undefined;
+    if (this.is("="))
+      type = TokenType.kEqual;
+    else if (this.is("|"))
+      type = TokenType.kPipe;
+
+    if (type === undefined)
+      return undefined;
+
+    this.cur_pos_ += type.length;
+    return new Token(type, this.cur_line_, type);
+  }
+
+  /**
+   * Attempts to match strings against the input
+   * @return {Token|undefined} Returns the Token for the string or undefined
+   *                           if no match found.
+   */
+  tryString() {
+    let start = this.cur_pos_;
+
+    // Must have at least 2 chars for a string.
+    if (this.cur_pos_ >= this.len_ || (this.cur_pos_ + 1 >= this.len_))
+      return undefined;
+    if (!this.is("\""))
+      return undefined;
+
+    this.cur_pos_ += 1;
+    let str = "";
+    while (this.cur_pos_ <= this.len_) {
+      if (this.is("\""))
+        break;
+
+      if (this.is("\\")) {
+        this.cur_pos_ += 1;
+        if (this.cur_pos_ >= this.len_)
+          return undefined;
+
+        if (this.is("\\")) {
+          str += "\\";
+        } else if (this.is("\"")) {
+          str += '"';
+        } else {
+          str += this.input_[this.cur_pos_];
+        }
+      } else {
+        str += this.input_[this.cur_pos_];
+      }
+      this.cur_pos_ += 1;
+    }
+
+    if (this.cur_pos_ >= this.len_)
+      return undefined;
+
+    this.cur_pos_ += 1;
+
+    return new Token(TokenType.kStringLiteral, this.cur_line_, str);
+  }
+}

+ 191 - 0
3rdparty/spirv-tools/tools/sva/src/lexer_test.js

@@ -0,0 +1,191 @@
+// Copyright 2019 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.
+
+import { assert } from "chai";
+import Lexer from "./lexer";
+import { TokenType } from "./token";
+
+describe("lexer", () => {
+  describe("skipped content", () => {
+    it("skips whitespace", () => {
+      let input = " \t\r\n\t  \tOpKill\t\n\t  \r  ";
+      let l = new Lexer(input);
+
+      let t = l.next();
+      assert.equal(t.type, TokenType.kOp);
+      assert.equal(t.line, 2);
+      assert.equal(t.data.name, "OpKill");
+
+      t = l.next();
+      assert.equal(t.type, TokenType.kEOF);
+      assert.equal(t.line, 3);
+    });
+
+    it("skips ; comments", () => {
+      let input = `; start with comment
+OpKill ; end of line comment
+; another comment
+%1`;
+
+      let l = new Lexer(input);
+      let t = l.next();
+      assert.equal(t.type, TokenType.kOp);
+      assert.equal(t.data.name, "OpKill");
+      assert.equal(t.line, 2);
+
+      t = l.next();
+      assert.equal(t.type, TokenType.kResultId);
+      assert.equal(t.data.name, "1");
+      assert.equal(t.data.val, 1);
+      assert.equal(t.line, 4);
+    });
+  });
+
+  describe("numerics", () => {
+    it("parses floats", () => {
+      let input = ["0.0", "0.", ".0", "5.7", "5.", ".7", "-0.0", "-.0",
+        "-0.", "-5.7", "-5.", "-.7"];
+
+      let results = [0.0, 0.0, 0.0, 5.7, 5.0, 0.7, 0.0, 0.0, 0.0, -5.7, -5.0,
+        -0.7];
+      input.forEach((val, idx) => {
+        let l = new Lexer(val);
+        let t = l.next();
+
+        assert.equal(t.type, TokenType.kFloatLiteral,
+          `expected ${val} to be a float got ${t.type}`);
+        assert.equal(t.data, results[idx],
+          `expected ${results[idx]} === ${t.data}`);
+
+        t = l.next();
+        assert.equal(t.type, TokenType.kEOF);
+        assert.equal(t.data, undefined);
+      });
+    });
+
+    it("handles invalid floats", () => {
+      let input = [".", "-."];
+      input.forEach((val) => {
+        let l = new Lexer(val);
+        let t = l.next();
+
+        assert.notEqual(t.type, TokenType.kFloatLiteral,
+          `expect ${val} to not match type float`);
+      });
+    });
+
+    it("parses integers", () => {
+      let input = ["0", "-0", "123", "-123", "2147483647", "-2147483648",
+        "4294967295", "0x00", "0x24"];
+      let results = [0, 0, 123, -123,2147483647, -2147483648, 4294967295,
+        0x0, 0x24];
+
+      input.forEach((val, idx) => {
+        let l = new Lexer(val);
+        let t = l.next();
+
+        assert.equal(t.type, TokenType.kIntegerLiteral,
+          `expected ${val} to be an integer got ${t.type}`);
+        assert.equal(t.data, results[idx],
+          `expected ${results[idx]} === ${t.data}`);
+
+        t = l.next();
+        assert.equal(t.type, TokenType.kEOF);
+        assert.equal(t.data, undefined);
+      });
+    });
+  });
+
+  it("matches result_ids", () => {
+    let input = `%123
+%001
+%main
+%_a_b_c`;
+
+    let result = [
+      {name: "123", val: 123},
+      {name: "001", val: 1},
+      {name: "main", val: undefined},
+      {name: "_a_b_c", val: undefined}
+    ];
+
+    let l = new Lexer(input);
+    for (let i = 0; i < result.length; ++i) {
+      let t = l.next();
+      assert.equal(t.type, TokenType.kResultId);
+      assert.equal(t.data.name, result[i].name);
+      assert.equal(t.data.val, result[i].val);
+    }
+  });
+
+  it("matches punctuation", () => {
+    let input = "=";
+    let results = [TokenType.kEqual];
+
+    let l = new Lexer(input);
+    for (let i = 0; i < results.length; ++i) {
+      let t = l.next();
+      assert.equal(t.type, results[i]);
+      assert.equal(t.line, i + 1);
+    }
+
+    let t = l.next();
+    assert.equal(t.type, TokenType.kEOF);
+  });
+
+  describe("strings", () => {
+    it("matches strings", () => {
+      let input = "\"GLSL.std.450\"";
+
+      let l = new Lexer(input);
+      let t = l.next();
+      assert.equal(t.type, TokenType.kStringLiteral);
+      assert.equal(t.data, "GLSL.std.450");
+    });
+
+    it("handles unfinished strings", () => {
+      let input = "\"GLSL.std.450";
+
+      let l = new Lexer(input);
+      let t = l.next();
+      assert.equal(t.type, TokenType.kError);
+    });
+
+    it("handles escapes", () => {
+      let input = `"embedded\\"quote"
+"embedded\\\\slash"
+"embedded\\nchar"`;
+      let results = [`embedded\"quote`, `embedded\\slash`, `embeddednchar`];
+
+      let l = new Lexer(input);
+      for (let i = 0; i < results.length; ++i) {
+        let t = l.next();
+        assert.equal(t.type, TokenType.kStringLiteral, results[i]);
+        assert.equal(t.data, results[i]);
+      }
+    });
+  });
+
+  it("matches keywords", () => {
+    let input = "GLSL Function";
+    let results = ["GLSL", "Function"];
+
+    let l = new Lexer(input);
+    for (let i = 0; i < results.length; ++i) {
+      let t = l.next();
+      assert.equal(t.type, TokenType.kIdentifier, results[i]);
+      assert.equal(t.data, results[i]);
+    }
+  });
+});

+ 277 - 0
3rdparty/spirv-tools/tools/sva/src/parser.js

@@ -0,0 +1,277 @@
+// Copyright 2019 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.
+
+import { TokenType } from "./token.js";
+import * as AST from "./ast.js";
+
+export default class Parser {
+  /**
+   * @param {Hash} The SPIR-V grammar
+   * @param {Lexer} The lexer
+   * @return {AST} Attempts to build an AST from the tokens returned by the
+   *               given lexer
+   */
+  constructor(grammar, lexer) {
+    this.grammar_ = grammar;
+    this.lexer_ = lexer;
+
+    this.peek_ = [];
+    this.error_ = "";
+  }
+
+  get error() { return this.error_; }
+
+  next() {
+    return this.peek_.shift() || this.lexer_.next();
+  }
+
+  peek(idx) {
+    while (this.peek_.length <= idx) {
+      this.peek_.push(this.lexer_.next());
+    }
+    return this.peek_[idx];
+  }
+
+  /**
+   * Executes the parser.
+   *
+   * @return {AST|undefined} returns a parsed AST on success or undefined
+   *                         on error. The error message can be retrieved by
+   *                         calling error().
+   */
+  parse() {
+    let ast = new AST.Module();
+    for(;;) {
+      let token = this.next();
+      if (token === TokenType.kError) {
+        this.error_ = token.line() + ": " + token.data();
+        return undefined;
+      }
+      if (token.type === TokenType.kEOF)
+        break;
+
+      let result_id = undefined;
+      if (token.type === TokenType.kResultId) {
+        result_id = token;
+
+        token = this.next();
+        if (token.type !== TokenType.kEqual) {
+          this.error_ = token.line + ": expected = after result id";
+          return undefined;
+        }
+
+        token = this.next();
+      }
+
+      if (token.type !== TokenType.kOp) {
+        this.error_ = token.line + ": expected Op got " + token.type;
+        return undefined;
+      }
+
+      let name = token.data.name;
+      let data = this.getInstructionData(name);
+      let operands = [];
+      let result_type = undefined;
+
+      for (let operand of data.operands) {
+        if (operand.kind === "IdResult") {
+          if (result_id === undefined) {
+            this.error_ = token.line + ": expected result id";
+            return undefined;
+          }
+          let o = new AST.Operand(ast, result_id.data.name, "result_id",
+            result_id.data.val, []);
+          if (o === undefined) {
+            return undefined;
+          }
+          operands.push(o);
+        } else {
+          if (operand.quantifier === "?") {
+            if (this.nextIsNewInstr()) {
+              break;
+            }
+          } else if (operand.quantifier === "*") {
+            while (!this.nextIsNewInstr()) {
+              let o = this.extractOperand(ast, result_type, operand);
+              if (o === undefined) {
+                return undefined;
+              }
+              operands.push(o);
+            }
+            break;
+          }
+
+          let o = this.extractOperand(ast, result_type, operand);
+          if (o === undefined) {
+            return undefined;
+          }
+
+          // Store the result type away so we can use it for context dependent
+          // numbers if needed.
+          if (operand.kind === "IdResultType") {
+            result_type = ast.getType(o.name());
+          }
+
+          operands.push(o);
+        }
+      }
+
+      // Verify only GLSL extended instructions are used
+      if (name === "OpExtInstImport" && operands[1].value() !== "GLSL.std.450") {
+        this.error_ = token.line + ": Only GLSL.std.450 external instructions supported";
+        return undefined;
+      }
+
+      let inst = new AST.Instruction(name, data.opcode, operands);
+
+      ast.addInstruction(inst);
+    }
+    return ast;
+  }
+
+  getInstructionData(name) {
+    return this.grammar_["instructions"][name];
+  }
+
+  nextIsNewInstr() {
+    let n0 = this.peek(0);
+    if (n0.type === TokenType.kOp || n0.type === TokenType.kEOF) {
+      return true;
+    }
+
+    let n1 = this.peek(1);
+    if (n1.type === TokenType.kEOF) {
+      return false;
+    }
+    if (n0.type === TokenType.kResultId && n1.type === TokenType.kEqual)
+      return true;
+
+    return false;
+  }
+
+  extractOperand(ast, result_type, data) {
+    let t = this.next();
+
+    let name = undefined;
+    let kind = undefined;
+    let value = undefined;
+    let params = [];
+
+    // TODO(dsinclair): There are a bunch of missing types here. See
+    // https://github.com/KhronosGroup/SPIRV-Tools/blob/master/source/text.cpp#L210
+    if (data.kind === "IdResult" || data.kind === "IdRef"
+        || data.kind === "IdResultType") {
+      if (t.type !== TokenType.kResultId) {
+        this.error_ = t.line + ": expected result id";
+        return undefined;
+      }
+
+      name = t.data.name;
+      kind = "result_id";
+      value = t.data.val;
+    } else if (data.kind === "LiteralString") {
+      if (t.type !== TokenType.kStringLiteral) {
+        this.error_ = t.line + ": expected string not found";
+        return undefined;
+      }
+
+      name = t.data;
+      kind = "string";
+      value = t.data;
+    } else if (data.kind === "LiteralInteger") {
+      if (t.type !== TokenType.kIntegerLiteral) {
+        this.error_ = t.line + ": expected integer not found";
+        return undefined;
+      }
+
+      name = "" + t.data;
+      kind = t.type;
+      value = t.data;
+    } else if (data.kind === "LiteralContextDependentNumber") {
+      if (result_type === undefined) {
+        this.error_ = t.line +
+            ": missing result type for context dependent number";
+        return undefined;
+      }
+      if (t.type !== TokenType.kIntegerLiteral
+          && t.type !== TokenType.kFloatLiteral) {
+        this.error_ = t.line + ": expected number not found";
+        return undefined;
+      }
+
+      name = "" + t.data;
+      kind = result_type.type;
+      value = t.data;
+
+    } else if (data.kind === "LiteralExtInstInteger") {
+      if (t.type !== TokenType.kIdentifier) {
+        this.error_ = t.line + ": expected instruction identifier";
+        return undefined;
+      }
+
+      if (this.grammar_.ext[t.data] === undefined) {
+        this.error_ = t.line + `: unable to find extended instruction (${t.data})`;
+        return undefined;
+      }
+
+      name = t.data;
+      kind = "integer";
+      value = this.grammar_.ext[t.data];
+
+    } else {
+      let d = this.grammar_.operand_kinds[data.kind];
+      if (d === undefined) {
+        this.error_ = t.line + ": expected " + data.kind + " not found";
+        return undefined;
+      }
+
+      let val = d.values[t.data]["value"];
+      let names = [t.data];
+      if (d.type === "BitEnum") {
+        for(;;) {
+          let tmp = this.peek(0);
+          if (tmp.type !== TokenType.kPipe) {
+            break;
+          }
+
+          this.next();  // skip pipe
+          tmp = this.next();
+
+          if (tmp.type !== TokenType.kIdentifier) {
+            this.error_ = tmp.line() + ": expected identifier";
+            return undefined;
+          }
+
+          val |= d.values[tmp.data]["value"];
+          names.push(tmp.data);
+        }
+      }
+
+      name = names.join("|");
+      kind = d.type;
+      value = val;
+
+      for (const op_name of names) {
+        if (d.values[op_name]['params'] === undefined) {
+          continue;
+        }
+
+        for (const param of d.values[op_name]["params"]) {
+          params.push(this.extractOperand(ast, result_type, { kind: param }));
+        }
+      }
+    }
+    return new AST.Operand(ast, name, kind, value, params);
+  }
+}

+ 464 - 0
3rdparty/spirv-tools/tools/sva/src/parser_test.js

@@ -0,0 +1,464 @@
+// Copyright 2019 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.
+
+import { assert } from "chai";
+import Lexer from "./lexer";
+import Parser from "./parser";
+import grammar from "./spirv.data.js";
+
+describe("parser", () => {
+  it("parses an opcode", () => {
+    let input = "OpKill";
+    let l = new Lexer(input);
+    let p = new Parser(grammar, l);
+
+    let ast = p.parse();
+    assert.exists(ast);
+    assert.lengthOf(ast.instructions(), 1);
+
+    let inst = ast.instruction(0);
+    assert.equal(inst.name(), "OpKill");
+    assert.equal(inst.opcode(), 252);
+    assert.lengthOf(inst.operands, 0);
+  });
+
+  it("parses an opcode with an identifier", () => {
+    let input = "OpCapability Shader";
+    let l = new Lexer(input);
+    let p = new Parser(grammar, l);
+
+    let ast = p.parse();
+    assert.exists(ast, p.error);
+    assert.lengthOf(ast.instructions(), 1);
+
+    let inst = ast.instruction(0);
+    assert.equal(inst.name(), "OpCapability");
+    assert.equal(inst.opcode(), 17);
+    assert.lengthOf(inst.operands(), 1);
+
+    let op = inst.operand(0);
+    assert.equal(op.name(), "Shader");
+    assert.equal(op.type(), "ValueEnum");
+    assert.equal(op.value(), 1);
+  });
+
+  it("parses an opcode with a result", () => {
+    let input = "%void = OpTypeVoid";
+    let l = new Lexer(input);
+    let p = new Parser(grammar, l);
+
+    let ast = p.parse();
+    assert.exists(ast);
+    assert.lengthOf(ast.instructions(), 1);
+
+    let inst = ast.instruction(0);
+    assert.equal(inst.name(), "OpTypeVoid");
+    assert.equal(inst.opcode(), 19);
+    assert.lengthOf(inst.operands(), 1);
+
+    let op = inst.operand(0);
+    assert.equal(op.name(), "void");
+    assert.equal(op.value(), 1);
+  });
+
+  it("sets module bounds based on numeric result", () => {
+    let input = "%3 = OpTypeVoid";
+
+    let l = new Lexer(input);
+    let p = new Parser(grammar, l);
+
+    let ast = p.parse();
+    assert.exists(ast);
+    assert.equal(ast.getId("next"), 4);
+  });
+
+  it("returns the same value for a named result_id", () => {
+    let input = "%3 = OpTypeFunction %int %int";
+
+    let l = new Lexer(input);
+    let p = new Parser(grammar, l);
+
+    let ast = p.parse();
+    assert.exists(ast);
+    assert.lengthOf(ast.instructions(), 1);
+
+    let inst = ast.instruction(0);
+    let op1 = inst.operand(1);
+    assert.equal(op1.name(), "int");
+    assert.equal(op1.value(), 4);
+
+    let op2 = inst.operand(2);
+    assert.equal(op2.name(), "int");
+    assert.equal(op2.value(), 4);
+  });
+
+  it("parses an opcode with a string", () => {
+    let input = "OpEntryPoint Fragment %main \"main\"";
+
+    let l = new Lexer(input);
+    let p = new Parser(grammar, l);
+
+    let ast = p.parse();
+    assert.exists(ast);
+    assert.lengthOf(ast.instructions(), 1);
+
+    let inst = ast.instruction(0);
+    let op = inst.operand(2);
+    assert.equal(op.name(), "main");
+    assert.equal(op.value(), "main");
+  });
+
+  describe("numerics", () => {
+    describe("integers", () => {
+      it("parses an opcode with an integer", () => {
+        let input = "OpSource GLSL 440";
+
+        let l = new Lexer(input);
+        let p = new Parser(grammar, l);
+
+        let ast = p.parse();
+        assert.exists(ast);
+        assert.lengthOf(ast.instructions(), 1);
+
+        let inst = ast.instruction(0);
+        let op0 = inst.operand(0);
+        assert.equal(op0.name(), "GLSL");
+        assert.equal(op0.type(), "ValueEnum");
+        assert.equal(op0.value(), 2);
+
+        let op1 = inst.operand(1);
+        assert.equal(op1.name(), "440");
+        assert.equal(op1.value(), 440);
+      });
+
+      it("parses an opcode with a hex integer", () => {
+        let input = "OpSource GLSL 0x440";
+
+        let l = new Lexer(input);
+        let p = new Parser(grammar, l);
+
+        let ast = p.parse();
+        assert.exists(ast);
+        assert.lengthOf(ast.instructions(), 1);
+
+        let inst = ast.instruction(0);
+        let op0 = inst.operand(0);
+        assert.equal(op0.name(), "GLSL");
+        assert.equal(op0.type(), "ValueEnum");
+        assert.equal(op0.value(), 2);
+
+        let op1 = inst.operand(1);
+        assert.equal(op1.name(), "1088");
+        assert.equal(op1.value(), 0x440);
+      });
+
+      it.skip("parses immediate integers", () => {
+        // TODO(dsinclair): Support or skip?
+      });
+    });
+
+    describe("floats", () => {
+      it("parses floats", () => {
+        let input = `%float = OpTypeFloat 32
+                     %float1 = OpConstant %float 0.400000006`;
+
+        let l = new Lexer(input);
+        let p = new Parser(grammar, l);
+
+        let ast = p.parse();
+        assert.exists(ast, p.error);
+        assert.lengthOf(ast.instructions(), 2);
+
+        let inst = ast.instruction(1);
+        let op2 = inst.operand(2);
+        assert.equal(op2.value(), 0.400000006);
+      });
+
+      // TODO(dsinclair): Make hex encoded floats parse ...
+      it.skip("parses hex floats", () => {
+        let input = `%float = OpTypeFloat 32
+                     %nfloat = OpConstant %float -0.4p+2
+                     %pfloat = OpConstant %float 0.4p-2
+                     %inf = OpConstant %float32 0x1p+128
+                     %neginf = OpConstant %float32 -0x1p+128
+                     %aNaN = OpConstant %float32 0x1.8p+128
+                     %moreNaN = OpConstant %float32 -0x1.0002p+128`;
+
+        let results = [-40.0, .004, 0x00000, 0x00000, 0x7fc00000, 0xff800100];
+        let l = new Lexer(input);
+        let p = new Parser(grammar, l);
+
+        let ast = p.parse();
+        assert.exists(ast, p.error);
+        assert.lengthOf(ast.instructions(), 7);
+
+        for (const idx in results) {
+          let inst = ast.instruction(idx);
+          let op2 = inst.operand(2);
+          assert.equal(op2.value(), results[idx]);
+        }
+      });
+
+      it("parses a float that looks like an int", () => {
+        let input = `%float = OpTypeFloat 32
+                     %float1 = OpConstant %float 1`;
+
+        let l = new Lexer(input);
+        let p = new Parser(grammar, l);
+
+        let ast = p.parse();
+        assert.exists(ast, p.error);
+        assert.lengthOf(ast.instructions(), 2);
+
+        let inst = ast.instruction(1);
+        let op2 = inst.operand(2);
+        assert.equal(op2.value(), 1);
+        assert.equal(op2.type(), "float");
+      });
+    });
+  });
+
+  describe("enums", () => {
+    it("parses enum values", () => {
+      let input = `%1 = OpTypeFloat 32
+  %30 = OpImageSampleExplicitLod %1 %20 %18 Grad|ConstOffset %22 %24 %29`;
+
+      let vals = [{val: 1, name: "1"},
+        {val: 30, name: "30"},
+        {val: 20, name: "20"},
+        {val: 18, name: "18"},
+        {val: 12, name: "Grad|ConstOffset"}];
+
+      let l = new Lexer(input);
+      let p = new Parser(grammar, l);
+
+      let ast = p.parse();
+      assert.exists(ast, p.error);
+      assert.lengthOf(ast.instructions(), 2);
+
+      let inst = ast.instruction(1);
+      for (let idx in vals) {
+        let op = inst.operand(idx);
+        assert.equal(op.name(), vals[idx].name);
+        assert.equal(op.value(), vals[idx].val);
+      }
+
+      // BitEnum
+      let params = inst.operand(4).params();
+      assert.lengthOf(params, 3);
+      assert.equal(params[0].name(), "22");
+      assert.equal(params[0].value(), 22);
+      assert.equal(params[1].name(), "24");
+      assert.equal(params[1].value(), 24);
+      assert.equal(params[2].name(), "29");
+      assert.equal(params[2].value(), 29);
+    });
+
+    it("parses enumerants with parameters", () => {
+      let input ="OpExecutionMode %main LocalSize 2 3 4";
+
+      let l = new Lexer(input);
+      let p = new Parser(grammar, l);
+
+      let ast = p.parse();
+      assert.exists(ast, p.error);
+      assert.lengthOf(ast.instructions(), 1);
+
+      let inst = ast.instruction(0);
+      assert.equal(inst.name(), "OpExecutionMode");
+      assert.lengthOf(inst.operands(), 2);
+      assert.equal(inst.operand(0).name(), "main");
+      assert.equal(inst.operand(1).name(), "LocalSize");
+
+      let params = inst.operand(1).params();
+      assert.lengthOf(params, 3);
+      assert.equal(params[0].name(), "2");
+      assert.equal(params[1].name(), "3");
+      assert.equal(params[2].name(), "4");
+    });
+  });
+
+  it("parses result into second operand if needed", () => {
+    let input = `%int = OpTypeInt 32 1
+                 %int_3 = OpConstant %int 3`;
+    let l = new Lexer(input);
+    let p = new Parser(grammar, l);
+
+    let ast = p.parse();
+    assert.exists(ast);
+    assert.lengthOf(ast.instructions(), 2);
+
+    let inst = ast.instruction(1);
+    assert.equal(inst.name(), "OpConstant");
+    assert.equal(inst.opcode(), 43);
+    assert.lengthOf(inst.operands(), 3);
+
+    let op0 = inst.operand(0);
+    assert.equal(op0.name(), "int");
+    assert.equal(op0.value(), 1);
+
+    let op1 = inst.operand(1);
+    assert.equal(op1.name(), "int_3");
+    assert.equal(op1.value(), 2);
+
+    let op2 = inst.operand(2);
+    assert.equal(op2.name(), "3");
+    assert.equal(op2.value(), 3);
+  });
+
+  describe("quantifiers", () => {
+    describe("?", () => {
+      it("skips if missing", () => {
+        let input = `OpImageWrite %1 %2 %3
+OpKill`;
+        let l = new Lexer(input);
+        let p = new Parser(grammar, l);
+
+        let ast = p.parse();
+        assert.exists(ast);
+        assert.lengthOf(ast.instructions(), 2);
+
+        let inst = ast.instruction(0);
+        assert.equal(inst.name(), "OpImageWrite");
+        assert.lengthOf(inst.operands(), 3);
+      });
+
+      it("skips if missing at EOF", () => {
+        let input = "OpImageWrite %1 %2 %3";
+        let l = new Lexer(input);
+        let p = new Parser(grammar, l);
+
+        let ast = p.parse();
+        assert.exists(ast);
+        assert.lengthOf(ast.instructions(), 1);
+
+        let inst = ast.instruction(0);
+        assert.equal(inst.name(), "OpImageWrite");
+        assert.lengthOf(inst.operands(), 3);
+      });
+
+      it("extracts if available", () => {
+        let input = `OpImageWrite %1 %2 %3 ConstOffset %2
+OpKill`;
+        let l = new Lexer(input);
+        let p = new Parser(grammar, l);
+
+        let ast = p.parse();
+        assert.exists(ast);
+        assert.lengthOf(ast.instructions(), 2);
+
+        let inst = ast.instruction(0);
+        assert.equal(inst.name(), "OpImageWrite");
+        assert.lengthOf(inst.operands(), 4);
+        assert.equal(inst.operand(3).name(), "ConstOffset");
+      });
+    });
+
+    describe("*", () => {
+      it("skips if missing", () => {
+        let input = `OpEntryPoint Fragment %main "main"
+OpKill`;
+
+        let l = new Lexer(input);
+        let p = new Parser(grammar, l);
+
+        let ast = p.parse();
+        assert.exists(ast);
+        assert.lengthOf(ast.instructions(), 2);
+
+        let inst = ast.instruction(0);
+        assert.equal(inst.name(), "OpEntryPoint");
+        assert.lengthOf(inst.operands(), 3);
+        assert.equal(inst.operand(2).name(), "main");
+      });
+
+      it("extracts one if available", () => {
+        let input = `OpEntryPoint Fragment %main "main" %2
+OpKill`;
+
+        let l = new Lexer(input);
+        let p = new Parser(grammar, l);
+
+        let ast = p.parse();
+        assert.exists(ast);
+        assert.lengthOf(ast.instructions(), 2);
+
+        let inst = ast.instruction(0);
+        assert.equal(inst.name(), "OpEntryPoint");
+        assert.lengthOf(inst.operands(), 4);
+        assert.equal(inst.operand(3).name(), "2");
+      });
+
+      it("extracts multiple if available", () => {
+        let input = `OpEntryPoint Fragment %main "main" %2 %3 %4 %5
+OpKill`;
+
+        let l = new Lexer(input);
+        let p = new Parser(grammar, l);
+
+        let ast = p.parse();
+        assert.exists(ast);
+        assert.lengthOf(ast.instructions(), 2);
+
+        let inst = ast.instruction(0);
+        assert.equal(inst.name(), "OpEntryPoint");
+        assert.lengthOf(inst.operands(), 7);
+        assert.equal(inst.operand(3).name(), "2");
+        assert.equal(inst.operand(4).name(), "3");
+        assert.equal(inst.operand(5).name(), "4");
+        assert.equal(inst.operand(6).name(), "5");
+      });
+    });
+  });
+
+  describe("extended instructions", () => {
+    it("errors on non-glsl extensions", () => {
+      let input = "%1 = OpExtInstImport \"OpenCL.std.100\"";
+
+      let l = new Lexer(input);
+      let p = new Parser(grammar, l);
+
+      assert.isUndefined(p.parse());
+    });
+
+    it("handles extended instructions", () => {
+      let input = `%1 = OpExtInstImport "GLSL.std.450"
+  %44 = OpExtInst %7 %1 Sqrt %43`;
+
+      let l = new Lexer(input);
+      let p = new Parser(grammar, l);
+
+      let ast = p.parse();
+      assert.exists(ast, p.error);
+      assert.lengthOf(ast.instructions(), 2);
+
+      let inst = ast.instruction(1);
+      assert.lengthOf(inst.operands(), 5);
+      assert.equal(inst.operand(3).value(), 31);
+      assert.equal(inst.operand(3).name(), "Sqrt");
+      assert.equal(inst.operand(4).value(), 43);
+      assert.equal(inst.operand(4).name(), "43");
+    });
+  });
+
+  it.skip("handles spec constant ops", () => {
+    // let input = "%sum = OpSpecConstantOp %i32 IAdd %a %b";
+  });
+
+  it.skip("handles OpCopyMemory", () => {
+    // let input = "OpCopyMemory %1 %2 " +
+    //             "Volatile|Nontemporal|MakePointerVisible %3 " +
+    //             "Aligned|MakePointerAvailable|NonPrivatePointer 16 %4";
+  });
+});

+ 4567 - 0
3rdparty/spirv-tools/tools/sva/src/spirv.data.js

@@ -0,0 +1,4567 @@
+/*Copyright (c) 2014-2016 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and/or associated documentation files (the "Materials"),
+to deal in the Materials without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Materials, and to permit persons to whom the
+Materials are furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Materials.
+
+MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ 
+
+THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+IN THE MATERIALS.*/
+
+// THIS FILE IS GENERATED WITH tools/process_grammar.rb
+
+export default {
+  "magic": "0x07230203",
+  "version": [
+    1,
+    5
+  ],
+  "instructions": {
+    "OpNop": {
+      "opcode": 0,
+      "operands": [
+
+      ]
+    },
+    "OpUndef": {
+      "opcode": 1,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpSourceContinued": {
+      "opcode": 2,
+      "operands": [
+        {
+          "kind": "LiteralString"
+        }
+      ]
+    },
+    "OpSource": {
+      "opcode": 3,
+      "operands": [
+        {
+          "kind": "SourceLanguage"
+        },
+        {
+          "kind": "LiteralInteger"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "?"
+        },
+        {
+          "kind": "LiteralString",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpSourceExtension": {
+      "opcode": 4,
+      "operands": [
+        {
+          "kind": "LiteralString"
+        }
+      ]
+    },
+    "OpName": {
+      "opcode": 5,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralString"
+        }
+      ]
+    },
+    "OpMemberName": {
+      "opcode": 6,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger"
+        },
+        {
+          "kind": "LiteralString"
+        }
+      ]
+    },
+    "OpString": {
+      "opcode": 7,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "LiteralString"
+        }
+      ]
+    },
+    "OpLine": {
+      "opcode": 8,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger"
+        },
+        {
+          "kind": "LiteralInteger"
+        }
+      ]
+    },
+    "OpExtension": {
+      "opcode": 10,
+      "operands": [
+        {
+          "kind": "LiteralString"
+        }
+      ]
+    },
+    "OpExtInstImport": {
+      "opcode": 11,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "LiteralString"
+        }
+      ]
+    },
+    "OpExtInst": {
+      "opcode": 12,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralExtInstInteger"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpMemoryModel": {
+      "opcode": 14,
+      "operands": [
+        {
+          "kind": "AddressingModel"
+        },
+        {
+          "kind": "MemoryModel"
+        }
+      ]
+    },
+    "OpEntryPoint": {
+      "opcode": 15,
+      "operands": [
+        {
+          "kind": "ExecutionModel"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralString"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpExecutionMode": {
+      "opcode": 16,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ExecutionMode"
+        }
+      ]
+    },
+    "OpCapability": {
+      "opcode": 17,
+      "operands": [
+        {
+          "kind": "Capability"
+        }
+      ]
+    },
+    "OpTypeVoid": {
+      "opcode": 19,
+      "operands": [
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpTypeBool": {
+      "opcode": 20,
+      "operands": [
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpTypeInt": {
+      "opcode": 21,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "LiteralInteger"
+        },
+        {
+          "kind": "LiteralInteger"
+        }
+      ]
+    },
+    "OpTypeFloat": {
+      "opcode": 22,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "LiteralInteger"
+        }
+      ]
+    },
+    "OpTypeVector": {
+      "opcode": 23,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger"
+        }
+      ]
+    },
+    "OpTypeMatrix": {
+      "opcode": 24,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger"
+        }
+      ]
+    },
+    "OpTypeImage": {
+      "opcode": 25,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "Dim"
+        },
+        {
+          "kind": "LiteralInteger"
+        },
+        {
+          "kind": "LiteralInteger"
+        },
+        {
+          "kind": "LiteralInteger"
+        },
+        {
+          "kind": "LiteralInteger"
+        },
+        {
+          "kind": "ImageFormat"
+        },
+        {
+          "kind": "AccessQualifier",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpTypeSampler": {
+      "opcode": 26,
+      "operands": [
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpTypeSampledImage": {
+      "opcode": 27,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpTypeArray": {
+      "opcode": 28,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpTypeRuntimeArray": {
+      "opcode": 29,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpTypeStruct": {
+      "opcode": 30,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpTypePointer": {
+      "opcode": 32,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "StorageClass"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpTypeFunction": {
+      "opcode": 33,
+      "operands": [
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpConstantTrue": {
+      "opcode": 41,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpConstantFalse": {
+      "opcode": 42,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpConstant": {
+      "opcode": 43,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "LiteralContextDependentNumber"
+        }
+      ]
+    },
+    "OpConstantComposite": {
+      "opcode": 44,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpConstantNull": {
+      "opcode": 46,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpSpecConstantTrue": {
+      "opcode": 48,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpSpecConstantFalse": {
+      "opcode": 49,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpSpecConstant": {
+      "opcode": 50,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "LiteralContextDependentNumber"
+        }
+      ]
+    },
+    "OpSpecConstantComposite": {
+      "opcode": 51,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpSpecConstantOp": {
+      "opcode": 52,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "LiteralSpecConstantOpInteger"
+        }
+      ]
+    },
+    "OpFunction": {
+      "opcode": 54,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "FunctionControl"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFunctionParameter": {
+      "opcode": 55,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpFunctionEnd": {
+      "opcode": 56,
+      "operands": [
+
+      ]
+    },
+    "OpFunctionCall": {
+      "opcode": 57,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpVariable": {
+      "opcode": 59,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "StorageClass"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpImageTexelPointer": {
+      "opcode": 60,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpLoad": {
+      "opcode": 61,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "MemoryAccess",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpStore": {
+      "opcode": 62,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "MemoryAccess",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpCopyMemory": {
+      "opcode": 63,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "MemoryAccess",
+          "quantifier": "?"
+        },
+        {
+          "kind": "MemoryAccess",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpAccessChain": {
+      "opcode": 65,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpInBoundsAccessChain": {
+      "opcode": 66,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpArrayLength": {
+      "opcode": 68,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger"
+        }
+      ]
+    },
+    "OpDecorate": {
+      "opcode": 71,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "Decoration"
+        }
+      ]
+    },
+    "OpMemberDecorate": {
+      "opcode": 72,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger"
+        },
+        {
+          "kind": "Decoration"
+        }
+      ]
+    },
+    "OpDecorationGroup": {
+      "opcode": 73,
+      "operands": [
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpGroupDecorate": {
+      "opcode": 74,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpGroupMemberDecorate": {
+      "opcode": 75,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "PairIdRefLiteralInteger",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpVectorExtractDynamic": {
+      "opcode": 77,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpVectorInsertDynamic": {
+      "opcode": 78,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpVectorShuffle": {
+      "opcode": 79,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpCompositeConstruct": {
+      "opcode": 80,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpCompositeExtract": {
+      "opcode": 81,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpCompositeInsert": {
+      "opcode": 82,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpCopyObject": {
+      "opcode": 83,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpTranspose": {
+      "opcode": 84,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSampledImage": {
+      "opcode": 86,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpImageSampleImplicitLod": {
+      "opcode": 87,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpImageSampleExplicitLod": {
+      "opcode": 88,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands"
+        }
+      ]
+    },
+    "OpImageSampleDrefImplicitLod": {
+      "opcode": 89,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpImageSampleDrefExplicitLod": {
+      "opcode": 90,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands"
+        }
+      ]
+    },
+    "OpImageSampleProjImplicitLod": {
+      "opcode": 91,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpImageSampleProjExplicitLod": {
+      "opcode": 92,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands"
+        }
+      ]
+    },
+    "OpImageSampleProjDrefImplicitLod": {
+      "opcode": 93,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpImageSampleProjDrefExplicitLod": {
+      "opcode": 94,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands"
+        }
+      ]
+    },
+    "OpImageFetch": {
+      "opcode": 95,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpImageGather": {
+      "opcode": 96,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpImageDrefGather": {
+      "opcode": 97,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpImageRead": {
+      "opcode": 98,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpImageWrite": {
+      "opcode": 99,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ImageOperands",
+          "quantifier": "?"
+        }
+      ]
+    },
+    "OpImage": {
+      "opcode": 100,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpImageQuerySizeLod": {
+      "opcode": 103,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpImageQuerySize": {
+      "opcode": 104,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpImageQueryLod": {
+      "opcode": 105,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpImageQueryLevels": {
+      "opcode": 106,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpImageQuerySamples": {
+      "opcode": 107,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpConvertFToU": {
+      "opcode": 109,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpConvertFToS": {
+      "opcode": 110,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpConvertSToF": {
+      "opcode": 111,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpConvertUToF": {
+      "opcode": 112,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpUConvert": {
+      "opcode": 113,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSConvert": {
+      "opcode": 114,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFConvert": {
+      "opcode": 115,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpQuantizeToF16": {
+      "opcode": 116,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpBitcast": {
+      "opcode": 124,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSNegate": {
+      "opcode": 126,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFNegate": {
+      "opcode": 127,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpIAdd": {
+      "opcode": 128,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFAdd": {
+      "opcode": 129,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpISub": {
+      "opcode": 130,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFSub": {
+      "opcode": 131,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpIMul": {
+      "opcode": 132,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFMul": {
+      "opcode": 133,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpUDiv": {
+      "opcode": 134,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSDiv": {
+      "opcode": 135,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFDiv": {
+      "opcode": 136,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpUMod": {
+      "opcode": 137,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSRem": {
+      "opcode": 138,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSMod": {
+      "opcode": 139,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFRem": {
+      "opcode": 140,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFMod": {
+      "opcode": 141,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpVectorTimesScalar": {
+      "opcode": 142,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpMatrixTimesScalar": {
+      "opcode": 143,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpVectorTimesMatrix": {
+      "opcode": 144,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpMatrixTimesVector": {
+      "opcode": 145,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpMatrixTimesMatrix": {
+      "opcode": 146,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpOuterProduct": {
+      "opcode": 147,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpDot": {
+      "opcode": 148,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpIAddCarry": {
+      "opcode": 149,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpISubBorrow": {
+      "opcode": 150,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpUMulExtended": {
+      "opcode": 151,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSMulExtended": {
+      "opcode": 152,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAny": {
+      "opcode": 154,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAll": {
+      "opcode": 155,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpIsNan": {
+      "opcode": 156,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpIsInf": {
+      "opcode": 157,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpLogicalEqual": {
+      "opcode": 164,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpLogicalNotEqual": {
+      "opcode": 165,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpLogicalOr": {
+      "opcode": 166,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpLogicalAnd": {
+      "opcode": 167,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpLogicalNot": {
+      "opcode": 168,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSelect": {
+      "opcode": 169,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpIEqual": {
+      "opcode": 170,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpINotEqual": {
+      "opcode": 171,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpUGreaterThan": {
+      "opcode": 172,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSGreaterThan": {
+      "opcode": 173,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpUGreaterThanEqual": {
+      "opcode": 174,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSGreaterThanEqual": {
+      "opcode": 175,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpULessThan": {
+      "opcode": 176,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSLessThan": {
+      "opcode": 177,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpULessThanEqual": {
+      "opcode": 178,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpSLessThanEqual": {
+      "opcode": 179,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFOrdEqual": {
+      "opcode": 180,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFUnordEqual": {
+      "opcode": 181,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFOrdNotEqual": {
+      "opcode": 182,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFUnordNotEqual": {
+      "opcode": 183,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFOrdLessThan": {
+      "opcode": 184,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFUnordLessThan": {
+      "opcode": 185,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFOrdGreaterThan": {
+      "opcode": 186,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFUnordGreaterThan": {
+      "opcode": 187,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFOrdLessThanEqual": {
+      "opcode": 188,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFUnordLessThanEqual": {
+      "opcode": 189,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFOrdGreaterThanEqual": {
+      "opcode": 190,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFUnordGreaterThanEqual": {
+      "opcode": 191,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpShiftRightLogical": {
+      "opcode": 194,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpShiftRightArithmetic": {
+      "opcode": 195,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpShiftLeftLogical": {
+      "opcode": 196,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpBitwiseOr": {
+      "opcode": 197,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpBitwiseXor": {
+      "opcode": 198,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpBitwiseAnd": {
+      "opcode": 199,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpNot": {
+      "opcode": 200,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpBitFieldInsert": {
+      "opcode": 201,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpBitFieldSExtract": {
+      "opcode": 202,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpBitFieldUExtract": {
+      "opcode": 203,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpBitReverse": {
+      "opcode": 204,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpBitCount": {
+      "opcode": 205,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpDPdx": {
+      "opcode": 207,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpDPdy": {
+      "opcode": 208,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFwidth": {
+      "opcode": 209,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpDPdxFine": {
+      "opcode": 210,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpDPdyFine": {
+      "opcode": 211,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFwidthFine": {
+      "opcode": 212,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpDPdxCoarse": {
+      "opcode": 213,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpDPdyCoarse": {
+      "opcode": 214,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpFwidthCoarse": {
+      "opcode": 215,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpControlBarrier": {
+      "opcode": 224,
+      "operands": [
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        }
+      ]
+    },
+    "OpMemoryBarrier": {
+      "opcode": 225,
+      "operands": [
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        }
+      ]
+    },
+    "OpAtomicLoad": {
+      "opcode": 227,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        }
+      ]
+    },
+    "OpAtomicStore": {
+      "opcode": 228,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAtomicExchange": {
+      "opcode": 229,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAtomicCompareExchange": {
+      "opcode": 230,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAtomicIIncrement": {
+      "opcode": 232,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        }
+      ]
+    },
+    "OpAtomicIDecrement": {
+      "opcode": 233,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        }
+      ]
+    },
+    "OpAtomicIAdd": {
+      "opcode": 234,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAtomicISub": {
+      "opcode": 235,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAtomicSMin": {
+      "opcode": 236,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAtomicUMin": {
+      "opcode": 237,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAtomicSMax": {
+      "opcode": 238,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAtomicUMax": {
+      "opcode": 239,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAtomicAnd": {
+      "opcode": 240,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAtomicOr": {
+      "opcode": 241,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpAtomicXor": {
+      "opcode": 242,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdScope"
+        },
+        {
+          "kind": "IdMemorySemantics"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpPhi": {
+      "opcode": 245,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "PairIdRefIdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpLoopMerge": {
+      "opcode": 246,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LoopControl"
+        }
+      ]
+    },
+    "OpSelectionMerge": {
+      "opcode": 247,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "SelectionControl"
+        }
+      ]
+    },
+    "OpLabel": {
+      "opcode": 248,
+      "operands": [
+        {
+          "kind": "IdResult"
+        }
+      ]
+    },
+    "OpBranch": {
+      "opcode": 249,
+      "operands": [
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpBranchConditional": {
+      "opcode": 250,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpSwitch": {
+      "opcode": 251,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "PairLiteralIntegerIdRef",
+          "quantifier": "*"
+        }
+      ]
+    },
+    "OpKill": {
+      "opcode": 252,
+      "operands": [
+
+      ]
+    },
+    "OpReturn": {
+      "opcode": 253,
+      "operands": [
+
+      ]
+    },
+    "OpReturnValue": {
+      "opcode": 254,
+      "operands": [
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpUnreachable": {
+      "opcode": 255,
+      "operands": [
+
+      ]
+    },
+    "OpNoLine": {
+      "opcode": 317,
+      "operands": [
+
+      ]
+    },
+    "OpModuleProcessed": {
+      "opcode": 330,
+      "operands": [
+        {
+          "kind": "LiteralString"
+        }
+      ]
+    },
+    "OpExecutionModeId": {
+      "opcode": 331,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "ExecutionMode"
+        }
+      ]
+    },
+    "OpDecorateId": {
+      "opcode": 332,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "Decoration"
+        }
+      ]
+    },
+    "OpCopyLogical": {
+      "opcode": 400,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpPtrEqual": {
+      "opcode": 401,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpPtrNotEqual": {
+      "opcode": 402,
+      "operands": [
+        {
+          "kind": "IdResultType"
+        },
+        {
+          "kind": "IdResult"
+        },
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "IdRef"
+        }
+      ]
+    },
+    "OpDecorateString": {
+      "opcode": 5632,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "Decoration"
+        }
+      ]
+    },
+    "OpDecorateStringGOOGLE": {
+      "opcode": 5632,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "Decoration"
+        }
+      ]
+    },
+    "OpMemberDecorateString": {
+      "opcode": 5633,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger"
+        },
+        {
+          "kind": "Decoration"
+        }
+      ]
+    },
+    "OpMemberDecorateStringGOOGLE": {
+      "opcode": 5633,
+      "operands": [
+        {
+          "kind": "IdRef"
+        },
+        {
+          "kind": "LiteralInteger"
+        },
+        {
+          "kind": "Decoration"
+        }
+      ]
+    }
+  },
+  "operand_kinds": {
+    "ImageOperands": {
+      "type": "BitEnum",
+      "values": {
+        "None": {
+          "value": 0
+        },
+        "Bias": {
+          "value": 1,
+          "params": [
+            "IdRef"
+          ]
+        },
+        "Lod": {
+          "value": 2,
+          "params": [
+            "IdRef"
+          ]
+        },
+        "Grad": {
+          "value": 4,
+          "params": [
+            "IdRef",
+            "IdRef"
+          ]
+        },
+        "ConstOffset": {
+          "value": 8,
+          "params": [
+            "IdRef"
+          ]
+        },
+        "Sample": {
+          "value": 64,
+          "params": [
+            "IdRef"
+          ]
+        },
+        "MakeTexelAvailable": {
+          "value": 256,
+          "params": [
+            "IdScope"
+          ]
+        },
+        "MakeTexelAvailableKHR": {
+          "value": 256,
+          "params": [
+            "IdScope"
+          ]
+        },
+        "MakeTexelVisible": {
+          "value": 512,
+          "params": [
+            "IdScope"
+          ]
+        },
+        "MakeTexelVisibleKHR": {
+          "value": 512,
+          "params": [
+            "IdScope"
+          ]
+        },
+        "NonPrivateTexel": {
+          "value": 1024
+        },
+        "NonPrivateTexelKHR": {
+          "value": 1024
+        },
+        "VolatileTexel": {
+          "value": 2048
+        },
+        "VolatileTexelKHR": {
+          "value": 2048
+        },
+        "SignExtend": {
+          "value": 4096
+        },
+        "ZeroExtend": {
+          "value": 8192
+        }
+      }
+    },
+    "FPFastMathMode": {
+      "type": "BitEnum",
+      "values": {
+        "None": {
+          "value": 0
+        }
+      }
+    },
+    "SelectionControl": {
+      "type": "BitEnum",
+      "values": {
+        "None": {
+          "value": 0
+        },
+        "Flatten": {
+          "value": 1
+        },
+        "DontFlatten": {
+          "value": 2
+        }
+      }
+    },
+    "LoopControl": {
+      "type": "BitEnum",
+      "values": {
+        "None": {
+          "value": 0
+        },
+        "Unroll": {
+          "value": 1
+        },
+        "DontUnroll": {
+          "value": 2
+        },
+        "DependencyInfinite": {
+          "value": 4
+        },
+        "DependencyLength": {
+          "value": 8,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "MinIterations": {
+          "value": 16,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "MaxIterations": {
+          "value": 32,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "IterationMultiple": {
+          "value": 64,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "PeelCount": {
+          "value": 128,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "PartialCount": {
+          "value": 256,
+          "params": [
+            "LiteralInteger"
+          ]
+        }
+      }
+    },
+    "FunctionControl": {
+      "type": "BitEnum",
+      "values": {
+        "None": {
+          "value": 0
+        },
+        "Inline": {
+          "value": 1
+        },
+        "DontInline": {
+          "value": 2
+        },
+        "Pure": {
+          "value": 4
+        },
+        "Const": {
+          "value": 8
+        }
+      }
+    },
+    "MemorySemantics": {
+      "type": "BitEnum",
+      "values": {
+        "Relaxed": {
+          "value": 0
+        },
+        "None": {
+          "value": 0
+        },
+        "Acquire": {
+          "value": 2
+        },
+        "Release": {
+          "value": 4
+        },
+        "AcquireRelease": {
+          "value": 8
+        },
+        "SequentiallyConsistent": {
+          "value": 16
+        },
+        "UniformMemory": {
+          "value": 64
+        },
+        "SubgroupMemory": {
+          "value": 128
+        },
+        "WorkgroupMemory": {
+          "value": 256
+        },
+        "CrossWorkgroupMemory": {
+          "value": 512
+        },
+        "ImageMemory": {
+          "value": 2048
+        },
+        "OutputMemory": {
+          "value": 4096
+        },
+        "OutputMemoryKHR": {
+          "value": 4096
+        },
+        "MakeAvailable": {
+          "value": 8192
+        },
+        "MakeAvailableKHR": {
+          "value": 8192
+        },
+        "MakeVisible": {
+          "value": 16384
+        },
+        "MakeVisibleKHR": {
+          "value": 16384
+        },
+        "Volatile": {
+          "value": 32768
+        }
+      }
+    },
+    "MemoryAccess": {
+      "type": "BitEnum",
+      "values": {
+        "None": {
+          "value": 0
+        },
+        "Volatile": {
+          "value": 1
+        },
+        "Aligned": {
+          "value": 2,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "Nontemporal": {
+          "value": 4
+        },
+        "MakePointerAvailable": {
+          "value": 8,
+          "params": [
+            "IdScope"
+          ]
+        },
+        "MakePointerAvailableKHR": {
+          "value": 8,
+          "params": [
+            "IdScope"
+          ]
+        },
+        "MakePointerVisible": {
+          "value": 16,
+          "params": [
+            "IdScope"
+          ]
+        },
+        "MakePointerVisibleKHR": {
+          "value": 16,
+          "params": [
+            "IdScope"
+          ]
+        },
+        "NonPrivatePointer": {
+          "value": 32
+        },
+        "NonPrivatePointerKHR": {
+          "value": 32
+        }
+      }
+    },
+    "KernelProfilingInfo": {
+      "type": "BitEnum",
+      "values": {
+        "None": {
+          "value": 0
+        }
+      }
+    },
+    "SourceLanguage": {
+      "type": "ValueEnum",
+      "values": {
+        "Unknown": {
+          "value": 0
+        },
+        "ESSL": {
+          "value": 1
+        },
+        "GLSL": {
+          "value": 2
+        },
+        "OpenCL_C": {
+          "value": 3
+        },
+        "OpenCL_CPP": {
+          "value": 4
+        },
+        "HLSL": {
+          "value": 5
+        }
+      }
+    },
+    "ExecutionModel": {
+      "type": "ValueEnum",
+      "values": {
+        "Vertex": {
+          "value": 0
+        },
+        "Fragment": {
+          "value": 4
+        },
+        "GLCompute": {
+          "value": 5
+        }
+      }
+    },
+    "AddressingModel": {
+      "type": "ValueEnum",
+      "values": {
+        "Logical": {
+          "value": 0
+        }
+      }
+    },
+    "MemoryModel": {
+      "type": "ValueEnum",
+      "values": {
+        "Simple": {
+          "value": 0
+        },
+        "GLSL450": {
+          "value": 1
+        },
+        "Vulkan": {
+          "value": 3
+        },
+        "VulkanKHR": {
+          "value": 3
+        }
+      }
+    },
+    "ExecutionMode": {
+      "type": "ValueEnum",
+      "values": {
+        "PixelCenterInteger": {
+          "value": 6
+        },
+        "OriginUpperLeft": {
+          "value": 7
+        },
+        "OriginLowerLeft": {
+          "value": 8
+        },
+        "EarlyFragmentTests": {
+          "value": 9
+        },
+        "DepthReplacing": {
+          "value": 12
+        },
+        "DepthGreater": {
+          "value": 14
+        },
+        "DepthLess": {
+          "value": 15
+        },
+        "DepthUnchanged": {
+          "value": 16
+        },
+        "LocalSize": {
+          "value": 17,
+          "params": [
+            "LiteralInteger",
+            "LiteralInteger",
+            "LiteralInteger"
+          ]
+        },
+        "LocalSizeId": {
+          "value": 38,
+          "params": [
+            "IdRef",
+            "IdRef",
+            "IdRef"
+          ]
+        }
+      }
+    },
+    "StorageClass": {
+      "type": "ValueEnum",
+      "values": {
+        "UniformConstant": {
+          "value": 0
+        },
+        "Input": {
+          "value": 1
+        },
+        "Uniform": {
+          "value": 2
+        },
+        "Output": {
+          "value": 3
+        },
+        "Workgroup": {
+          "value": 4
+        },
+        "CrossWorkgroup": {
+          "value": 5
+        },
+        "Private": {
+          "value": 6
+        },
+        "Function": {
+          "value": 7
+        },
+        "PushConstant": {
+          "value": 9
+        },
+        "Image": {
+          "value": 11
+        },
+        "StorageBuffer": {
+          "value": 12
+        }
+      }
+    },
+    "Dim": {
+      "type": "ValueEnum",
+      "values": {
+        "1D": {
+          "value": 0
+        },
+        "2D": {
+          "value": 1
+        },
+        "3D": {
+          "value": 2
+        },
+        "Cube": {
+          "value": 3
+        }
+      }
+    },
+    "ImageFormat": {
+      "type": "ValueEnum",
+      "values": {
+        "Unknown": {
+          "value": 0
+        },
+        "Rgba32f": {
+          "value": 1
+        },
+        "Rgba16f": {
+          "value": 2
+        },
+        "R32f": {
+          "value": 3
+        },
+        "Rgba8": {
+          "value": 4
+        },
+        "Rgba8Snorm": {
+          "value": 5
+        },
+        "Rgba32i": {
+          "value": 21
+        },
+        "Rgba16i": {
+          "value": 22
+        },
+        "Rgba8i": {
+          "value": 23
+        },
+        "R32i": {
+          "value": 24
+        },
+        "Rgba32ui": {
+          "value": 30
+        },
+        "Rgba16ui": {
+          "value": 31
+        },
+        "Rgba8ui": {
+          "value": 32
+        },
+        "R32ui": {
+          "value": 33
+        }
+      }
+    },
+    "FPRoundingMode": {
+      "type": "ValueEnum",
+      "values": {
+        "RTE": {
+          "value": 0
+        },
+        "RTZ": {
+          "value": 1
+        },
+        "RTP": {
+          "value": 2
+        },
+        "RTN": {
+          "value": 3
+        }
+      }
+    },
+    "Decoration": {
+      "type": "ValueEnum",
+      "values": {
+        "RelaxedPrecision": {
+          "value": 0
+        },
+        "SpecId": {
+          "value": 1,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "Block": {
+          "value": 2
+        },
+        "BufferBlock": {
+          "value": 3
+        },
+        "RowMajor": {
+          "value": 4
+        },
+        "ColMajor": {
+          "value": 5
+        },
+        "ArrayStride": {
+          "value": 6,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "MatrixStride": {
+          "value": 7,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "GLSLShared": {
+          "value": 8
+        },
+        "GLSLPacked": {
+          "value": 9
+        },
+        "BuiltIn": {
+          "value": 11,
+          "params": [
+            "BuiltIn"
+          ]
+        },
+        "NoPerspective": {
+          "value": 13
+        },
+        "Flat": {
+          "value": 14
+        },
+        "Centroid": {
+          "value": 16
+        },
+        "Invariant": {
+          "value": 18
+        },
+        "Restrict": {
+          "value": 19
+        },
+        "Aliased": {
+          "value": 20
+        },
+        "Volatile": {
+          "value": 21
+        },
+        "Coherent": {
+          "value": 23
+        },
+        "NonWritable": {
+          "value": 24
+        },
+        "NonReadable": {
+          "value": 25
+        },
+        "Uniform": {
+          "value": 26
+        },
+        "UniformId": {
+          "value": 27,
+          "params": [
+            "IdScope"
+          ]
+        },
+        "Location": {
+          "value": 30,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "Component": {
+          "value": 31,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "Index": {
+          "value": 32,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "Binding": {
+          "value": 33,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "DescriptorSet": {
+          "value": 34,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "Offset": {
+          "value": 35,
+          "params": [
+            "LiteralInteger"
+          ]
+        },
+        "FPRoundingMode": {
+          "value": 39,
+          "params": [
+            "FPRoundingMode"
+          ]
+        },
+        "NoContraction": {
+          "value": 42
+        },
+        "NoSignedWrap": {
+          "value": 4469
+        },
+        "NoUnsignedWrap": {
+          "value": 4470
+        },
+        "ExplicitInterpAMD": {
+          "value": 4999
+        },
+        "CounterBuffer": {
+          "value": 5634,
+          "params": [
+            "IdRef"
+          ]
+        },
+        "HlslCounterBufferGOOGLE": {
+          "value": 5634,
+          "params": [
+            "IdRef"
+          ]
+        },
+        "UserSemantic": {
+          "value": 5635,
+          "params": [
+            "LiteralString"
+          ]
+        },
+        "HlslSemanticGOOGLE": {
+          "value": 5635,
+          "params": [
+            "LiteralString"
+          ]
+        },
+        "UserTypeGOOGLE": {
+          "value": 5636,
+          "params": [
+            "LiteralString"
+          ]
+        }
+      }
+    },
+    "BuiltIn": {
+      "type": "ValueEnum",
+      "values": {
+        "Position": {
+          "value": 0
+        },
+        "PointSize": {
+          "value": 1
+        },
+        "VertexId": {
+          "value": 5
+        },
+        "InstanceId": {
+          "value": 6
+        },
+        "FragCoord": {
+          "value": 15
+        },
+        "PointCoord": {
+          "value": 16
+        },
+        "FrontFacing": {
+          "value": 17
+        },
+        "SampleMask": {
+          "value": 20
+        },
+        "FragDepth": {
+          "value": 22
+        },
+        "HelperInvocation": {
+          "value": 23
+        },
+        "NumWorkgroups": {
+          "value": 24
+        },
+        "WorkgroupSize": {
+          "value": 25
+        },
+        "WorkgroupId": {
+          "value": 26
+        },
+        "LocalInvocationId": {
+          "value": 27
+        },
+        "GlobalInvocationId": {
+          "value": 28
+        },
+        "LocalInvocationIndex": {
+          "value": 29
+        },
+        "VertexIndex": {
+          "value": 42
+        },
+        "InstanceIndex": {
+          "value": 43
+        },
+        "BaryCoordNoPerspAMD": {
+          "value": 4992
+        },
+        "BaryCoordNoPerspCentroidAMD": {
+          "value": 4993
+        },
+        "BaryCoordNoPerspSampleAMD": {
+          "value": 4994
+        },
+        "BaryCoordSmoothAMD": {
+          "value": 4995
+        },
+        "BaryCoordSmoothCentroidAMD": {
+          "value": 4996
+        },
+        "BaryCoordSmoothSampleAMD": {
+          "value": 4997
+        },
+        "BaryCoordPullModelAMD": {
+          "value": 4998
+        }
+      }
+    },
+    "Scope": {
+      "type": "ValueEnum",
+      "values": {
+        "CrossDevice": {
+          "value": 0
+        },
+        "Device": {
+          "value": 1
+        },
+        "Workgroup": {
+          "value": 2
+        },
+        "Subgroup": {
+          "value": 3
+        },
+        "Invocation": {
+          "value": 4
+        },
+        "QueueFamily": {
+          "value": 5
+        },
+        "QueueFamilyKHR": {
+          "value": 5
+        }
+      }
+    },
+    "Capability": {
+      "type": "ValueEnum",
+      "values": {
+        "Matrix": {
+          "value": 0
+        },
+        "Shader": {
+          "value": 1
+        },
+        "Geometry": {
+          "value": 2
+        },
+        "Tessellation": {
+          "value": 3
+        },
+        "Addresses": {
+          "value": 4
+        },
+        "Linkage": {
+          "value": 5
+        },
+        "Kernel": {
+          "value": 6
+        },
+        "Float16": {
+          "value": 9
+        },
+        "Float64": {
+          "value": 10
+        },
+        "Int64": {
+          "value": 11
+        },
+        "Groups": {
+          "value": 18
+        },
+        "AtomicStorage": {
+          "value": 21
+        },
+        "Int16": {
+          "value": 22
+        },
+        "ImageGatherExtended": {
+          "value": 25
+        },
+        "StorageImageMultisample": {
+          "value": 27
+        },
+        "UniformBufferArrayDynamicIndexing": {
+          "value": 28
+        },
+        "SampledImageArrayDynamicIndexing": {
+          "value": 29
+        },
+        "StorageBufferArrayDynamicIndexing": {
+          "value": 30
+        },
+        "StorageImageArrayDynamicIndexing": {
+          "value": 31
+        },
+        "ClipDistance": {
+          "value": 32
+        },
+        "CullDistance": {
+          "value": 33
+        },
+        "SampleRateShading": {
+          "value": 35
+        },
+        "SampledRect": {
+          "value": 37
+        },
+        "Int8": {
+          "value": 39
+        },
+        "InputAttachment": {
+          "value": 40
+        },
+        "SparseResidency": {
+          "value": 41
+        },
+        "MinLod": {
+          "value": 42
+        },
+        "Sampled1D": {
+          "value": 43
+        },
+        "Image1D": {
+          "value": 44
+        },
+        "SampledCubeArray": {
+          "value": 45
+        },
+        "SampledBuffer": {
+          "value": 46
+        },
+        "ImageMSArray": {
+          "value": 48
+        },
+        "StorageImageExtendedFormats": {
+          "value": 49
+        },
+        "ImageQuery": {
+          "value": 50
+        },
+        "DerivativeControl": {
+          "value": 51
+        },
+        "InterpolationFunction": {
+          "value": 52
+        },
+        "TransformFeedback": {
+          "value": 53
+        },
+        "StorageImageReadWithoutFormat": {
+          "value": 55
+        },
+        "StorageImageWriteWithoutFormat": {
+          "value": 56
+        },
+        "GroupNonUniform": {
+          "value": 61
+        },
+        "ShaderLayer": {
+          "value": 69
+        },
+        "ShaderViewportIndex": {
+          "value": 70
+        },
+        "SubgroupBallotKHR": {
+          "value": 4423
+        },
+        "DrawParameters": {
+          "value": 4427
+        },
+        "SubgroupVoteKHR": {
+          "value": 4431
+        },
+        "StorageBuffer16BitAccess": {
+          "value": 4433
+        },
+        "StorageUniformBufferBlock16": {
+          "value": 4433
+        },
+        "StoragePushConstant16": {
+          "value": 4435
+        },
+        "StorageInputOutput16": {
+          "value": 4436
+        },
+        "DeviceGroup": {
+          "value": 4437
+        },
+        "MultiView": {
+          "value": 4439
+        },
+        "VariablePointersStorageBuffer": {
+          "value": 4441
+        },
+        "AtomicStorageOps": {
+          "value": 4445
+        },
+        "SampleMaskPostDepthCoverage": {
+          "value": 4447
+        },
+        "StorageBuffer8BitAccess": {
+          "value": 4448
+        },
+        "StoragePushConstant8": {
+          "value": 4450
+        },
+        "DenormPreserve": {
+          "value": 4464
+        },
+        "DenormFlushToZero": {
+          "value": 4465
+        },
+        "SignedZeroInfNanPreserve": {
+          "value": 4466
+        },
+        "RoundingModeRTE": {
+          "value": 4467
+        },
+        "RoundingModeRTZ": {
+          "value": 4468
+        },
+        "Float16ImageAMD": {
+          "value": 5008
+        },
+        "ImageGatherBiasLodAMD": {
+          "value": 5009
+        },
+        "FragmentMaskAMD": {
+          "value": 5010
+        },
+        "StencilExportEXT": {
+          "value": 5013
+        },
+        "ImageReadWriteLodAMD": {
+          "value": 5015
+        },
+        "ShaderClockKHR": {
+          "value": 5055
+        },
+        "FragmentFullyCoveredEXT": {
+          "value": 5265
+        },
+        "MeshShadingNV": {
+          "value": 5266
+        },
+        "ImageFootprintNV": {
+          "value": 5282
+        },
+        "FragmentBarycentricNV": {
+          "value": 5284
+        },
+        "ComputeDerivativeGroupQuadsNV": {
+          "value": 5288
+        },
+        "FragmentDensityEXT": {
+          "value": 5291
+        },
+        "ShadingRateNV": {
+          "value": 5291
+        },
+        "GroupNonUniformPartitionedNV": {
+          "value": 5297
+        },
+        "ShaderNonUniform": {
+          "value": 5301
+        },
+        "ShaderNonUniformEXT": {
+          "value": 5301
+        },
+        "RuntimeDescriptorArray": {
+          "value": 5302
+        },
+        "RuntimeDescriptorArrayEXT": {
+          "value": 5302
+        },
+        "RayTracingNV": {
+          "value": 5340
+        },
+        "VulkanMemoryModel": {
+          "value": 5345
+        },
+        "VulkanMemoryModelKHR": {
+          "value": 5345
+        },
+        "VulkanMemoryModelDeviceScope": {
+          "value": 5346
+        },
+        "VulkanMemoryModelDeviceScopeKHR": {
+          "value": 5346
+        },
+        "PhysicalStorageBufferAddresses": {
+          "value": 5347
+        },
+        "PhysicalStorageBufferAddressesEXT": {
+          "value": 5347
+        },
+        "ComputeDerivativeGroupLinearNV": {
+          "value": 5350
+        },
+        "CooperativeMatrixNV": {
+          "value": 5357
+        },
+        "FragmentShaderSampleInterlockEXT": {
+          "value": 5363
+        },
+        "FragmentShaderShadingRateInterlockEXT": {
+          "value": 5372
+        },
+        "ShaderSMBuiltinsNV": {
+          "value": 5373
+        },
+        "FragmentShaderPixelInterlockEXT": {
+          "value": 5378
+        },
+        "DemoteToHelperInvocationEXT": {
+          "value": 5379
+        },
+        "SubgroupShuffleINTEL": {
+          "value": 5568
+        },
+        "SubgroupBufferBlockIOINTEL": {
+          "value": 5569
+        },
+        "SubgroupImageBlockIOINTEL": {
+          "value": 5570
+        },
+        "SubgroupImageMediaBlockIOINTEL": {
+          "value": 5579
+        },
+        "IntegerFunctions2INTEL": {
+          "value": 5584
+        },
+        "SubgroupAvcMotionEstimationINTEL": {
+          "value": 5696
+        },
+        "SubgroupAvcMotionEstimationIntraINTEL": {
+          "value": 5697
+        },
+        "SubgroupAvcMotionEstimationChromaINTEL": {
+          "value": 5698
+        }
+      }
+    }
+  },
+  "ext": {
+    "Round": 1,
+    "RoundEven": 2,
+    "Trunc": 3,
+    "FAbs": 4,
+    "SAbs": 5,
+    "FSign": 6,
+    "SSign": 7,
+    "Floor": 8,
+    "Ceil": 9,
+    "Fract": 10,
+    "Radians": 11,
+    "Degrees": 12,
+    "Sin": 13,
+    "Cos": 14,
+    "Tan": 15,
+    "Asin": 16,
+    "Acos": 17,
+    "Atan": 18,
+    "Sinh": 19,
+    "Cosh": 20,
+    "Tanh": 21,
+    "Asinh": 22,
+    "Acosh": 23,
+    "Atanh": 24,
+    "Atan2": 25,
+    "Pow": 26,
+    "Exp": 27,
+    "Log": 28,
+    "Exp2": 29,
+    "Log2": 30,
+    "Sqrt": 31,
+    "InverseSqrt": 32,
+    "Determinant": 33,
+    "MatrixInverse": 34,
+    "Modf": 35,
+    "ModfStruct": 36,
+    "FMin": 37,
+    "UMin": 38,
+    "SMin": 39,
+    "FMax": 40,
+    "UMax": 41,
+    "SMax": 42,
+    "FClamp": 43,
+    "UClamp": 44,
+    "SClamp": 45,
+    "FMix": 46,
+    "IMix": 47,
+    "Step": 48,
+    "SmoothStep": 49,
+    "Fma": 50,
+    "Frexp": 51,
+    "FrexpStruct": 52,
+    "Ldexp": 53,
+    "PackSnorm4x8": 54,
+    "PackUnorm4x8": 55,
+    "PackSnorm2x16": 56,
+    "PackUnorm2x16": 57,
+    "PackHalf2x16": 58,
+    "PackDouble2x32": 59,
+    "UnpackSnorm2x16": 60,
+    "UnpackUnorm2x16": 61,
+    "UnpackHalf2x16": 62,
+    "UnpackSnorm4x8": 63,
+    "UnpackUnorm4x8": 64,
+    "UnpackDouble2x32": 65,
+    "Length": 66,
+    "Distance": 67,
+    "Cross": 68,
+    "Normalize": 69,
+    "FaceForward": 70,
+    "Reflect": 71,
+    "Refract": 72,
+    "FindILsb": 73,
+    "FindSMsb": 74,
+    "FindUMsb": 75,
+    "InterpolateAtCentroid": 76,
+    "InterpolateAtSample": 77,
+    "InterpolateAtOffset": 78,
+    "NMin": 79,
+    "NMax": 80,
+    "NClamp": 81
+  }
+}

+ 40 - 0
3rdparty/spirv-tools/tools/sva/src/sva.js

@@ -0,0 +1,40 @@
+// Copyright 2019 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.
+
+import Parser from "./parser.js";
+import Lexer from "./lexer.js";
+import Assembler from "./assembler.js";
+
+import grammar from "./spirv.data.js";
+
+export default class SVA {
+  /**
+   * Attempts to convert |input| SPIR-V assembly into SPIR-V binary.
+   *
+   * @param {String} the input string containing the assembly
+   * @return {Uint32Array|string} returns a Uint32Array containing the binary
+   *                             SPIR-V or a string on error.
+   */
+  static assemble(input) {
+    let l = new Lexer(input);
+    let p = new Parser(grammar, l);
+
+    let ast = p.parse();
+    if (ast === undefined)
+      return p.error;
+
+    let a = new Assembler(ast);
+    return a.assemble();
+  }
+}

+ 55 - 0
3rdparty/spirv-tools/tools/sva/src/token.js

@@ -0,0 +1,55 @@
+// Copyright 2019 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.
+
+const TokenType = {
+  kEOF: "end of file",
+  kError: "error",
+
+  kIdentifier: "identifier",
+
+  kIntegerLiteral: "integer_literal",
+  kFloatLiteral: "float_literal",
+  kStringLiteral: "string_literal",
+  kResultId: "result_id",
+
+  kOp: "Op",
+  kEqual: "=",
+  kPipe: "|",
+};
+
+class Token {
+  /**
+   * @param {TokenType} type The type of token
+   * @param {Integer} line The line number this token was on
+   * @param {Any} data Data attached to the token
+   * @param {Integer} bits If the type is a float or integer the bit width
+   */
+  constructor(type, line, data) {
+    this.type_ = type;
+    this.line_ = line;
+    this.data_ = data;
+    this.bits_ = 0;
+  }
+
+  get type() { return this.type_; }
+  get line() { return this.line_; }
+
+  get data() { return this.data_; }
+  set data(val) { this.data_ = val; }
+
+  get bits() { return this.bits_; }
+  set bits(val) { this.bits_ = val; }
+}
+
+export {Token, TokenType};

+ 18 - 0
3rdparty/spirv-tools/tools/sva/tests/empty_main.spv_asm

@@ -0,0 +1,18 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 6
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main"
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 440
+               OpName %main "main"
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd

+ 23 - 0
3rdparty/spirv-tools/tools/sva/tests/index.html

@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+<head>
+  <meta charset='utf-8'>
+</head>
+<body>
+  <pre id='code'><code></code></pre>
+
+  <script type="module">
+    let c = document.getElementById('code');
+
+    import SVA from "/build/sva.js";
+
+    let assembly = SVA.assemble("OpCapability Shader");
+    if (typeof assembly === "string") {
+      c.innerText = assembly;
+    } else {
+      c.innerText = Array.from(assembly)
+        .map(b => b.toString(16).padStart(8, "0")).join(" ");
+    }
+  </script>
+</body>
+</html>

+ 30 - 0
3rdparty/spirv-tools/tools/sva/tests/simple.spv_asm

@@ -0,0 +1,30 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 14
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %gl_FragColor
+               OpExecutionMode %main OriginUpperLeft
+               OpSource GLSL 330
+               OpName %main "main"
+               OpName %gl_FragColor "gl_FragColor"
+               OpDecorate %gl_FragColor Location 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%gl_FragColor = OpVariable %_ptr_Output_v4float Output
+%float_0_400000006 = OpConstant %float 0.400000006
+%float_0_800000012 = OpConstant %float 0.800000012
+    %float_1 = OpConstant %float 1
+         %13 = OpConstantComposite %v4float %float_0_400000006 %float_0_400000006 %float_0_800000012 %float_1
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpStore %gl_FragColor %13
+               OpReturn
+               OpFunctionEnd
+

+ 119 - 0
3rdparty/spirv-tools/tools/sva/tools/process_grammar.rb

@@ -0,0 +1,119 @@
+#!/usr/bin/env ruby
+
+# Copyright 2019 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.
+
+require 'json'
+
+GRAMMAR = "../../external/spirv-headers/include/spirv/unified1/spirv.core.grammar.json"
+GLSL = "../../external/spirv-headers/include/spirv/unified1/extinst.glsl.std.450.grammar.json"
+
+CAPABILITIES = %w(
+      Matrix
+      Shader
+      Sampled1D
+      Image1D
+      DerivativeControl
+      ImageQuery
+      VulkanMemoryModel
+)
+
+g = JSON.parse(File.open(GRAMMAR).read)
+magic = g['magic_number']
+vers = [g['major_version'], g['minor_version']]
+instructions = {}
+
+g['instructions'].each do |inst|
+  if (inst.has_key?('capabilities'))
+    skip = true
+    inst['capabilities'].each do |cap|
+      if CAPABILITIES.include?(cap)
+        skip = false
+        break
+      end
+    end
+    next if skip
+  end
+
+  op = {
+    opcode: inst['opcode'],
+    operands: []
+  }
+
+  if !inst['operands'].nil?
+    inst['operands'].each do |operand|
+      operand.delete('name')
+      op[:operands] << operand
+    end
+  end
+
+  instructions[inst['opname']] = op
+end
+
+operand_kinds = {}
+g['operand_kinds'].each do |op_kind|
+  next if op_kind['category'] !~ /Enum/
+
+  kind = {
+    type: op_kind['category'],
+    values: {}
+  }
+
+  op_kind['enumerants'].each do |enum|
+    if (enum.has_key?('capabilities'))
+      skip = true
+      enum['capabilities'].each do |cap|
+        if CAPABILITIES.include?(cap)
+          skip = false
+          break
+        end
+      end
+      next if skip
+    end
+
+    v = if op_kind['category'] == 'BitEnum'
+      enum['value'].to_i(16)
+    else
+      enum['value'].to_i
+    end
+    params = []
+    if enum.has_key?('parameters')
+      enum['parameters'].each do |param|
+        params << param['kind']
+      end
+    end
+    kind[:values][enum['enumerant']] = {value: v}
+    kind[:values][enum['enumerant']][:params] = params unless params.empty?
+  end
+
+  next if kind[:values].empty?
+  operand_kinds[op_kind['kind']] = kind
+end
+
+# We only support GLSL extensions at the moment.
+ext = {}
+glsl = JSON.parse(File.open(GLSL).read)
+glsl['instructions'].each do |inst|
+  ext[inst['opname']] = inst['opcode']
+end
+
+puts "/*#{g['copyright'].join("\n")}*/"
+puts "\n// THIS FILE IS GENERATED WITH tools/process_grammar.rb\n\n"
+puts "export default " + JSON.pretty_generate({
+  magic: magic,
+  version: vers,
+  instructions: instructions,
+  operand_kinds: operand_kinds,
+  ext: ext
+})

+ 1778 - 0
3rdparty/spirv-tools/tools/sva/yarn.lock

@@ -0,0 +1,1778 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/code-frame@^7.0.0":
+  version "7.5.5"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
+  integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==
+  dependencies:
+    "@babel/highlight" "^7.0.0"
+
+"@babel/highlight@^7.0.0":
+  version "7.5.0"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540"
+  integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==
+  dependencies:
+    chalk "^2.0.0"
+    esutils "^2.0.2"
+    js-tokens "^4.0.0"
+
+"@types/[email protected]":
+  version "0.0.39"
+  resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
+  integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
+
+"@types/node@^12.7.5":
+  version "12.7.5"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.5.tgz#e19436e7f8e9b4601005d73673b6dc4784ffcc2f"
+  integrity sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==
+
+"@zeit/[email protected]":
+  version "2.6.0"
+  resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-2.6.0.tgz#004e8e553b4cd53d538bd38eac7bcbf58a867fe3"
+  integrity sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==
+
+accepts@~1.3.5:
+  version "1.3.7"
+  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
+  integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
+  dependencies:
+    mime-types "~2.1.24"
+    negotiator "0.6.2"
+
+acorn-jsx@^5.0.2:
+  version "5.0.2"
+  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f"
+  integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==
+
+acorn@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a"
+  integrity sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==
+
[email protected]:
+  version "6.5.3"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.3.tgz#71a569d189ecf4f4f321224fecb166f071dd90f9"
+  integrity sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==
+  dependencies:
+    fast-deep-equal "^2.0.1"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.4.1"
+    uri-js "^4.2.2"
+
+ajv@^6.10.0, ajv@^6.10.2:
+  version "6.10.2"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52"
+  integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==
+  dependencies:
+    fast-deep-equal "^2.0.1"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.4.1"
+    uri-js "^4.2.2"
+
+ansi-align@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f"
+  integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=
+  dependencies:
+    string-width "^2.0.0"
+
[email protected]:
+  version "3.2.3"
+  resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813"
+  integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==
+
+ansi-escapes@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
+  integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
+
+ansi-regex@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+  integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
+
+ansi-regex@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+  integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
+
+ansi-regex@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
+  integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
+
+ansi-styles@^3.2.0, ansi-styles@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+  integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+  dependencies:
+    color-convert "^1.9.0"
+
+arch@^2.1.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e"
+  integrity sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg==
+
[email protected]:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/arg/-/arg-2.0.0.tgz#c06e7ff69ab05b3a4a03ebe0407fac4cba657545"
+  integrity sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w==
+
+argparse@^1.0.7:
+  version "1.0.10"
+  resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+  integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+  dependencies:
+    sprintf-js "~1.0.2"
+
+assertion-error@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
+  integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
+
+astral-regex@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
+  integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
+
+balanced-match@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+  integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+
[email protected]:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
+  integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==
+  dependencies:
+    ansi-align "^2.0.0"
+    camelcase "^4.0.0"
+    chalk "^2.0.1"
+    cli-boxes "^1.0.0"
+    string-width "^2.0.0"
+    term-size "^1.2.0"
+    widest-line "^2.0.0"
+
+brace-expansion@^1.1.7:
+  version "1.1.11"
+  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+  integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+  dependencies:
+    balanced-match "^1.0.0"
+    concat-map "0.0.1"
+
[email protected]:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
+  integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
+
[email protected]:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+  integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
+
+callsites@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+  integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+camelcase@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
+  integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
+
+camelcase@^5.0.0:
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+  integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+chai@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5"
+  integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==
+  dependencies:
+    assertion-error "^1.1.0"
+    check-error "^1.0.2"
+    deep-eql "^3.0.1"
+    get-func-name "^2.0.0"
+    pathval "^1.1.0"
+    type-detect "^4.0.5"
+
[email protected]:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
+  integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==
+  dependencies:
+    ansi-styles "^3.2.1"
+    escape-string-regexp "^1.0.5"
+    supports-color "^5.3.0"
+
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2:
+  version "2.4.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+  integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+  dependencies:
+    ansi-styles "^3.2.1"
+    escape-string-regexp "^1.0.5"
+    supports-color "^5.3.0"
+
+chardet@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
+  integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
+
+check-error@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
+  integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=
+
+cli-boxes@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
+  integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM=
+
+cli-cursor@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+  integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
+  dependencies:
+    restore-cursor "^2.0.0"
+
+cli-width@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
+  integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
+
[email protected]:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.3.tgz#0526361bf78724c1f20be248d428e365433c07ef"
+  integrity sha512-2WNImOvCRe6r63Gk9pShfkwXsVtKCroMAevIbiae021mS850UkWPbevxsBz3tnvjZIEGvlwaqCPsw+4ulzNgJA==
+  dependencies:
+    arch "^2.1.0"
+    execa "^0.8.0"
+
+cliui@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
+  integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==
+  dependencies:
+    string-width "^2.1.1"
+    strip-ansi "^4.0.0"
+    wrap-ansi "^2.0.0"
+
+code-point-at@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+  integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
+
+color-convert@^1.9.0:
+  version "1.9.3"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+  integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+  dependencies:
+    color-name "1.1.3"
+
[email protected]:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+  integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+
+compressible@~2.0.14:
+  version "2.0.17"
+  resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1"
+  integrity sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==
+  dependencies:
+    mime-db ">= 1.40.0 < 2"
+
[email protected]:
+  version "1.7.3"
+  resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.3.tgz#27e0e176aaf260f7f2c2813c3e440adb9f1993db"
+  integrity sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==
+  dependencies:
+    accepts "~1.3.5"
+    bytes "3.0.0"
+    compressible "~2.0.14"
+    debug "2.6.9"
+    on-headers "~1.0.1"
+    safe-buffer "5.1.2"
+    vary "~1.1.2"
+
[email protected]:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+  integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+
[email protected]:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
+  integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ=
+
+cross-spawn@^5.0.1:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
+  integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=
+  dependencies:
+    lru-cache "^4.0.1"
+    shebang-command "^1.2.0"
+    which "^1.2.9"
+
+cross-spawn@^6.0.0, cross-spawn@^6.0.5:
+  version "6.0.5"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+  integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
+  dependencies:
+    nice-try "^1.0.4"
+    path-key "^2.0.1"
+    semver "^5.5.0"
+    shebang-command "^1.2.0"
+    which "^1.2.9"
+
[email protected]:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+  dependencies:
+    ms "2.0.0"
+
[email protected]:
+  version "3.2.6"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
+  integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
+  dependencies:
+    ms "^2.1.1"
+
+debug@^4.0.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+  integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
+  dependencies:
+    ms "^2.1.1"
+
+decamelize@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+  integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+
+deep-eql@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
+  integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==
+  dependencies:
+    type-detect "^4.0.0"
+
+deep-extend@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+  integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
+
+deep-is@~0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+  integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
+
+define-properties@^1.1.2, define-properties@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
+  integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
+  dependencies:
+    object-keys "^1.0.12"
+
[email protected]:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
+  integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
+
+doctrine@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
+  integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
+  dependencies:
+    esutils "^2.0.2"
+
+emoji-regex@^7.0.1:
+  version "7.0.3"
+  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
+  integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
+
+end-of-stream@^1.1.0:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
+  integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
+  dependencies:
+    once "^1.4.0"
+
+es-abstract@^1.5.1:
+  version "1.14.2"
+  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.14.2.tgz#7ce108fad83068c8783c3cdf62e504e084d8c497"
+  integrity sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg==
+  dependencies:
+    es-to-primitive "^1.2.0"
+    function-bind "^1.1.1"
+    has "^1.0.3"
+    has-symbols "^1.0.0"
+    is-callable "^1.1.4"
+    is-regex "^1.0.4"
+    object-inspect "^1.6.0"
+    object-keys "^1.1.1"
+    string.prototype.trimleft "^2.0.0"
+    string.prototype.trimright "^2.0.0"
+
+es-to-primitive@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377"
+  integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==
+  dependencies:
+    is-callable "^1.1.4"
+    is-date-object "^1.0.1"
+    is-symbol "^1.0.2"
+
[email protected], escape-string-regexp@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+  integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+
+eslint-scope@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9"
+  integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==
+  dependencies:
+    esrecurse "^4.1.0"
+    estraverse "^4.1.1"
+
+eslint-utils@^1.4.2:
+  version "1.4.2"
+  resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab"
+  integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==
+  dependencies:
+    eslint-visitor-keys "^1.0.0"
+
+eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
+  integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
+
+eslint@^6.3.0:
+  version "6.4.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.4.0.tgz#5aa9227c3fbe921982b2eda94ba0d7fae858611a"
+  integrity sha512-WTVEzK3lSFoXUovDHEbkJqCVPEPwbhCq4trDktNI6ygs7aO41d4cDT0JFAT5MivzZeVLWlg7vHL+bgrQv/t3vA==
+  dependencies:
+    "@babel/code-frame" "^7.0.0"
+    ajv "^6.10.0"
+    chalk "^2.1.0"
+    cross-spawn "^6.0.5"
+    debug "^4.0.1"
+    doctrine "^3.0.0"
+    eslint-scope "^5.0.0"
+    eslint-utils "^1.4.2"
+    eslint-visitor-keys "^1.1.0"
+    espree "^6.1.1"
+    esquery "^1.0.1"
+    esutils "^2.0.2"
+    file-entry-cache "^5.0.1"
+    functional-red-black-tree "^1.0.1"
+    glob-parent "^5.0.0"
+    globals "^11.7.0"
+    ignore "^4.0.6"
+    import-fresh "^3.0.0"
+    imurmurhash "^0.1.4"
+    inquirer "^6.4.1"
+    is-glob "^4.0.0"
+    js-yaml "^3.13.1"
+    json-stable-stringify-without-jsonify "^1.0.1"
+    levn "^0.3.0"
+    lodash "^4.17.14"
+    minimatch "^3.0.4"
+    mkdirp "^0.5.1"
+    natural-compare "^1.4.0"
+    optionator "^0.8.2"
+    progress "^2.0.0"
+    regexpp "^2.0.1"
+    semver "^6.1.2"
+    strip-ansi "^5.2.0"
+    strip-json-comments "^3.0.1"
+    table "^5.2.3"
+    text-table "^0.2.0"
+    v8-compile-cache "^2.0.3"
+
+esm@^3.2.25:
+  version "3.2.25"
+  resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10"
+  integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==
+
+espree@^6.1.1:
+  version "6.1.1"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.1.tgz#7f80e5f7257fc47db450022d723e356daeb1e5de"
+  integrity sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ==
+  dependencies:
+    acorn "^7.0.0"
+    acorn-jsx "^5.0.2"
+    eslint-visitor-keys "^1.1.0"
+
+esprima@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+  integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+esquery@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708"
+  integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==
+  dependencies:
+    estraverse "^4.0.0"
+
+esrecurse@^4.1.0:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf"
+  integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==
+  dependencies:
+    estraverse "^4.1.0"
+
+estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+  integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+esutils@^2.0.2:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+  integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+execa@^0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
+  integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=
+  dependencies:
+    cross-spawn "^5.0.1"
+    get-stream "^3.0.0"
+    is-stream "^1.1.0"
+    npm-run-path "^2.0.0"
+    p-finally "^1.0.0"
+    signal-exit "^3.0.0"
+    strip-eof "^1.0.0"
+
+execa@^0.8.0:
+  version "0.8.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da"
+  integrity sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=
+  dependencies:
+    cross-spawn "^5.0.1"
+    get-stream "^3.0.0"
+    is-stream "^1.1.0"
+    npm-run-path "^2.0.0"
+    p-finally "^1.0.0"
+    signal-exit "^3.0.0"
+    strip-eof "^1.0.0"
+
+execa@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
+  integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
+  dependencies:
+    cross-spawn "^6.0.0"
+    get-stream "^4.0.0"
+    is-stream "^1.1.0"
+    npm-run-path "^2.0.0"
+    p-finally "^1.0.0"
+    signal-exit "^3.0.0"
+    strip-eof "^1.0.0"
+
+external-editor@^3.0.3:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
+  integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
+  dependencies:
+    chardet "^0.7.0"
+    iconv-lite "^0.4.24"
+    tmp "^0.0.33"
+
+fast-deep-equal@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
+  integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
+
+fast-json-stable-stringify@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
+  integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
+
+fast-levenshtein@~2.0.4:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+  integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
+
[email protected]:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d"
+  integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=
+  dependencies:
+    punycode "^1.3.2"
+
+figures@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
+  integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
+  dependencies:
+    escape-string-regexp "^1.0.5"
+
+file-entry-cache@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c"
+  integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==
+  dependencies:
+    flat-cache "^2.0.1"
+
[email protected], find-up@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+  integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+  dependencies:
+    locate-path "^3.0.0"
+
+flat-cache@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
+  integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==
+  dependencies:
+    flatted "^2.0.0"
+    rimraf "2.6.3"
+    write "1.0.3"
+
+flat@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2"
+  integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==
+  dependencies:
+    is-buffer "~2.0.3"
+
+flatted@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08"
+  integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==
+
+fs.realpath@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+  integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
+
+function-bind@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+  integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+functional-red-black-tree@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
+  integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
+
+get-caller-file@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
+  integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
+
+get-caller-file@^2.0.1:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+  integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
+get-func-name@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
+  integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=
+
+get-stream@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
+  integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
+
+get-stream@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
+  integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
+  dependencies:
+    pump "^3.0.0"
+
+glob-parent@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954"
+  integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==
+  dependencies:
+    is-glob "^4.0.1"
+
[email protected]:
+  version "7.1.3"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
+  integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+glob@^7.1.3:
+  version "7.1.4"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
+  integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+globals@^11.7.0:
+  version "11.12.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
+  integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
[email protected]:
+  version "1.10.5"
+  resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
+  integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
+
+has-flag@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+  integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+
+has-symbols@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44"
+  integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=
+
+has@^1.0.1, has@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+  integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+  dependencies:
+    function-bind "^1.1.1"
+
[email protected]:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
+  integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
+
+iconv-lite@^0.4.24:
+  version "0.4.24"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+  integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+  dependencies:
+    safer-buffer ">= 2.1.2 < 3"
+
+ignore@^4.0.6:
+  version "4.0.6"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
+  integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
+
+import-fresh@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118"
+  integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==
+  dependencies:
+    parent-module "^1.0.0"
+    resolve-from "^4.0.0"
+
+imurmurhash@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+  integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
+
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"
+
+inherits@2:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+  integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+ini@~1.3.0:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
+  integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
+
+inquirer@^6.4.1:
+  version "6.5.2"
+  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca"
+  integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==
+  dependencies:
+    ansi-escapes "^3.2.0"
+    chalk "^2.4.2"
+    cli-cursor "^2.1.0"
+    cli-width "^2.0.0"
+    external-editor "^3.0.3"
+    figures "^2.0.0"
+    lodash "^4.17.12"
+    mute-stream "0.0.7"
+    run-async "^2.2.0"
+    rxjs "^6.4.0"
+    string-width "^2.1.0"
+    strip-ansi "^5.1.0"
+    through "^2.3.6"
+
+invert-kv@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
+  integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
+
+is-buffer@~2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
+  integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
+
+is-callable@^1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
+  integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
+
+is-date-object@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
+  integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=
+
+is-extglob@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+  integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
+
+is-fullwidth-code-point@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+  integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
+  dependencies:
+    number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+  integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
+
+is-glob@^4.0.0, is-glob@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
+  integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
+  dependencies:
+    is-extglob "^2.1.1"
+
+is-promise@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
+  integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
+
+is-regex@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
+  integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=
+  dependencies:
+    has "^1.0.1"
+
+is-stream@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+  integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
+
+is-symbol@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
+  integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==
+  dependencies:
+    has-symbols "^1.0.0"
+
+isexe@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+  integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
+
+js-tokens@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+  integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
[email protected], js-yaml@^3.13.1:
+  version "3.13.1"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
+  integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
+  dependencies:
+    argparse "^1.0.7"
+    esprima "^4.0.0"
+
+json-schema-traverse@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+  integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json-stable-stringify-without-jsonify@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+  integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
+
+lcid@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
+  integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
+  dependencies:
+    invert-kv "^2.0.0"
+
+levn@^0.3.0, levn@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+  integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
+  dependencies:
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+
+locate-path@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+  integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+  dependencies:
+    p-locate "^3.0.0"
+    path-exists "^3.0.0"
+
+lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14:
+  version "4.17.15"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
+  integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
+
[email protected]:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
+  integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
+  dependencies:
+    chalk "^2.0.1"
+
+lru-cache@^4.0.1:
+  version "4.1.5"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
+  integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
+  dependencies:
+    pseudomap "^1.0.2"
+    yallist "^2.1.2"
+
+map-age-cleaner@^0.1.1:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
+  integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
+  dependencies:
+    p-defer "^1.0.0"
+
+mem@^4.0.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
+  integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
+  dependencies:
+    map-age-cleaner "^0.1.1"
+    mimic-fn "^2.0.0"
+    p-is-promise "^2.0.0"
+
[email protected]:
+  version "1.40.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32"
+  integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==
+
+"mime-db@>= 1.40.0 < 2":
+  version "1.41.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.41.0.tgz#9110408e1f6aa1b34aef51f2c9df3caddf46b6a0"
+  integrity sha512-B5gxBI+2K431XW8C2rcc/lhppbuji67nf9v39eH8pkWoZDxnAL0PxdpH32KYRScniF8qDHBDlI+ipgg5WrCUYw==
+
+mime-db@~1.33.0:
+  version "1.33.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
+  integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==
+
[email protected]:
+  version "2.1.18"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
+  integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==
+  dependencies:
+    mime-db "~1.33.0"
+
+mime-types@~2.1.24:
+  version "2.1.24"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81"
+  integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==
+  dependencies:
+    mime-db "1.40.0"
+
+mimic-fn@^1.0.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
+  integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
+
+mimic-fn@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+  integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
[email protected], minimatch@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+  integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+  dependencies:
+    brace-expansion "^1.1.7"
+
[email protected]:
+  version "0.0.8"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+  integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
+
+minimist@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+  integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
+
[email protected], mkdirp@^0.5.1:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+  integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
+  dependencies:
+    minimist "0.0.8"
+
+mocha@^6.2.0:
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.0.tgz#f896b642843445d1bb8bca60eabd9206b8916e56"
+  integrity sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==
+  dependencies:
+    ansi-colors "3.2.3"
+    browser-stdout "1.3.1"
+    debug "3.2.6"
+    diff "3.5.0"
+    escape-string-regexp "1.0.5"
+    find-up "3.0.0"
+    glob "7.1.3"
+    growl "1.10.5"
+    he "1.2.0"
+    js-yaml "3.13.1"
+    log-symbols "2.2.0"
+    minimatch "3.0.4"
+    mkdirp "0.5.1"
+    ms "2.1.1"
+    node-environment-flags "1.0.5"
+    object.assign "4.1.0"
+    strip-json-comments "2.0.1"
+    supports-color "6.0.0"
+    which "1.3.1"
+    wide-align "1.1.3"
+    yargs "13.2.2"
+    yargs-parser "13.0.0"
+    yargs-unparser "1.5.0"
+
[email protected]:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+  integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+
[email protected]:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+  integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
+
+ms@^2.1.1:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+  integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
[email protected]:
+  version "0.0.7"
+  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
+  integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
+
+natural-compare@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+  integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
+
[email protected]:
+  version "0.6.2"
+  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
+  integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
+
+nice-try@^1.0.4:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+  integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+
[email protected]:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a"
+  integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==
+  dependencies:
+    object.getownpropertydescriptors "^2.0.3"
+    semver "^5.7.0"
+
+npm-run-path@^2.0.0:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
+  integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
+  dependencies:
+    path-key "^2.0.0"
+
+number-is-nan@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+  integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
+
+object-inspect@^1.6.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b"
+  integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==
+
+object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
+  integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
+
[email protected]:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
+  integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
+  dependencies:
+    define-properties "^1.1.2"
+    function-bind "^1.1.1"
+    has-symbols "^1.0.0"
+    object-keys "^1.0.11"
+
+object.getownpropertydescriptors@^2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
+  integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=
+  dependencies:
+    define-properties "^1.1.2"
+    es-abstract "^1.5.1"
+
+on-headers@~1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
+  integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
+
+once@^1.3.0, once@^1.3.1, once@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+  integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
+  dependencies:
+    wrappy "1"
+
+onetime@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+  integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=
+  dependencies:
+    mimic-fn "^1.0.0"
+
+optionator@^0.8.2:
+  version "0.8.2"
+  resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
+  integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=
+  dependencies:
+    deep-is "~0.1.3"
+    fast-levenshtein "~2.0.4"
+    levn "~0.3.0"
+    prelude-ls "~1.1.2"
+    type-check "~0.3.2"
+    wordwrap "~1.0.0"
+
+os-locale@^3.0.0, os-locale@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
+  integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
+  dependencies:
+    execa "^1.0.0"
+    lcid "^2.0.0"
+    mem "^4.0.0"
+
+os-tmpdir@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+  integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
+
+p-defer@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
+  integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
+
+p-finally@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
+  integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
+
+p-is-promise@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
+  integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
+
+p-limit@^2.0.0:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537"
+  integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==
+  dependencies:
+    p-try "^2.0.0"
+
+p-locate@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+  integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+  dependencies:
+    p-limit "^2.0.0"
+
+p-try@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+  integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+parent-module@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
+  integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+  dependencies:
+    callsites "^3.0.0"
+
+path-exists@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+  integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
+
+path-is-absolute@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+  integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
+
[email protected]:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+  integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
+
+path-key@^2.0.0, path-key@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+  integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
+
[email protected]:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45"
+  integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==
+
+pathval@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"
+  integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA=
+
+prelude-ls@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+  integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
+
+progress@^2.0.0:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
+  integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
+
+pseudomap@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+  integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
+
+pump@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+  integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
+  dependencies:
+    end-of-stream "^1.1.0"
+    once "^1.3.1"
+
+punycode@^1.3.2:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+  integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
+
+punycode@^2.1.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
+  integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+
[email protected]:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
+  integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=
+
+rc@^1.0.1, rc@^1.1.6:
+  version "1.2.8"
+  resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
+  integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
+  dependencies:
+    deep-extend "^0.6.0"
+    ini "~1.3.0"
+    minimist "^1.2.0"
+    strip-json-comments "~2.0.1"
+
+regexpp@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
+  integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
+
[email protected]:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20"
+  integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==
+  dependencies:
+    rc "^1.1.6"
+    safe-buffer "^5.0.1"
+
[email protected]:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942"
+  integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI=
+  dependencies:
+    rc "^1.0.1"
+
+require-directory@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+  integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
+
+require-main-filename@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+  integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
+
+require-main-filename@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
+  integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+
+resolve-from@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+  integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+restore-cursor@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
+  integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368=
+  dependencies:
+    onetime "^2.0.0"
+    signal-exit "^3.0.2"
+
[email protected]:
+  version "2.6.3"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
+  integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
+  dependencies:
+    glob "^7.1.3"
+
+rollup@^1.21.4:
+  version "1.21.4"
+  resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.21.4.tgz#00a41a30f90095db890301b226cbe2918e4cf54d"
+  integrity sha512-Pl512XVCmVzgcBz5h/3Li4oTaoDcmpuFZ+kdhS/wLreALz//WuDAMfomD3QEYl84NkDu6Z6wV9twlcREb4qQsw==
+  dependencies:
+    "@types/estree" "0.0.39"
+    "@types/node" "^12.7.5"
+    acorn "^7.0.0"
+
+run-async@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
+  integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA=
+  dependencies:
+    is-promise "^2.1.0"
+
+rxjs@^6.4.0:
+  version "6.5.3"
+  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a"
+  integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==
+  dependencies:
+    tslib "^1.9.0"
+
[email protected]:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+  integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+safe-buffer@^5.0.1:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
+  integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
+
+"safer-buffer@>= 2.1.2 < 3":
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+  integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+semver@^5.5.0, semver@^5.7.0:
+  version "5.7.1"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+  integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
+semver@^6.1.2:
+  version "6.3.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
+  integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
[email protected]:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.0.tgz#f1606dc6ff8f9029a1ee042c11dfe7903a5cb92e"
+  integrity sha512-63N075Tn3PsFYcu0NVV7tb367UbiW3gnC+/50ohL4oqOhAG6bmbaWqiRcXQgbzqc0ALBjSAzg7VTfa0Qw4E3hA==
+  dependencies:
+    bytes "3.0.0"
+    content-disposition "0.5.2"
+    fast-url-parser "1.1.3"
+    mime-types "2.1.18"
+    minimatch "3.0.4"
+    path-is-inside "1.0.2"
+    path-to-regexp "2.2.1"
+    range-parser "1.2.0"
+
+serve@^11.1.0:
+  version "11.1.0"
+  resolved "https://registry.yarnpkg.com/serve/-/serve-11.1.0.tgz#1bfe2f4a08d0130cbf44711cdb7996cb742172e0"
+  integrity sha512-+4wpDtOSS+4ZLyDWMxThutA3iOTawX2+yDovOI8cjOUOmemyvNlHyFAsezBlSgbZKTYChI3tzA1Mh0z6XZ62qA==
+  dependencies:
+    "@zeit/schemas" "2.6.0"
+    ajv "6.5.3"
+    arg "2.0.0"
+    boxen "1.3.0"
+    chalk "2.4.1"
+    clipboardy "1.2.3"
+    compression "1.7.3"
+    serve-handler "6.1.0"
+    update-check "1.5.2"
+
+set-blocking@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+  integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
+
+shebang-command@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+  integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
+  dependencies:
+    shebang-regex "^1.0.0"
+
+shebang-regex@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+  integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
+
+signal-exit@^3.0.0, signal-exit@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
+  integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
+
+slice-ansi@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
+  integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==
+  dependencies:
+    ansi-styles "^3.2.0"
+    astral-regex "^1.0.0"
+    is-fullwidth-code-point "^2.0.0"
+
+sprintf-js@~1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+  integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
+
+string-width@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+  integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
+  dependencies:
+    code-point-at "^1.0.0"
+    is-fullwidth-code-point "^1.0.0"
+    strip-ansi "^3.0.0"
+
+"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
+  integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
+  dependencies:
+    is-fullwidth-code-point "^2.0.0"
+    strip-ansi "^4.0.0"
+
+string-width@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
+  integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
+  dependencies:
+    emoji-regex "^7.0.1"
+    is-fullwidth-code-point "^2.0.0"
+    strip-ansi "^5.1.0"
+
+string.prototype.trimleft@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634"
+  integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==
+  dependencies:
+    define-properties "^1.1.3"
+    function-bind "^1.1.1"
+
+string.prototype.trimright@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58"
+  integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==
+  dependencies:
+    define-properties "^1.1.3"
+    function-bind "^1.1.1"
+
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+  integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
+  dependencies:
+    ansi-regex "^2.0.0"
+
+strip-ansi@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+  integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
+  dependencies:
+    ansi-regex "^3.0.0"
+
+strip-ansi@^5.1.0, strip-ansi@^5.2.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
+  integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
+  dependencies:
+    ansi-regex "^4.1.0"
+
+strip-eof@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
+  integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
+
[email protected], strip-json-comments@~2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+  integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
+
+strip-json-comments@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7"
+  integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==
+
[email protected]:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a"
+  integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==
+  dependencies:
+    has-flag "^3.0.0"
+
+supports-color@^5.3.0:
+  version "5.5.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+  integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+  dependencies:
+    has-flag "^3.0.0"
+
+table@^5.2.3:
+  version "5.4.6"
+  resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
+  integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==
+  dependencies:
+    ajv "^6.10.2"
+    lodash "^4.17.14"
+    slice-ansi "^2.1.0"
+    string-width "^3.0.0"
+
+term-size@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69"
+  integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=
+  dependencies:
+    execa "^0.7.0"
+
+text-table@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+  integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
+
+through@^2.3.6:
+  version "2.3.8"
+  resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+  integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
+
+tmp@^0.0.33:
+  version "0.0.33"
+  resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+  integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
+  dependencies:
+    os-tmpdir "~1.0.2"
+
+tslib@^1.9.0:
+  version "1.10.0"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
+  integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
+
+type-check@~0.3.2:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+  integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
+  dependencies:
+    prelude-ls "~1.1.2"
+
+type-detect@^4.0.0, type-detect@^4.0.5:
+  version "4.0.8"
+  resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
+  integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
+
[email protected]:
+  version "1.5.2"
+  resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.5.2.tgz#2fe09f725c543440b3d7dabe8971f2d5caaedc28"
+  integrity sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ==
+  dependencies:
+    registry-auth-token "3.3.2"
+    registry-url "3.1.0"
+
+uri-js@^4.2.2:
+  version "4.2.2"
+  resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
+  integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
+  dependencies:
+    punycode "^2.1.0"
+
+v8-compile-cache@^2.0.3:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e"
+  integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==
+
+vary@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+  integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
+
+which-module@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
+  integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
+
[email protected], which@^1.2.9:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+  integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
+  dependencies:
+    isexe "^2.0.0"
+
[email protected]:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
+  integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
+  dependencies:
+    string-width "^1.0.2 || 2"
+
+widest-line@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc"
+  integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==
+  dependencies:
+    string-width "^2.1.1"
+
+wordwrap@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+  integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
+
+wrap-ansi@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
+  integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=
+  dependencies:
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+
+wrappy@1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+  integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
+
[email protected]:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"
+  integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==
+  dependencies:
+    mkdirp "^0.5.1"
+
+"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
+  integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
+
+yallist@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+  integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
+
[email protected]:
+  version "13.0.0"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.0.0.tgz#3fc44f3e76a8bdb1cc3602e860108602e5ccde8b"
+  integrity sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==
+  dependencies:
+    camelcase "^5.0.0"
+    decamelize "^1.2.0"
+
+yargs-parser@^11.1.1:
+  version "11.1.1"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"
+  integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==
+  dependencies:
+    camelcase "^5.0.0"
+    decamelize "^1.2.0"
+
+yargs-parser@^13.0.0:
+  version "13.1.1"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0"
+  integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==
+  dependencies:
+    camelcase "^5.0.0"
+    decamelize "^1.2.0"
+
[email protected]:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.5.0.tgz#f2bb2a7e83cbc87bb95c8e572828a06c9add6e0d"
+  integrity sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==
+  dependencies:
+    flat "^4.1.0"
+    lodash "^4.17.11"
+    yargs "^12.0.5"
+
[email protected]:
+  version "13.2.2"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.2.tgz#0c101f580ae95cea7f39d927e7770e3fdc97f993"
+  integrity sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==
+  dependencies:
+    cliui "^4.0.0"
+    find-up "^3.0.0"
+    get-caller-file "^2.0.1"
+    os-locale "^3.1.0"
+    require-directory "^2.1.1"
+    require-main-filename "^2.0.0"
+    set-blocking "^2.0.0"
+    string-width "^3.0.0"
+    which-module "^2.0.0"
+    y18n "^4.0.0"
+    yargs-parser "^13.0.0"
+
+yargs@^12.0.5:
+  version "12.0.5"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
+  integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==
+  dependencies:
+    cliui "^4.0.0"
+    decamelize "^1.2.0"
+    find-up "^3.0.0"
+    get-caller-file "^1.0.1"
+    os-locale "^3.0.0"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^2.0.0"
+    which-module "^2.0.0"
+    y18n "^3.2.1 || ^4.0.0"
+    yargs-parser "^11.1.1"

+ 1 - 1
3rdparty/spirv-tools/tools/util/cli_consumer.h

@@ -15,7 +15,7 @@
 #ifndef SOURCE_UTIL_CLI_CONSUMMER_H_
 #define SOURCE_UTIL_CLI_CONSUMMER_H_
 
-#include <include/spirv-tools/libspirv.h>
+#include "include/spirv-tools/libspirv.h"
 
 namespace spvtools {
 namespace utils {

+ 2 - 1
3rdparty/spirv-tools/utils/check_copyright.py

@@ -30,7 +30,8 @@ AUTHORS = ['The Khronos Group Inc.',
            'LunarG Inc.',
            'Google Inc.',
            'Google LLC',
-           'Pierre Moreau']
+           'Pierre Moreau',
+           'Samsung Inc']
 CURRENT_YEAR='2019'
 
 YEARS = '(2014-2016|2015-2016|2016|2016-2017|2017|2018|2019)'

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