mirror of
https://gitee.com/openharmony/third_party_spirv-tools
synced 2024-11-23 07:20:28 +00:00
Merge pull request !24 from openharmony_ci/revert-merge-23-master
This commit is contained in:
commit
86aeb7d7b9
3
.gitignore
vendored
3
.gitignore
vendored
@ -4,7 +4,6 @@
|
|||||||
compile_commands.json
|
compile_commands.json
|
||||||
/build*/
|
/build*/
|
||||||
/buildtools/
|
/buildtools/
|
||||||
/external/abseil_cpp/
|
|
||||||
/external/googletest
|
/external/googletest
|
||||||
/external/SPIRV-Headers
|
/external/SPIRV-Headers
|
||||||
/external/spirv-headers
|
/external/spirv-headers
|
||||||
@ -21,7 +20,7 @@ bazel-bin
|
|||||||
bazel-genfiles
|
bazel-genfiles
|
||||||
bazel-out
|
bazel-out
|
||||||
bazel-spirv-tools
|
bazel-spirv-tools
|
||||||
bazel-SPIRV-Tools
|
bazel-spirv-tools
|
||||||
bazel-testlogs
|
bazel-testlogs
|
||||||
|
|
||||||
# Vim
|
# Vim
|
||||||
|
19
Android.mk
19
Android.mk
@ -71,7 +71,6 @@ SPVTOOLS_SRC_FILES := \
|
|||||||
source/val/validate_primitives.cpp \
|
source/val/validate_primitives.cpp \
|
||||||
source/val/validate_ray_query.cpp \
|
source/val/validate_ray_query.cpp \
|
||||||
source/val/validate_ray_tracing.cpp \
|
source/val/validate_ray_tracing.cpp \
|
||||||
source/val/validate_ray_tracing_reorder.cpp \
|
|
||||||
source/val/validate_scopes.cpp \
|
source/val/validate_scopes.cpp \
|
||||||
source/val/validate_small_type_uses.cpp \
|
source/val/validate_small_type_uses.cpp \
|
||||||
source/val/validate_type.cpp
|
source/val/validate_type.cpp
|
||||||
@ -79,7 +78,6 @@ SPVTOOLS_SRC_FILES := \
|
|||||||
SPVTOOLS_OPT_SRC_FILES := \
|
SPVTOOLS_OPT_SRC_FILES := \
|
||||||
source/opt/aggressive_dead_code_elim_pass.cpp \
|
source/opt/aggressive_dead_code_elim_pass.cpp \
|
||||||
source/opt/amd_ext_to_khr.cpp \
|
source/opt/amd_ext_to_khr.cpp \
|
||||||
source/opt/analyze_live_input_pass.cpp \
|
|
||||||
source/opt/basic_block.cpp \
|
source/opt/basic_block.cpp \
|
||||||
source/opt/block_merge_pass.cpp \
|
source/opt/block_merge_pass.cpp \
|
||||||
source/opt/block_merge_util.cpp \
|
source/opt/block_merge_util.cpp \
|
||||||
@ -111,9 +109,8 @@ SPVTOOLS_OPT_SRC_FILES := \
|
|||||||
source/opt/eliminate_dead_constant_pass.cpp \
|
source/opt/eliminate_dead_constant_pass.cpp \
|
||||||
source/opt/eliminate_dead_functions_pass.cpp \
|
source/opt/eliminate_dead_functions_pass.cpp \
|
||||||
source/opt/eliminate_dead_functions_util.cpp \
|
source/opt/eliminate_dead_functions_util.cpp \
|
||||||
source/opt/eliminate_dead_io_components_pass.cpp \
|
source/opt/eliminate_dead_input_components_pass.cpp \
|
||||||
source/opt/eliminate_dead_members_pass.cpp \
|
source/opt/eliminate_dead_members_pass.cpp \
|
||||||
source/opt/eliminate_dead_output_stores_pass.cpp \
|
|
||||||
source/opt/feature_manager.cpp \
|
source/opt/feature_manager.cpp \
|
||||||
source/opt/fix_func_call_arguments.cpp \
|
source/opt/fix_func_call_arguments.cpp \
|
||||||
source/opt/fix_storage_class.cpp \
|
source/opt/fix_storage_class.cpp \
|
||||||
@ -136,11 +133,9 @@ SPVTOOLS_OPT_SRC_FILES := \
|
|||||||
source/opt/instrument_pass.cpp \
|
source/opt/instrument_pass.cpp \
|
||||||
source/opt/interface_var_sroa.cpp \
|
source/opt/interface_var_sroa.cpp \
|
||||||
source/opt/interp_fixup_pass.cpp \
|
source/opt/interp_fixup_pass.cpp \
|
||||||
source/opt/invocation_interlock_placement_pass.cpp \
|
|
||||||
source/opt/ir_context.cpp \
|
source/opt/ir_context.cpp \
|
||||||
source/opt/ir_loader.cpp \
|
source/opt/ir_loader.cpp \
|
||||||
source/opt/licm_pass.cpp \
|
source/opt/licm_pass.cpp \
|
||||||
source/opt/liveness.cpp \
|
|
||||||
source/opt/local_access_chain_convert_pass.cpp \
|
source/opt/local_access_chain_convert_pass.cpp \
|
||||||
source/opt/local_redundancy_elimination.cpp \
|
source/opt/local_redundancy_elimination.cpp \
|
||||||
source/opt/local_single_block_elim_pass.cpp \
|
source/opt/local_single_block_elim_pass.cpp \
|
||||||
@ -183,8 +178,6 @@ SPVTOOLS_OPT_SRC_FILES := \
|
|||||||
source/opt/strip_debug_info_pass.cpp \
|
source/opt/strip_debug_info_pass.cpp \
|
||||||
source/opt/strip_nonsemantic_info_pass.cpp \
|
source/opt/strip_nonsemantic_info_pass.cpp \
|
||||||
source/opt/struct_cfg_analysis.cpp \
|
source/opt/struct_cfg_analysis.cpp \
|
||||||
source/opt/switch_descriptorset_pass.cpp \
|
|
||||||
source/opt/trim_capabilities_pass.cpp \
|
|
||||||
source/opt/type_manager.cpp \
|
source/opt/type_manager.cpp \
|
||||||
source/opt/types.cpp \
|
source/opt/types.cpp \
|
||||||
source/opt/unify_const_pass.cpp \
|
source/opt/unify_const_pass.cpp \
|
||||||
@ -224,8 +217,7 @@ $(1)/opencl.std.insts.inc \
|
|||||||
--core-insts-output=$(1)/core.insts-unified1.inc \
|
--core-insts-output=$(1)/core.insts-unified1.inc \
|
||||||
--glsl-insts-output=$(1)/glsl.std.450.insts.inc \
|
--glsl-insts-output=$(1)/glsl.std.450.insts.inc \
|
||||||
--opencl-insts-output=$(1)/opencl.std.insts.inc \
|
--opencl-insts-output=$(1)/opencl.std.insts.inc \
|
||||||
--operand-kinds-output=$(1)/operand.kinds-unified1.inc \
|
--operand-kinds-output=$(1)/operand.kinds-unified1.inc
|
||||||
--output-language=c++
|
|
||||||
@echo "[$(TARGET_ARCH_ABI)] Grammar (from unified1) : instructions & operands <= grammar JSON files"
|
@echo "[$(TARGET_ARCH_ABI)] Grammar (from unified1) : instructions & operands <= grammar JSON files"
|
||||||
$(LOCAL_PATH)/source/opcode.cpp: $(1)/core.insts-unified1.inc
|
$(LOCAL_PATH)/source/opcode.cpp: $(1)/core.insts-unified1.inc
|
||||||
$(LOCAL_PATH)/source/operand.cpp: $(1)/operand.kinds-unified1.inc
|
$(LOCAL_PATH)/source/operand.cpp: $(1)/operand.kinds-unified1.inc
|
||||||
@ -299,8 +291,7 @@ $(1)/extension_enum.inc $(1)/enum_string_mapping.inc: \
|
|||||||
--extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
|
--extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
|
||||||
--extinst-cldebuginfo100-grammar=$(SPV_CLDEBUGINFO100_GRAMMAR) \
|
--extinst-cldebuginfo100-grammar=$(SPV_CLDEBUGINFO100_GRAMMAR) \
|
||||||
--extension-enum-output=$(1)/extension_enum.inc \
|
--extension-enum-output=$(1)/extension_enum.inc \
|
||||||
--enum-string-mapping-output=$(1)/enum_string_mapping.inc \
|
--enum-string-mapping-output=$(1)/enum_string_mapping.inc
|
||||||
--output-language=c++
|
|
||||||
@echo "[$(TARGET_ARCH_ABI)] Generate enum<->string mapping <= grammar JSON files"
|
@echo "[$(TARGET_ARCH_ABI)] Generate enum<->string mapping <= grammar JSON files"
|
||||||
# Generated header extension_enum.inc is transitively included by table.h, which is
|
# Generated header extension_enum.inc is transitively included by table.h, which is
|
||||||
# used pervasively. Capture the pervasive dependency.
|
# used pervasively. Capture the pervasive dependency.
|
||||||
@ -343,7 +334,7 @@ LOCAL_C_INCLUDES := \
|
|||||||
$(SPVTOOLS_OUT_PATH)
|
$(SPVTOOLS_OUT_PATH)
|
||||||
LOCAL_EXPORT_C_INCLUDES := \
|
LOCAL_EXPORT_C_INCLUDES := \
|
||||||
$(LOCAL_PATH)/include
|
$(LOCAL_PATH)/include
|
||||||
LOCAL_CXXFLAGS:=-std=c++17 -fno-exceptions -fno-rtti -Werror
|
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -Werror
|
||||||
LOCAL_SRC_FILES:= $(SPVTOOLS_SRC_FILES)
|
LOCAL_SRC_FILES:= $(SPVTOOLS_SRC_FILES)
|
||||||
include $(BUILD_STATIC_LIBRARY)
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
@ -354,7 +345,7 @@ LOCAL_C_INCLUDES := \
|
|||||||
$(LOCAL_PATH)/source \
|
$(LOCAL_PATH)/source \
|
||||||
$(SPVHEADERS_LOCAL_PATH)/include \
|
$(SPVHEADERS_LOCAL_PATH)/include \
|
||||||
$(SPVTOOLS_OUT_PATH)
|
$(SPVTOOLS_OUT_PATH)
|
||||||
LOCAL_CXXFLAGS:=-std=c++17 -fno-exceptions -fno-rtti -Werror
|
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -Werror
|
||||||
LOCAL_STATIC_LIBRARIES:=SPIRV-Tools
|
LOCAL_STATIC_LIBRARIES:=SPIRV-Tools
|
||||||
LOCAL_SRC_FILES:= $(SPVTOOLS_OPT_SRC_FILES)
|
LOCAL_SRC_FILES:= $(SPVTOOLS_OPT_SRC_FILES)
|
||||||
include $(BUILD_STATIC_LIBRARY)
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
662
BUILD.bazel
662
BUILD.bazel
@ -1,24 +1,27 @@
|
|||||||
load(
|
load(
|
||||||
":build_defs.bzl",
|
":build_defs.bzl",
|
||||||
"CLDEBUGINFO100_GRAMMAR_JSON_FILE",
|
|
||||||
"COMMON_COPTS",
|
"COMMON_COPTS",
|
||||||
"DEBUGINFO_GRAMMAR_JSON_FILE",
|
"DEBUGINFO_GRAMMAR_JSON_FILE",
|
||||||
|
"CLDEBUGINFO100_GRAMMAR_JSON_FILE",
|
||||||
"SHDEBUGINFO100_GRAMMAR_JSON_FILE",
|
"SHDEBUGINFO100_GRAMMAR_JSON_FILE",
|
||||||
"TEST_COPTS",
|
"TEST_COPTS",
|
||||||
|
"base_test",
|
||||||
"generate_core_tables",
|
"generate_core_tables",
|
||||||
"generate_enum_string_mapping",
|
"generate_enum_string_mapping",
|
||||||
"generate_extinst_lang_headers",
|
"generate_extinst_lang_headers",
|
||||||
"generate_glsl_tables",
|
"generate_glsl_tables",
|
||||||
"generate_opencl_tables",
|
"generate_opencl_tables",
|
||||||
"generate_vendor_tables",
|
"generate_vendor_tables",
|
||||||
"incompatible_with",
|
"link_test",
|
||||||
|
"lint_test",
|
||||||
|
"opt_test",
|
||||||
|
"reduce_test",
|
||||||
|
"util_test",
|
||||||
|
"val_test",
|
||||||
)
|
)
|
||||||
|
|
||||||
package(
|
package(
|
||||||
default_visibility = ["//visibility:private"],
|
default_visibility = ["//visibility:private"],
|
||||||
features = [
|
|
||||||
"layering_check",
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
licenses(["notice"])
|
licenses(["notice"])
|
||||||
@ -38,50 +41,35 @@ py_binary(
|
|||||||
srcs = ["utils/generate_language_headers.py"],
|
srcs = ["utils/generate_language_headers.py"],
|
||||||
)
|
)
|
||||||
|
|
||||||
generate_core_tables(version = "unified1")
|
generate_core_tables("unified1")
|
||||||
|
|
||||||
generate_enum_string_mapping(version = "unified1")
|
generate_enum_string_mapping("unified1")
|
||||||
|
|
||||||
generate_opencl_tables(version = "unified1")
|
generate_opencl_tables("unified1")
|
||||||
|
|
||||||
generate_glsl_tables(version = "unified1")
|
generate_glsl_tables("unified1")
|
||||||
|
|
||||||
generate_vendor_tables(extension = "spv-amd-shader-explicit-vertex-parameter")
|
generate_vendor_tables("spv-amd-shader-explicit-vertex-parameter")
|
||||||
|
|
||||||
generate_vendor_tables(extension = "spv-amd-shader-trinary-minmax")
|
generate_vendor_tables("spv-amd-shader-trinary-minmax")
|
||||||
|
|
||||||
generate_vendor_tables(extension = "spv-amd-gcn-shader")
|
generate_vendor_tables("spv-amd-gcn-shader")
|
||||||
|
|
||||||
generate_vendor_tables(extension = "spv-amd-shader-ballot")
|
generate_vendor_tables("spv-amd-shader-ballot")
|
||||||
|
|
||||||
generate_vendor_tables(extension = "debuginfo")
|
generate_vendor_tables("debuginfo")
|
||||||
|
|
||||||
generate_vendor_tables(extension = "nonsemantic.clspvreflection")
|
generate_vendor_tables("opencl.debuginfo.100", "CLDEBUG100_")
|
||||||
|
|
||||||
generate_vendor_tables(
|
generate_vendor_tables("nonsemantic.shader.debuginfo.100", "SHDEBUG100_")
|
||||||
extension = "opencl.debuginfo.100",
|
|
||||||
operand_kind_prefix = "CLDEBUG100_",
|
|
||||||
)
|
|
||||||
|
|
||||||
generate_vendor_tables(
|
generate_vendor_tables("nonsemantic.clspvreflection")
|
||||||
extension = "nonsemantic.shader.debuginfo.100",
|
|
||||||
operand_kind_prefix = "SHDEBUG100_",
|
|
||||||
)
|
|
||||||
|
|
||||||
generate_extinst_lang_headers(
|
generate_extinst_lang_headers("DebugInfo", DEBUGINFO_GRAMMAR_JSON_FILE)
|
||||||
name = "DebugInfo",
|
|
||||||
grammar = DEBUGINFO_GRAMMAR_JSON_FILE,
|
|
||||||
)
|
|
||||||
|
|
||||||
generate_extinst_lang_headers(
|
generate_extinst_lang_headers("OpenCLDebugInfo100", CLDEBUGINFO100_GRAMMAR_JSON_FILE)
|
||||||
name = "OpenCLDebugInfo100",
|
|
||||||
grammar = CLDEBUGINFO100_GRAMMAR_JSON_FILE,
|
|
||||||
)
|
|
||||||
|
|
||||||
generate_extinst_lang_headers(
|
generate_extinst_lang_headers("NonSemanticShaderDebugInfo100", SHDEBUGINFO100_GRAMMAR_JSON_FILE)
|
||||||
name = "NonSemanticShaderDebugInfo100",
|
|
||||||
grammar = SHDEBUGINFO100_GRAMMAR_JSON_FILE,
|
|
||||||
)
|
|
||||||
|
|
||||||
py_binary(
|
py_binary(
|
||||||
name = "generate_registry_tables",
|
name = "generate_registry_tables",
|
||||||
@ -89,12 +77,12 @@ py_binary(
|
|||||||
)
|
)
|
||||||
|
|
||||||
genrule(
|
genrule(
|
||||||
name = "generators_inc",
|
name = "gen_registry_tables",
|
||||||
srcs = ["@spirv_headers//:spirv_xml_registry"],
|
srcs = ["@spirv_headers//:spirv_xml_registry"],
|
||||||
outs = ["generators.inc"],
|
outs = ["generators.inc"],
|
||||||
cmd = "$(location :generate_registry_tables) --xml=$(location @spirv_headers//:spirv_xml_registry) --generator-output=$(location generators.inc)",
|
cmd = "$(location generate_registry_tables) --xml=$(location @spirv_headers//:spirv_xml_registry) --generator-output=$(location generators.inc)",
|
||||||
cmd_bat = "$(location :generate_registry_tables) --xml=$(location @spirv_headers//:spirv_xml_registry) --generator-output=$(location generators.inc)",
|
cmd_bat = "$(location //:generate_registry_tables) --xml=$(location @spirv_headers//:spirv_xml_registry) --generator-output=$(location generators.inc)",
|
||||||
tools = [":generate_registry_tables"],
|
exec_tools = [":generate_registry_tables"],
|
||||||
)
|
)
|
||||||
|
|
||||||
py_binary(
|
py_binary(
|
||||||
@ -103,103 +91,120 @@ py_binary(
|
|||||||
)
|
)
|
||||||
|
|
||||||
genrule(
|
genrule(
|
||||||
name = "build_version_inc",
|
name = "gen_build_version",
|
||||||
srcs = ["CHANGES"],
|
srcs = ["CHANGES"],
|
||||||
outs = ["build-version.inc"],
|
outs = ["build-version.inc"],
|
||||||
cmd = "SOURCE_DATE_EPOCH=0 $(location :update_build_version) $(location CHANGES) $(location build-version.inc)",
|
cmd = "SOURCE_DATE_EPOCH=0 $(location update_build_version) $(location CHANGES) $(location build-version.inc)",
|
||||||
cmd_bat = "set SOURCE_DATE_EPOCH=0 && $(location :update_build_version) $(location CHANGES) $(location build-version.inc)",
|
cmd_bat = "set SOURCE_DATE_EPOCH=0 && $(location //:update_build_version) $(location CHANGES) $(location build-version.inc)",
|
||||||
local = True,
|
exec_tools = [":update_build_version"],
|
||||||
tools = [":update_build_version"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Libraries
|
# Libraries
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "spirv_tools",
|
name = "generated_headers",
|
||||||
hdrs = [
|
hdrs = [
|
||||||
"include/spirv-tools/libspirv.h",
|
":gen_build_version",
|
||||||
"include/spirv-tools/libspirv.hpp",
|
|
||||||
],
|
|
||||||
copts = COMMON_COPTS,
|
|
||||||
includes = ["include"],
|
|
||||||
linkstatic = 1,
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
":spirv_tools_internal",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "spirv_tools_internal",
|
|
||||||
srcs = glob([
|
|
||||||
"source/*.cpp",
|
|
||||||
"source/util/*.cpp",
|
|
||||||
"source/val/*.cpp",
|
|
||||||
]) + [
|
|
||||||
":build_version_inc",
|
|
||||||
":gen_core_tables_unified1",
|
":gen_core_tables_unified1",
|
||||||
":gen_enum_string_mapping",
|
":gen_enum_string_mapping",
|
||||||
":gen_extinst_lang_headers_DebugInfo",
|
":gen_extinst_lang_headers_DebugInfo",
|
||||||
":gen_extinst_lang_headers_NonSemanticShaderDebugInfo100",
|
|
||||||
":gen_extinst_lang_headers_OpenCLDebugInfo100",
|
":gen_extinst_lang_headers_OpenCLDebugInfo100",
|
||||||
|
":gen_extinst_lang_headers_NonSemanticShaderDebugInfo100",
|
||||||
":gen_glsl_tables_unified1",
|
":gen_glsl_tables_unified1",
|
||||||
":gen_opencl_tables_unified1",
|
":gen_opencl_tables_unified1",
|
||||||
|
":gen_registry_tables",
|
||||||
":gen_vendor_tables_debuginfo",
|
":gen_vendor_tables_debuginfo",
|
||||||
":gen_vendor_tables_nonsemantic_clspvreflection",
|
":gen_vendor_tables_nonsemantic_clspvreflection",
|
||||||
":gen_vendor_tables_nonsemantic_shader_debuginfo_100",
|
|
||||||
":gen_vendor_tables_opencl_debuginfo_100",
|
":gen_vendor_tables_opencl_debuginfo_100",
|
||||||
|
":gen_vendor_tables_nonsemantic_shader_debuginfo_100",
|
||||||
":gen_vendor_tables_spv_amd_gcn_shader",
|
":gen_vendor_tables_spv_amd_gcn_shader",
|
||||||
":gen_vendor_tables_spv_amd_shader_ballot",
|
":gen_vendor_tables_spv_amd_shader_ballot",
|
||||||
":gen_vendor_tables_spv_amd_shader_explicit_vertex_parameter",
|
":gen_vendor_tables_spv_amd_shader_explicit_vertex_parameter",
|
||||||
":gen_vendor_tables_spv_amd_shader_trinary_minmax",
|
":gen_vendor_tables_spv_amd_shader_trinary_minmax",
|
||||||
":generators_inc",
|
|
||||||
],
|
],
|
||||||
hdrs = [
|
copts = COMMON_COPTS,
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "spirv_tools_headers",
|
||||||
|
hdrs = glob([
|
||||||
"include/spirv-tools/libspirv.h",
|
"include/spirv-tools/libspirv.h",
|
||||||
"include/spirv-tools/libspirv.hpp",
|
"include/spirv-tools/libspirv.hpp",
|
||||||
":gen_extinst_lang_headers_DebugInfo",
|
|
||||||
":gen_extinst_lang_headers_NonSemanticShaderDebugInfo100",
|
|
||||||
":gen_extinst_lang_headers_OpenCLDebugInfo100",
|
|
||||||
] + glob([
|
|
||||||
"source/*.h",
|
"source/*.h",
|
||||||
"source/util/*.h",
|
"source/util/*.h",
|
||||||
"source/val/*.h",
|
"source/val/*.h",
|
||||||
]),
|
]),
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
includes = ["include"],
|
includes = ["source"],
|
||||||
deps = [
|
deps = [
|
||||||
"@spirv_headers//:spirv_common_headers",
|
"@spirv_headers//:spirv_c_headers",
|
||||||
"@spirv_headers//:spirv_cpp11_headers",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "spirv_tools",
|
||||||
|
srcs = glob([
|
||||||
|
"source/*.cpp",
|
||||||
|
"source/util/*.cpp",
|
||||||
|
"source/val/*.cpp",
|
||||||
|
]),
|
||||||
|
hdrs = [
|
||||||
|
"include/spirv-tools/libspirv.h",
|
||||||
|
"include/spirv-tools/libspirv.hpp",
|
||||||
|
],
|
||||||
|
copts = COMMON_COPTS + select({
|
||||||
|
"@bazel_tools//src/conditions:windows": [""],
|
||||||
|
"//conditions:default": ["-Wno-implicit-fallthrough"],
|
||||||
|
}),
|
||||||
|
includes = ["include"],
|
||||||
|
linkstatic = 1,
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
":generated_headers",
|
||||||
|
":spirv_tools_headers",
|
||||||
|
"@spirv_headers//:spirv_c_headers",
|
||||||
|
"@spirv_headers//:spirv_common_headers",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "spirv_tools_comp",
|
||||||
|
srcs = glob([
|
||||||
|
"source/comp/*.cpp",
|
||||||
|
"source/comp/*.h",
|
||||||
|
]),
|
||||||
|
copts = COMMON_COPTS,
|
||||||
|
linkstatic = 1,
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
":generated_headers",
|
||||||
|
":spirv_tools",
|
||||||
|
":spirv_tools_headers",
|
||||||
|
"@spirv_headers//:spirv_common_headers",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "spirv_tools_opt_headers",
|
||||||
|
hdrs = glob(["source/opt/*.h"]),
|
||||||
|
copts = COMMON_COPTS,
|
||||||
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "spirv_tools_opt",
|
name = "spirv_tools_opt",
|
||||||
|
srcs = glob(["source/opt/*.cpp"]),
|
||||||
hdrs = [
|
hdrs = [
|
||||||
"include/spirv-tools/instrument.hpp",
|
"include/spirv-tools/instrument.hpp",
|
||||||
"include/spirv-tools/optimizer.hpp",
|
"include/spirv-tools/optimizer.hpp",
|
||||||
],
|
],
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
|
includes = ["include"],
|
||||||
linkstatic = 1,
|
linkstatic = 1,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools",
|
":spirv_tools",
|
||||||
":spirv_tools_opt_internal",
|
":spirv_tools_headers",
|
||||||
],
|
":spirv_tools_opt_headers",
|
||||||
)
|
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "spirv_tools_opt_internal",
|
|
||||||
srcs = glob(["source/opt/*.cpp"]) + [
|
|
||||||
":gen_vendor_tables_spv_amd_shader_ballot",
|
|
||||||
],
|
|
||||||
hdrs = glob(["source/opt/*.h"]) + [
|
|
||||||
"include/spirv-tools/instrument.hpp",
|
|
||||||
"include/spirv-tools/optimizer.hpp",
|
|
||||||
],
|
|
||||||
copts = COMMON_COPTS,
|
|
||||||
deps = [
|
|
||||||
":spirv_tools_internal",
|
|
||||||
"@spirv_headers//:spirv_common_headers",
|
"@spirv_headers//:spirv_common_headers",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -209,9 +214,11 @@ cc_library(
|
|||||||
srcs = glob(["source/reduce/*.cpp"]),
|
srcs = glob(["source/reduce/*.cpp"]),
|
||||||
hdrs = glob(["source/reduce/*.h"]),
|
hdrs = glob(["source/reduce/*.h"]),
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
|
linkstatic = 1,
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools_internal",
|
":spirv_tools",
|
||||||
":spirv_tools_opt_internal",
|
":spirv_tools_opt",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -223,38 +230,21 @@ cc_library(
|
|||||||
linkstatic = 1,
|
linkstatic = 1,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools_internal",
|
":spirv_tools",
|
||||||
":spirv_tools_opt_internal",
|
":spirv_tools_opt",
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "spirv_tools_lint_internal",
|
|
||||||
srcs = glob([
|
|
||||||
"source/lint/*.cpp",
|
|
||||||
"source/lint/*.h",
|
|
||||||
]),
|
|
||||||
hdrs = ["include/spirv-tools/linter.hpp"] + glob([
|
|
||||||
"source/lint/*.h",
|
|
||||||
]),
|
|
||||||
copts = COMMON_COPTS,
|
|
||||||
includes = ["include"],
|
|
||||||
deps = [
|
|
||||||
":spirv_tools_internal",
|
|
||||||
":spirv_tools_opt_internal",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "spirv_tools_lint",
|
name = "spirv_tools_lint",
|
||||||
|
srcs = glob(["source/lint/*.cpp", "source/lint/*.h"]),
|
||||||
hdrs = ["include/spirv-tools/linter.hpp"],
|
hdrs = ["include/spirv-tools/linter.hpp"],
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
includes = ["include"],
|
|
||||||
linkstatic = 1,
|
linkstatic = 1,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools",
|
":spirv_tools",
|
||||||
":spirv_tools_lint_internal",
|
":spirv_tools_opt",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -263,28 +253,23 @@ cc_library(
|
|||||||
srcs = glob(["tools/util/*.cpp"]),
|
srcs = glob(["tools/util/*.cpp"]),
|
||||||
hdrs = glob(["tools/util/*.h"]),
|
hdrs = glob(["tools/util/*.h"]),
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
|
linkstatic = 1,
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
deps = [":spirv_tools"],
|
deps = [":spirv_tools"],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "tools_io",
|
|
||||||
hdrs = ["tools/io.h"],
|
|
||||||
copts = COMMON_COPTS,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Tools
|
# Tools
|
||||||
|
|
||||||
cc_binary(
|
cc_binary(
|
||||||
name = "spirv-as",
|
name = "spirv-as",
|
||||||
srcs = [
|
srcs = [
|
||||||
"tools/as/as.cpp",
|
"tools/as/as.cpp",
|
||||||
|
"tools/io.h",
|
||||||
],
|
],
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools_internal",
|
":spirv_tools",
|
||||||
":tools_io",
|
|
||||||
":tools_util",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -292,44 +277,25 @@ cc_binary(
|
|||||||
name = "spirv-dis",
|
name = "spirv-dis",
|
||||||
srcs = [
|
srcs = [
|
||||||
"tools/dis/dis.cpp",
|
"tools/dis/dis.cpp",
|
||||||
|
"tools/io.h",
|
||||||
],
|
],
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools",
|
":spirv_tools",
|
||||||
":tools_io",
|
|
||||||
":tools_util",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_binary(
|
|
||||||
name = "spirv-objdump",
|
|
||||||
srcs = [
|
|
||||||
"tools/objdump/extract_source.cpp",
|
|
||||||
"tools/objdump/extract_source.h",
|
|
||||||
"tools/objdump/objdump.cpp",
|
|
||||||
],
|
|
||||||
copts = COMMON_COPTS,
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
":spirv_tools_internal",
|
|
||||||
":spirv_tools_opt_internal",
|
|
||||||
":tools_io",
|
|
||||||
":tools_util",
|
|
||||||
"@spirv_headers//:spirv_cpp_headers",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_binary(
|
cc_binary(
|
||||||
name = "spirv-val",
|
name = "spirv-val",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"tools/io.h",
|
||||||
"tools/val/val.cpp",
|
"tools/val/val.cpp",
|
||||||
],
|
],
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools_internal",
|
":spirv_tools",
|
||||||
":tools_io",
|
|
||||||
":tools_util",
|
":tools_util",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -337,14 +303,14 @@ cc_binary(
|
|||||||
cc_binary(
|
cc_binary(
|
||||||
name = "spirv-opt",
|
name = "spirv-opt",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"tools/io.h",
|
||||||
"tools/opt/opt.cpp",
|
"tools/opt/opt.cpp",
|
||||||
],
|
],
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools_internal",
|
":spirv_tools",
|
||||||
":spirv_tools_opt_internal",
|
":spirv_tools_opt",
|
||||||
":tools_io",
|
|
||||||
":tools_util",
|
":tools_util",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -352,15 +318,15 @@ cc_binary(
|
|||||||
cc_binary(
|
cc_binary(
|
||||||
name = "spirv-reduce",
|
name = "spirv-reduce",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"tools/io.h",
|
||||||
"tools/reduce/reduce.cpp",
|
"tools/reduce/reduce.cpp",
|
||||||
],
|
],
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools_internal",
|
":spirv_tools",
|
||||||
":spirv_tools_opt_internal",
|
":spirv_tools_opt",
|
||||||
":spirv_tools_reduce",
|
":spirv_tools_reduce",
|
||||||
":tools_io",
|
|
||||||
":tools_util",
|
":tools_util",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -368,29 +334,28 @@ cc_binary(
|
|||||||
cc_binary(
|
cc_binary(
|
||||||
name = "spirv-link",
|
name = "spirv-link",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"tools/io.h",
|
||||||
"tools/link/linker.cpp",
|
"tools/link/linker.cpp",
|
||||||
],
|
],
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools_internal",
|
":spirv_tools",
|
||||||
":spirv_tools_link",
|
":spirv_tools_link",
|
||||||
":tools_io",
|
|
||||||
":tools_util",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_binary(
|
cc_binary(
|
||||||
name = "spirv-lint",
|
name = "spirv-lint",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"tools/io.h",
|
||||||
"tools/lint/lint.cpp",
|
"tools/lint/lint.cpp",
|
||||||
],
|
],
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
":spirv_tools",
|
||||||
":spirv_tools_lint",
|
":spirv_tools_lint",
|
||||||
":spirv_tools_opt_internal",
|
|
||||||
":tools_io",
|
|
||||||
":tools_util",
|
":tools_util",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -401,143 +366,50 @@ cc_binary(
|
|||||||
"tools/cfg/bin_to_dot.cpp",
|
"tools/cfg/bin_to_dot.cpp",
|
||||||
"tools/cfg/bin_to_dot.h",
|
"tools/cfg/bin_to_dot.h",
|
||||||
"tools/cfg/cfg.cpp",
|
"tools/cfg/cfg.cpp",
|
||||||
|
"tools/io.h",
|
||||||
],
|
],
|
||||||
copts = COMMON_COPTS,
|
copts = COMMON_COPTS,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [":spirv_tools"],
|
||||||
":spirv_tools_internal",
|
|
||||||
":tools_io",
|
|
||||||
":tools_util",
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Unit tests
|
# Unit tests
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "test_lib",
|
name = "test_common",
|
||||||
testonly = 1,
|
testonly = 1,
|
||||||
srcs = [
|
srcs = [
|
||||||
"test/unit_spirv.cpp",
|
|
||||||
],
|
|
||||||
hdrs = [
|
|
||||||
"test/test_fixture.h",
|
"test/test_fixture.h",
|
||||||
|
"test/unit_spirv.cpp",
|
||||||
"test/unit_spirv.h",
|
"test/unit_spirv.h",
|
||||||
],
|
],
|
||||||
|
compatible_with = [],
|
||||||
copts = TEST_COPTS,
|
copts = TEST_COPTS,
|
||||||
deps = [
|
includes = ["test"],
|
||||||
":spirv_tools_internal",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
# PCH (precompiled header) tests only work when using CMake and MSVC on Windows,
|
|
||||||
# so they will be skipped in the Bazel builds.
|
|
||||||
|
|
||||||
[cc_test(
|
|
||||||
name = "base_{testcase}_test".format(testcase = f[len("test/"):-len("_test.cpp")]),
|
|
||||||
size = "small",
|
|
||||||
srcs = [f],
|
|
||||||
copts = TEST_COPTS + ["-DTESTING"],
|
|
||||||
linkstatic = 1,
|
|
||||||
target_compatible_with = {
|
|
||||||
"test/timer_test.cpp": incompatible_with(["@bazel_tools//src/conditions:windows"]),
|
|
||||||
}.get(f, []),
|
|
||||||
deps = [
|
|
||||||
"tools_util",
|
|
||||||
":spirv_tools_internal",
|
|
||||||
":test_lib",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
|
||||||
) for f in glob(
|
|
||||||
[
|
|
||||||
"test/*_test.cpp",
|
|
||||||
"test/tools/*_test.cpp",
|
|
||||||
],
|
|
||||||
exclude = [
|
|
||||||
"test/cpp_interface_test.cpp",
|
|
||||||
"test/pch_test.cpp",
|
|
||||||
],
|
|
||||||
)]
|
|
||||||
|
|
||||||
cc_test(
|
|
||||||
name = "base_cpp_interface_test",
|
|
||||||
size = "small",
|
|
||||||
srcs = ["test/cpp_interface_test.cpp"],
|
|
||||||
linkstatic = 1,
|
|
||||||
deps = [
|
|
||||||
":spirv_tools_opt_internal",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
"@spirv_headers//:spirv_cpp11_headers",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_test(
|
|
||||||
name = "base_ilist_test",
|
|
||||||
size = "small",
|
|
||||||
srcs = ["test/util/ilist_test.cpp"],
|
|
||||||
copts = TEST_COPTS,
|
|
||||||
linkstatic = 1,
|
|
||||||
deps = [
|
|
||||||
":spirv_tools_internal",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "link_test_lib",
|
|
||||||
testonly = 1,
|
|
||||||
hdrs = ["test/link/linker_fixture.h"],
|
|
||||||
copts = TEST_COPTS,
|
|
||||||
deps = [
|
|
||||||
":spirv_tools_internal",
|
|
||||||
":spirv_tools_link",
|
|
||||||
":test_lib",
|
|
||||||
"@com_google_effcee//:effcee",
|
|
||||||
"@com_googlesource_code_re2//:re2",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
[cc_test(
|
|
||||||
name = "link_{testcase}_test".format(testcase = f[len("test/link/"):-len("_test.cpp")]),
|
|
||||||
size = "small",
|
|
||||||
srcs = [f],
|
|
||||||
copts = TEST_COPTS,
|
|
||||||
linkstatic = 1,
|
|
||||||
deps = [
|
|
||||||
":link_test_lib",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
|
||||||
) for f in glob(
|
|
||||||
["test/link/*_test.cpp"],
|
|
||||||
)]
|
|
||||||
|
|
||||||
[cc_test(
|
|
||||||
name = "lint_{testcase}_test".format(testcase = f[len("test/lint/"):-len("_test.cpp")]),
|
|
||||||
size = "small",
|
|
||||||
srcs = [f],
|
|
||||||
copts = TEST_COPTS,
|
|
||||||
linkstatic = 1,
|
linkstatic = 1,
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools",
|
":spirv_tools",
|
||||||
":spirv_tools_lint_internal",
|
|
||||||
":spirv_tools_opt_internal",
|
|
||||||
"@com_google_googletest//:gtest",
|
"@com_google_googletest//:gtest",
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
],
|
||||||
) for f in glob(
|
)
|
||||||
["test/lint/*_test.cpp"],
|
|
||||||
)]
|
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "opt_test_lib",
|
name = "link_test_common",
|
||||||
testonly = 1,
|
testonly = 1,
|
||||||
srcs = [
|
srcs = ["test/link/linker_fixture.h"],
|
||||||
"test/opt/pass_utils.cpp",
|
compatible_with = [],
|
||||||
|
copts = TEST_COPTS,
|
||||||
|
linkstatic = 1,
|
||||||
|
deps = [
|
||||||
|
":spirv_tools_link",
|
||||||
|
":test_common",
|
||||||
],
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "opt_test_common",
|
||||||
|
testonly = 1,
|
||||||
|
srcs = ["test/opt/pass_utils.cpp"],
|
||||||
hdrs = [
|
hdrs = [
|
||||||
"test/opt/assembly_builder.h",
|
"test/opt/assembly_builder.h",
|
||||||
"test/opt/function_utils.h",
|
"test/opt/function_utils.h",
|
||||||
@ -545,181 +417,143 @@ cc_library(
|
|||||||
"test/opt/pass_fixture.h",
|
"test/opt/pass_fixture.h",
|
||||||
"test/opt/pass_utils.h",
|
"test/opt/pass_utils.h",
|
||||||
],
|
],
|
||||||
|
compatible_with = [],
|
||||||
copts = TEST_COPTS,
|
copts = TEST_COPTS,
|
||||||
|
linkstatic = 1,
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools_internal",
|
":spirv_tools_opt",
|
||||||
":spirv_tools_opt_internal",
|
":test_common",
|
||||||
"@com_google_effcee//:effcee",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
[cc_test(
|
|
||||||
name = "opt_{testcase}_test".format(testcase = f[len("test/opt/"):-len("_test.cpp")]),
|
|
||||||
size = "small",
|
|
||||||
srcs = [f],
|
|
||||||
copts = TEST_COPTS,
|
|
||||||
linkstatic = 1,
|
|
||||||
deps = [
|
|
||||||
":opt_test_lib",
|
|
||||||
":spirv_tools_internal",
|
|
||||||
":spirv_tools_opt_internal",
|
|
||||||
":test_lib",
|
|
||||||
"@com_google_effcee//:effcee",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
|
||||||
) for f in glob(["test/opt/*_test.cpp"])]
|
|
||||||
|
|
||||||
[cc_test(
|
|
||||||
name = "opt_dom_tree_{testcase}_test".format(testcase = f[len("test/opt/dominator_tree/"):-len(".cpp")]),
|
|
||||||
size = "small",
|
|
||||||
srcs = [f],
|
|
||||||
copts = TEST_COPTS,
|
|
||||||
linkstatic = 1,
|
|
||||||
deps = [
|
|
||||||
":opt_test_lib",
|
|
||||||
":spirv_tools_opt_internal",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
|
||||||
) for f in glob(
|
|
||||||
["test/opt/dominator_tree/*.cpp"],
|
|
||||||
exclude = ["test/opt/dominator_tree/pch_test_opt_dom.cpp"],
|
|
||||||
)]
|
|
||||||
|
|
||||||
[cc_test(
|
|
||||||
name = "opt_loop_{testcase}_test".format(testcase = f[len("test/opt/loop_optimizations/"):-len(".cpp")]),
|
|
||||||
size = "small",
|
|
||||||
srcs = [f],
|
|
||||||
copts = TEST_COPTS,
|
|
||||||
linkstatic = 1,
|
|
||||||
deps = [
|
|
||||||
":opt_test_lib",
|
|
||||||
":spirv_tools",
|
|
||||||
":spirv_tools_opt_internal",
|
|
||||||
"@com_google_effcee//:effcee",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
|
||||||
) for f in glob(
|
|
||||||
["test/opt/loop_optimizations/*.cpp"],
|
|
||||||
exclude = ["test/opt/loop_optimizations/pch_test_opt_loop.cpp"],
|
|
||||||
)]
|
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "reduce_test_lib",
|
name = "reduce_test_common",
|
||||||
testonly = 1,
|
testonly = 1,
|
||||||
srcs = [
|
srcs = [
|
||||||
"test/reduce/reduce_test_util.cpp",
|
"test/reduce/reduce_test_util.cpp",
|
||||||
|
"tools/io.h",
|
||||||
],
|
],
|
||||||
hdrs = ["test/reduce/reduce_test_util.h"],
|
hdrs = ["test/reduce/reduce_test_util.h"],
|
||||||
|
compatible_with = [],
|
||||||
copts = TEST_COPTS,
|
copts = TEST_COPTS,
|
||||||
|
linkstatic = 1,
|
||||||
deps = [
|
deps = [
|
||||||
":spirv_tools",
|
|
||||||
":spirv_tools_opt_internal",
|
|
||||||
":spirv_tools_reduce",
|
":spirv_tools_reduce",
|
||||||
":test_lib",
|
":test_common",
|
||||||
":tools_io",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
[cc_test(
|
|
||||||
name = "reduce_{testcase}_test".format(testcase = f[len("test/reduce/"):-len("_test.cpp")]),
|
|
||||||
size = "small",
|
|
||||||
srcs = [f],
|
|
||||||
copts = TEST_COPTS,
|
|
||||||
linkstatic = 1,
|
|
||||||
deps = [
|
|
||||||
":reduce_test_lib",
|
|
||||||
":spirv_tools_internal",
|
|
||||||
":spirv_tools_opt_internal",
|
|
||||||
":spirv_tools_reduce",
|
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
|
||||||
) for f in glob(["test/reduce/*_test.cpp"])]
|
|
||||||
|
|
||||||
[cc_test(
|
|
||||||
name = "util_{testcase}_test".format(testcase = f[len("test/util/"):-len("_test.cpp")]),
|
|
||||||
size = "small",
|
|
||||||
srcs = [f],
|
|
||||||
copts = TEST_COPTS,
|
|
||||||
linkstatic = 1,
|
|
||||||
deps = [
|
|
||||||
":spirv_tools_internal",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
|
||||||
) for f in glob(["test/util/*_test.cpp"])]
|
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "val_test_lib",
|
name = "val_test_common",
|
||||||
testonly = 1,
|
testonly = 1,
|
||||||
srcs = [
|
srcs = [
|
||||||
"test/val/val_code_generator.cpp",
|
"test/val/val_code_generator.cpp",
|
||||||
|
"test/val/val_fixtures.h",
|
||||||
],
|
],
|
||||||
hdrs = [
|
hdrs = [
|
||||||
"test/val/val_code_generator.h",
|
"test/val/val_code_generator.h",
|
||||||
"test/val/val_fixtures.h",
|
|
||||||
],
|
],
|
||||||
copts = TEST_COPTS,
|
compatible_with = [],
|
||||||
deps = [
|
|
||||||
":spirv_tools_internal",
|
|
||||||
":test_lib",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
[cc_test(
|
|
||||||
name = "val_{testcase}_test".format(testcase = f[len("test/val/val_"):-len("_test.cpp")]),
|
|
||||||
size = "small",
|
|
||||||
srcs = [f],
|
|
||||||
copts = TEST_COPTS,
|
copts = TEST_COPTS,
|
||||||
linkstatic = 1,
|
linkstatic = 1,
|
||||||
deps = [
|
deps = [":test_common"],
|
||||||
":spirv_tools_internal",
|
)
|
||||||
":test_lib",
|
|
||||||
":val_test_lib",
|
# PCH (precompiled header) tests only work when using CMake and MSVC on Windows,
|
||||||
"@com_google_googletest//:gtest",
|
# so they will be skipped in the Bazel builds.
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
[base_test(
|
||||||
|
name = f[5:-4], # strip test/, .cpp
|
||||||
|
srcs = [f],
|
||||||
) for f in glob(
|
) for f in glob(
|
||||||
["test/val/val_*_test.cpp"],
|
["test/*.cpp"],
|
||||||
exclude = [
|
exclude = [
|
||||||
"test/val/val_capability_test.cpp",
|
"test/cpp_interface_test.cpp", # has its own base_test below.
|
||||||
"test/val/val_limits_test.cpp",
|
"test/log_test.cpp", # has its own base_test below.
|
||||||
|
"test/pch_test.cpp", # pch tests are skipped.
|
||||||
|
"test/timer_test.cpp", # has its own base_test below.
|
||||||
],
|
],
|
||||||
)]
|
)]
|
||||||
|
|
||||||
cc_test(
|
# This test uses unistd.h and does not run on Windows.
|
||||||
name = "val_capability_test",
|
base_test(
|
||||||
size = "large",
|
name = "timer_test",
|
||||||
timeout = "long",
|
srcs = select({
|
||||||
srcs = ["test/val/val_capability_test.cpp"],
|
"@bazel_tools//src/conditions:windows": [],
|
||||||
copts = TEST_COPTS + ["-O3"],
|
"//conditions:default": ["test/timer_test.cpp"],
|
||||||
linkstatic = 1,
|
}),
|
||||||
deps = [
|
|
||||||
":spirv_tools_internal",
|
|
||||||
":test_lib",
|
|
||||||
":val_test_lib",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_test(
|
base_test(
|
||||||
name = "val_limits_test",
|
name = "cpp_interface_test",
|
||||||
size = "large",
|
srcs = ["test/cpp_interface_test.cpp"],
|
||||||
timeout = "long",
|
deps = [":spirv_tools_opt"],
|
||||||
srcs = ["test/val/val_limits_test.cpp"],
|
|
||||||
copts = TEST_COPTS + [
|
|
||||||
"-O3",
|
|
||||||
],
|
|
||||||
linkstatic = 1,
|
|
||||||
deps = [
|
|
||||||
":test_lib",
|
|
||||||
":val_test_lib",
|
|
||||||
"@com_google_googletest//:gtest",
|
|
||||||
"@com_google_googletest//:gtest_main",
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
base_test(
|
||||||
|
name = "log_test",
|
||||||
|
srcs = ["test/log_test.cpp"],
|
||||||
|
deps = [":spirv_tools_opt"],
|
||||||
|
)
|
||||||
|
|
||||||
|
[link_test(
|
||||||
|
name = f[10:-4], # strip test/link/, .cpp
|
||||||
|
srcs = [f],
|
||||||
|
) for f in glob(
|
||||||
|
["test/link/*.cpp"],
|
||||||
|
)]
|
||||||
|
|
||||||
|
[lint_test(
|
||||||
|
name = f[10:-4], # strip test/lint/, .cpp
|
||||||
|
srcs = [f],
|
||||||
|
) for f in glob(
|
||||||
|
["test/lint/*.cpp"],
|
||||||
|
)]
|
||||||
|
|
||||||
|
[opt_test(
|
||||||
|
name = f[9:-4], # strip test/opt/, .cpp
|
||||||
|
srcs = [f],
|
||||||
|
) for f in glob(
|
||||||
|
["test/opt/*.cpp"],
|
||||||
|
# pch tests are skipped.
|
||||||
|
exclude = ["test/opt/pch_test_opt.cpp"],
|
||||||
|
)]
|
||||||
|
|
||||||
|
[opt_test(
|
||||||
|
name = "dom_tree_" + f[24:-4], # strip test/opt/dominator_tree/, .cpp
|
||||||
|
srcs = [f],
|
||||||
|
) for f in glob(
|
||||||
|
["test/opt/dominator_tree/*.cpp"],
|
||||||
|
# pch tests are skipped.
|
||||||
|
exclude = ["test/opt/dominator_tree/pch_test_opt_dom.cpp"],
|
||||||
|
)]
|
||||||
|
|
||||||
|
[opt_test(
|
||||||
|
name = "loop_" + f[28:-4], # strip test/opt/loop_optimizations/, .cpp
|
||||||
|
srcs = [f],
|
||||||
|
) for f in glob(
|
||||||
|
["test/opt/loop_optimizations/*.cpp"],
|
||||||
|
# pch tests are skipped.
|
||||||
|
exclude = ["test/opt/loop_optimizations/pch_test_opt_loop.cpp"],
|
||||||
|
)]
|
||||||
|
|
||||||
|
[reduce_test(
|
||||||
|
name = f[12:-4], # strip test/reduce/, .cpp
|
||||||
|
srcs = [f],
|
||||||
|
) for f in glob(["test/reduce/*.cpp"])]
|
||||||
|
|
||||||
|
[util_test(
|
||||||
|
name = f[10:-4], # strip test/util/, .cpp
|
||||||
|
srcs = [f],
|
||||||
|
) for f in glob(["test/util/*.cpp"])]
|
||||||
|
|
||||||
|
[val_test(
|
||||||
|
name = f[9:-4], # strip test/val/, .cpp
|
||||||
|
srcs = [f],
|
||||||
|
) for f in glob(
|
||||||
|
["test/val/*.cpp"],
|
||||||
|
exclude = [
|
||||||
|
"test/val/pch_test_val.cpp", # pch tests are skipped.
|
||||||
|
],
|
||||||
|
)]
|
||||||
|
|
||||||
|
145
CHANGES
145
CHANGES
@ -1,150 +1,5 @@
|
|||||||
Revision history for SPIRV-Tools
|
Revision history for SPIRV-Tools
|
||||||
|
|
||||||
v2023.6 2023-12-18
|
|
||||||
- General
|
|
||||||
- update_build_version.py produce deterministic header. (#5426)
|
|
||||||
- Support missing git in update_build_version.py (#5473)
|
|
||||||
- Optimizer
|
|
||||||
- Add ComputeDerivativeGroup*NV capabilities to trim capabilities pass. (#5430)
|
|
||||||
- Do not crash when tryingto fold unsupported spec constant (#5496)
|
|
||||||
- instrument: Fix handling of gl_InvocationID (#5493)
|
|
||||||
- Fix nullptr argument in MarkInsertChain (#5465)
|
|
||||||
- opt: support 64-bit OpAccessChain index in FixStorageClass (#5446)
|
|
||||||
- opt: add StorageImageReadWithoutFormat to cap trim (#5475)
|
|
||||||
- opt: add PhysicalStorageBufferAddresses to trim (#5476)
|
|
||||||
- Fix array size calculation (#5463
|
|
||||||
- Validator
|
|
||||||
- spirv-val: Loosen restriction on base type of DebugTypePointer and DebugTypeQualifier (#5479)
|
|
||||||
- spirv-val: Add WorkgroupMemoryExplicitLayoutKHR check for Block (#5461)
|
|
||||||
|
|
||||||
v2023.5 2023-10-15
|
|
||||||
- General
|
|
||||||
- Support 2 Intel extensions (#5357)
|
|
||||||
- SPV_QCOM_image_processing support (#5223)
|
|
||||||
- Optimizer
|
|
||||||
- opt: fix StorageInputOutput16 trimming. (#5359)
|
|
||||||
- opt: add StoragePushConstant16 to trim pass (#5366)
|
|
||||||
- opt: enable StorageUniform16 (#5371)
|
|
||||||
- opt: add bitmask support for capability trimming (#5372)
|
|
||||||
- opt: Add SwitchDescriptorSetPass (#5375)
|
|
||||||
- opt: add FragmentShader*InterlockEXT to capability trim pass (#5390)
|
|
||||||
- opt: add Int64 capability to trim pass (#5398)
|
|
||||||
- opt: add Float64 capability to trim pass (#5428)
|
|
||||||
- opt: add raytracing/rayquery to trim pass (#5397)
|
|
||||||
- opt: add ImageMSArray capability to trim pass. (#5395)
|
|
||||||
- Add SPV_KHR_physical_storage_buffer to allowlists (#5402)
|
|
||||||
- Add SPV_EXT_fragment_shader_interlock to allow lists (#5393)
|
|
||||||
- Make sure that fragment shader interlock instructions are not removed by DCE (#5400)
|
|
||||||
- instrument: Use Import linkage for instrumentation functions (#5355)
|
|
||||||
- Add a new legalization pass to dedupe invocation interlock instructions (#5409)
|
|
||||||
- instrument: Ensure linking works even of nothing is changed (#5419)
|
|
||||||
- Validator
|
|
||||||
- Move token version/cap/ext checks from parsing to validation (#5370)
|
|
||||||
- val: re-add ImageMSArray validation (#5394)
|
|
||||||
- Linker
|
|
||||||
- linker: Add --use-highest-version option
|
|
||||||
|
|
||||||
v2023.4 2023-07-17
|
|
||||||
- General
|
|
||||||
- Set cmake_policy CMP0128 (#5341)
|
|
||||||
- Add python3 requirement for the script (#5326)
|
|
||||||
- Add support for LiteralFloat type (#5323)
|
|
||||||
- SPV_KHR_cooperative_matrix (#5286)
|
|
||||||
- Allow OpTypeBool in UniformConstant (#5237)
|
|
||||||
- Allow physical storage buffer pointer in IO (#5251)
|
|
||||||
- Remove const zero image operands (#5232)
|
|
||||||
- Optimizer
|
|
||||||
- Enable vector constant folding (#4913) (#5272)
|
|
||||||
- Fold negation of integer vectors (#5269)
|
|
||||||
- Add folding rule for OpTranspose (#5241)
|
|
||||||
- Add SPV_NV_bindless_texture to spirv optimizations (#5231)
|
|
||||||
- Fix incorrect half float conversion (#5349)
|
|
||||||
- Add SPV_EXT_shader_atomic_float_add to allow lists (#5348)
|
|
||||||
- Instrument
|
|
||||||
- instrument: Cast gl_VertexIndex and InstanceIndex to uint (#5319)
|
|
||||||
- instrument: Fix buffer address length calculations (#5257)
|
|
||||||
- instrument: Reduce number of inst_bindless_stream_write_6 calls (#5327)
|
|
||||||
- Validator
|
|
||||||
- Validate GroupNonUniform instructions (#5296)
|
|
||||||
- spirv-val: Label SPV_KHR_cooperative_matrix VUID (#5301)
|
|
||||||
- Validate layouts for PhysicalStorageBuffer pointers (#5291)
|
|
||||||
- spirv-val: Remove VUID from 1.3.251 spec (#5244)
|
|
||||||
- Diff
|
|
||||||
- spirv-diff: Update test expectations (#5264)
|
|
||||||
- spirv-diff: Leave undefined ids unpaired. (#5262)
|
|
||||||
- spirv-diff: Properly match SPV_KHR_ray_query types. (#5259)
|
|
||||||
- diff: Don't give up entry point matching too early. (#5224)
|
|
||||||
|
|
||||||
v2023.3 2023-05-15
|
|
||||||
- General
|
|
||||||
- Update spirv_headers to include SPV_KHR_ray_tracing_position_fetch (#5205)
|
|
||||||
- spirv-tools: Add support for QNX (#5211)
|
|
||||||
- build: set std=c++17 for BUILD.gn (#5162)
|
|
||||||
- Optimizer
|
|
||||||
- Run ADCE when the printf extension is used. (#5215)
|
|
||||||
- Don't convert struct members to half (#5201)
|
|
||||||
- Apply scalar replacement on vars with Pointer decorations (#5208)
|
|
||||||
- opt: Fix null deref in OpMatrixTimesVector and OpVectorTimesMatrix (#5199)
|
|
||||||
- instrument: Add set and binding to bindless error records (#5204)
|
|
||||||
- instrument: Change descriptor state storage format (#5178)
|
|
||||||
- Fix LICMPass (#5087)
|
|
||||||
- Add Vulkan memory model to allow lists (#5173)
|
|
||||||
- Do not remove control barrier after spv1.3 (#5174)
|
|
||||||
- Validator
|
|
||||||
- spirv-val: Label Interface Location/Component VUIDs (#5221)
|
|
||||||
- Add support for SPV_EXT_shader_tile_image (#5188)
|
|
||||||
- Fix vector OpConstantComposite type validation (#5191)
|
|
||||||
- spirv-val: Label new Vulkan VUID 07951 (#5154)
|
|
||||||
- Fuzz
|
|
||||||
- Do not define GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE if it is already defined. (#5200)
|
|
||||||
|
|
||||||
v2023.2 2023-03-10
|
|
||||||
- General
|
|
||||||
- build: move from c++11 to c++17 (#4983)
|
|
||||||
- tools: refactorize tools flags parsing. (#5111)
|
|
||||||
- Add C interface for Optimizer (#5030)
|
|
||||||
- libspirv.cpp: adds c++ api for spvBinaryParse (#5109)
|
|
||||||
- build: change the way we set cxx version for bazel. (#5114)
|
|
||||||
- Optimizer
|
|
||||||
- Fix null pointer in FoldInsertWithConstants. (#5093)
|
|
||||||
- Fix removal of dependent non-semantic instructions (#5122)
|
|
||||||
- Remove duplicate lists of constant and type opcodes (#5106)
|
|
||||||
- opt: fix spirv ABI on Linux again. (#5113)
|
|
||||||
- Validator
|
|
||||||
- Validate decoration of structs with RuntimeArray (#5094)
|
|
||||||
- Validate operand type before operating on it (#5092)
|
|
||||||
- spirv-val: Conditional Branch without an exit is invalid in loop header (#5069)
|
|
||||||
- spirv-val: Initial SPV_EXT_mesh_shader builtins (#5080)
|
|
||||||
|
|
||||||
v2023.1 2023-01-17
|
|
||||||
- General
|
|
||||||
- Renamed "master" to "main" (issue#5051)
|
|
||||||
- Validate version 5 of clspv reflection (#5050)
|
|
||||||
- Remove testing support for VS2015 (#5027)
|
|
||||||
- Fix undef behaviour in hex float parsing (#5025)
|
|
||||||
- Require C++11 *or later* (#5020)
|
|
||||||
- Instrument
|
|
||||||
- Instrument: Fix bindless checking for BufferDeviceAddress (#5049)
|
|
||||||
- Optimizer
|
|
||||||
- Optimize allocation of spvtools::opt::Instruction::operands_ (#5024)
|
|
||||||
- spirv-opt: Fix OpCompositeInsert with Null Constant (#5008)
|
|
||||||
- spirv-opt: Handle null CompositeInsert (#4998)
|
|
||||||
- Add option to ADCE to remove output variables from interface. (#4994)
|
|
||||||
- Add support for tesc, tese and geom to EliminateDead*Components (#4990)
|
|
||||||
- Add pass to eliminate dead output components (#4982)
|
|
||||||
- spirv-opt: Add const folding for CompositeInsert (#4943)
|
|
||||||
- Add passes to eliminate dead output stores (#4970)
|
|
||||||
- Prevent eliminating case constructs in block merging (#4976)
|
|
||||||
- Validator
|
|
||||||
- Fix layout validation (#5015)
|
|
||||||
- Fix use of invalid analysis (#5013)
|
|
||||||
- Fix infinite loop in validator (#5006)
|
|
||||||
- Add validation support for SPV_NV_shader_invocation_reorder. (#4979)
|
|
||||||
- Only validate full layout in Vulkan environments (#4972)
|
|
||||||
- spirv-val: Label new Vulkan OpPtrAccessChain VUs (#4975)
|
|
||||||
- spirv-val: Add OpPtrAccessChain Base checks (#4965)
|
|
||||||
|
|
||||||
|
|
||||||
v2022.4 2022-10-12
|
v2022.4 2022-10-12
|
||||||
- General
|
- General
|
||||||
- Support Narrow Types in BitCast Folding Rule (#4941)
|
- Support Narrow Types in BitCast Folding Rule (#4941)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2015-2023 The Khronos Group Inc.
|
# Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -12,38 +12,26 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.17.2)
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
if (POLICY CMP0048)
|
||||||
project(spirv-tools)
|
cmake_policy(SET CMP0048 NEW)
|
||||||
|
endif()
|
||||||
# Avoid a bug in CMake 3.22.1. By default it will set -std=c++11 for
|
if (POLICY CMP0054)
|
||||||
# targets in test/*, when those tests need -std=c++17.
|
# Avoid dereferencing variables or interpret keywords that have been
|
||||||
# https://github.com/KhronosGroup/SPIRV-Tools/issues/5340
|
# quoted or bracketed.
|
||||||
# The bug is fixed in CMake 3.22.2
|
# https://cmake.org/cmake/help/v3.1/policy/CMP0054.html
|
||||||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.22.1")
|
cmake_policy(SET CMP0054 NEW)
|
||||||
if (${CMAKE_VERSION} VERSION_LESS "3.22.2")
|
|
||||||
cmake_policy(SET CMP0128 NEW)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
|
project(spirv-tools)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
set(SPIRV_TOOLS "SPIRV-Tools")
|
set(SPIRV_TOOLS "SPIRV-Tools")
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
# Require at least C++17
|
|
||||||
if(NOT CMAKE_CXX_STANDARD)
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
endif()
|
|
||||||
if(${CMAKE_CXX_STANDARD} LESS 17)
|
|
||||||
message(FATAL_ERROR "SPIRV-Tools requires C++17 or later, but is configured for C++${CMAKE_CXX_STANDARD})")
|
|
||||||
endif()
|
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
||||||
|
|
||||||
|
|
||||||
option(ENABLE_RTTI "Enables RTTI" OFF)
|
option(ENABLE_RTTI "Enables RTTI" OFF)
|
||||||
option(SPIRV_ALLOW_TIMERS "Allow timers via clock_gettime on supported platforms" ON)
|
option(SPIRV_ALLOW_TIMERS "Allow timers via clock_gettime on supported platforms" ON)
|
||||||
@ -63,8 +51,6 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "iOS")
|
|||||||
add_definitions(-DSPIRV_IOS)
|
add_definitions(-DSPIRV_IOS)
|
||||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "tvOS")
|
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "tvOS")
|
||||||
add_definitions(-DSPIRV_TVOS)
|
add_definitions(-DSPIRV_TVOS)
|
||||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "visionOS")
|
|
||||||
add_definitions(-DSPIRV_VISIONOS)
|
|
||||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
|
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
|
||||||
add_definitions(-DSPIRV_ANDROID)
|
add_definitions(-DSPIRV_ANDROID)
|
||||||
set(SPIRV_TIMER_ENABLED ${SPIRV_ALLOW_TIMERS})
|
set(SPIRV_TIMER_ENABLED ${SPIRV_ALLOW_TIMERS})
|
||||||
@ -76,8 +62,6 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia")
|
|||||||
add_definitions(-DSPIRV_FUCHSIA)
|
add_definitions(-DSPIRV_FUCHSIA)
|
||||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "GNU")
|
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "GNU")
|
||||||
add_definitions(-DSPIRV_GNU)
|
add_definitions(-DSPIRV_GNU)
|
||||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "QNX")
|
|
||||||
add_definitions(-DSPIRV_QNX)
|
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Your platform '${CMAKE_SYSTEM_NAME}' is not supported!")
|
message(FATAL_ERROR "Your platform '${CMAKE_SYSTEM_NAME}' is not supported!")
|
||||||
endif()
|
endif()
|
||||||
@ -204,9 +188,10 @@ function(spvtools_default_compile_options TARGET)
|
|||||||
target_compile_options(${TARGET} PRIVATE ${SPIRV_WARNINGS})
|
target_compile_options(${TARGET} PRIVATE ${SPIRV_WARNINGS})
|
||||||
|
|
||||||
if (${COMPILER_IS_LIKE_GNU})
|
if (${COMPILER_IS_LIKE_GNU})
|
||||||
|
target_compile_options(${TARGET} PRIVATE -std=c++11 -fno-exceptions)
|
||||||
target_compile_options(${TARGET} PRIVATE
|
target_compile_options(${TARGET} PRIVATE
|
||||||
-Wall -Wextra -Wno-long-long -Wshadow -Wundef -Wconversion
|
-Wall -Wextra -Wno-long-long -Wshadow -Wundef -Wconversion
|
||||||
-Wno-sign-conversion -fno-exceptions)
|
-Wno-sign-conversion)
|
||||||
|
|
||||||
if(NOT ENABLE_RTTI)
|
if(NOT ENABLE_RTTI)
|
||||||
add_compile_options(-fno-rtti)
|
add_compile_options(-fno-rtti)
|
||||||
@ -215,7 +200,7 @@ function(spvtools_default_compile_options TARGET)
|
|||||||
if(NOT "${SPIRV_PERF}" STREQUAL "")
|
if(NOT "${SPIRV_PERF}" STREQUAL "")
|
||||||
target_compile_options(${TARGET} PRIVATE -fno-omit-frame-pointer)
|
target_compile_options(${TARGET} PRIVATE -fno-omit-frame-pointer)
|
||||||
endif()
|
endif()
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
|
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
set(SPIRV_USE_SANITIZER "" CACHE STRING
|
set(SPIRV_USE_SANITIZER "" CACHE STRING
|
||||||
"Use the clang sanitizer [address|memory|thread|...]")
|
"Use the clang sanitizer [address|memory|thread|...]")
|
||||||
if(NOT "${SPIRV_USE_SANITIZER}" STREQUAL "")
|
if(NOT "${SPIRV_USE_SANITIZER}" STREQUAL "")
|
||||||
@ -243,7 +228,7 @@ function(spvtools_default_compile_options TARGET)
|
|||||||
# For MinGW cross compile, statically link to the C++ runtime.
|
# For MinGW cross compile, statically link to the C++ runtime.
|
||||||
# But it still depends on MSVCRT.dll.
|
# But it still depends on MSVCRT.dll.
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||||
if (NOT MSVC)
|
if (${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
|
||||||
set_target_properties(${TARGET} PROPERTIES
|
set_target_properties(${TARGET} PROPERTIES
|
||||||
LINK_FLAGS -static -static-libgcc -static-libstdc++)
|
LINK_FLAGS -static -static-libgcc -static-libstdc++)
|
||||||
endif()
|
endif()
|
||||||
@ -262,7 +247,7 @@ if(NOT COMMAND find_host_program)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Tests require Python3
|
# Tests require Python3
|
||||||
find_host_package(Python3 REQUIRED)
|
find_host_package(PythonInterp 3 REQUIRED)
|
||||||
|
|
||||||
# Check for symbol exports on Linux.
|
# Check for symbol exports on Linux.
|
||||||
# At the moment, this check will fail on the OSX build machines for the Android NDK.
|
# At the moment, this check will fail on the OSX build machines for the Android NDK.
|
||||||
@ -271,7 +256,7 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
|||||||
macro(spvtools_check_symbol_exports TARGET)
|
macro(spvtools_check_symbol_exports TARGET)
|
||||||
if (NOT "${SPIRV_SKIP_TESTS}")
|
if (NOT "${SPIRV_SKIP_TESTS}")
|
||||||
add_test(NAME spirv-tools-symbol-exports-${TARGET}
|
add_test(NAME spirv-tools-symbol-exports-${TARGET}
|
||||||
COMMAND Python3::Interpreter
|
COMMAND ${PYTHON_EXECUTABLE}
|
||||||
${spirv-tools_SOURCE_DIR}/utils/check_symbol_exports.py "$<TARGET_FILE:${TARGET}>")
|
${spirv-tools_SOURCE_DIR}/utils/check_symbol_exports.py "$<TARGET_FILE:${TARGET}>")
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
@ -284,7 +269,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||||
if(WIN32 AND NOT MINGW)
|
if(WIN32)
|
||||||
macro(spvtools_config_package_dir TARGET PATH)
|
macro(spvtools_config_package_dir TARGET PATH)
|
||||||
set(${PATH} ${TARGET}/cmake)
|
set(${PATH} ${TARGET}/cmake)
|
||||||
endmacro()
|
endmacro()
|
||||||
@ -304,23 +289,15 @@ if(ENABLE_SPIRV_TOOLS_INSTALL)
|
|||||||
endmacro()
|
endmacro()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Currently iOS and Android are very similar.
|
# Defaults to OFF if the user didn't set it.
|
||||||
# They both have their own packaging (APP/APK).
|
option(SPIRV_SKIP_EXECUTABLES
|
||||||
# Which makes regular executables/testing problematic.
|
"Skip building the executable and tests along with the library"
|
||||||
#
|
${SPIRV_SKIP_EXECUTABLES})
|
||||||
# Currently the only deliverables for these platforms are
|
option(SPIRV_SKIP_TESTS
|
||||||
# libraries (either STATIC or SHARED).
|
"Skip building tests along with the library" ${SPIRV_SKIP_TESTS})
|
||||||
#
|
if ("${SPIRV_SKIP_EXECUTABLES}")
|
||||||
# Furthermore testing is equally problematic.
|
|
||||||
if (IOS OR ANDROID)
|
|
||||||
set(SPIRV_SKIP_EXECUTABLES ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(SPIRV_SKIP_EXECUTABLES "Skip building the executable and tests along with the library")
|
|
||||||
if (SPIRV_SKIP_EXECUTABLES)
|
|
||||||
set(SPIRV_SKIP_TESTS ON)
|
set(SPIRV_SKIP_TESTS ON)
|
||||||
endif()
|
endif()
|
||||||
option(SPIRV_SKIP_TESTS "Skip building tests along with the library")
|
|
||||||
|
|
||||||
# Defaults to ON. The checks can be time consuming.
|
# Defaults to ON. The checks can be time consuming.
|
||||||
# Turn off if they take too long.
|
# Turn off if they take too long.
|
||||||
@ -378,7 +355,7 @@ endif(ENABLE_SPIRV_TOOLS_INSTALL)
|
|||||||
|
|
||||||
if (NOT "${SPIRV_SKIP_TESTS}")
|
if (NOT "${SPIRV_SKIP_TESTS}")
|
||||||
add_test(NAME spirv-tools-copyrights
|
add_test(NAME spirv-tools-copyrights
|
||||||
COMMAND Python3::Interpreter utils/check_copyright.py
|
COMMAND ${PYTHON_EXECUTABLE} utils/check_copyright.py
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
126
CONTRIBUTING.md
126
CONTRIBUTING.md
@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
## For users: Reporting bugs and requesting features
|
## For users: Reporting bugs and requesting features
|
||||||
|
|
||||||
We organize known future work in GitHub projects. See
|
We organize known future work in GitHub projects. See [Tracking SPIRV-Tools work
|
||||||
[Tracking SPIRV-Tools work with GitHub projects](https://github.com/KhronosGroup/SPIRV-Tools/blob/main/docs/projects.md)
|
with GitHub
|
||||||
|
projects](https://github.com/KhronosGroup/SPIRV-Tools/blob/master/docs/projects.md)
|
||||||
for more.
|
for more.
|
||||||
|
|
||||||
To report a new bug or request a new feature, please file a GitHub issue. Please
|
To report a new bug or request a new feature, please file a GitHub issue. Please
|
||||||
@ -35,9 +36,9 @@ create a new issue, as with bugs. In the issue provide
|
|||||||
|
|
||||||
## For developers: Contributing a patch
|
## For developers: Contributing a patch
|
||||||
|
|
||||||
Before we can use your code, you must sign the
|
Before we can use your code, you must sign the [Khronos Open Source Contributor
|
||||||
[Khronos Open Source Contributor License Agreement](https://cla-assistant.io/KhronosGroup/SPIRV-Tools)
|
License Agreement](https://cla-assistant.io/KhronosGroup/SPIRV-Tools) (CLA),
|
||||||
(CLA), which you can do online. The CLA is necessary mainly because you own the
|
which you can do online. The CLA is necessary mainly because you own the
|
||||||
copyright to your changes, even after your contribution becomes part of our
|
copyright to your changes, even after your contribution becomes part of our
|
||||||
codebase, so we need your permission to use and distribute your code. We also
|
codebase, so we need your permission to use and distribute your code. We also
|
||||||
need to be sure of various other things -- for instance that you'll tell us if
|
need to be sure of various other things -- for instance that you'll tell us if
|
||||||
@ -46,20 +47,20 @@ sign the CLA until after you've submitted your code for review and a member has
|
|||||||
approved it, but you must do it before we can put your code into our codebase.
|
approved it, but you must do it before we can put your code into our codebase.
|
||||||
|
|
||||||
See
|
See
|
||||||
[README.md](https://github.com/KhronosGroup/SPIRV-Tools/blob/main/README.md)
|
[README.md](https://github.com/KhronosGroup/SPIRV-Tools/blob/master/README.md)
|
||||||
for instruction on how to get, build, and test the source. Once you have made
|
for instruction on how to get, build, and test the source. Once you have made
|
||||||
your changes:
|
your changes:
|
||||||
|
|
||||||
* Ensure the code follows the
|
* Ensure the code follows the [Google C++ Style
|
||||||
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html).
|
Guide](https://google.github.io/styleguide/cppguide.html). Running
|
||||||
Running `clang-format -style=file -i [modified-files]` can help.
|
`clang-format -style=file -i [modified-files]` can help.
|
||||||
* Create a pull request (PR) with your patch.
|
* Create a pull request (PR) with your patch.
|
||||||
* Make sure the PR description clearly identified the problem, explains the
|
* Make sure the PR description clearly identified the problem, explains the
|
||||||
solution, and references the issue if applicable.
|
solution, and references the issue if applicable.
|
||||||
* If your patch completely fixes bug 1234, the commit message should say
|
* If your patch completely fixes bug 1234, the commit message should say
|
||||||
`Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/1234` When you do
|
`Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/1234`
|
||||||
this, the issue will be closed automatically when the commit goes into
|
When you do this, the issue will be closed automatically when the commit
|
||||||
main. Also, this helps us update the [CHANGES](CHANGES) file.
|
goes into master. Also, this helps us update the [CHANGES](CHANGES) file.
|
||||||
* Watch the continuous builds to make sure they pass.
|
* Watch the continuous builds to make sure they pass.
|
||||||
* Request a code review.
|
* Request a code review.
|
||||||
|
|
||||||
@ -81,8 +82,8 @@ Instructions for this are given below.
|
|||||||
The formal code reviews are done on GitHub. Reviewers are to look for all of the
|
The formal code reviews are done on GitHub. Reviewers are to look for all of the
|
||||||
usual things:
|
usual things:
|
||||||
|
|
||||||
* Coding style follows the
|
* Coding style follows the [Google C++ Style
|
||||||
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html)
|
Guide](https://google.github.io/styleguide/cppguide.html)
|
||||||
* Identify potential functional problems.
|
* Identify potential functional problems.
|
||||||
* Identify code duplication.
|
* Identify code duplication.
|
||||||
* Ensure the unit tests have enough coverage.
|
* Ensure the unit tests have enough coverage.
|
||||||
@ -101,49 +102,84 @@ should pay particular attention to:
|
|||||||
updated. For example, a new instruction is added, but the def-use manager is
|
updated. For example, a new instruction is added, but the def-use manager is
|
||||||
not updated. Later on, it is possible that the def-use manager will be used,
|
not updated. Later on, it is possible that the def-use manager will be used,
|
||||||
and give wrong results.
|
and give wrong results.
|
||||||
* If a pass gets the id of a type from the type manager, make sure the type is
|
|
||||||
not a struct or array. It there are two structs that look the same, the type
|
|
||||||
manager can return the wrong one.
|
|
||||||
|
|
||||||
## For maintainers: Merging a PR
|
## For maintainers: Merging a PR
|
||||||
|
|
||||||
We intend to maintain a linear history on the GitHub main branch, and the
|
We intend to maintain a linear history on the GitHub master branch, and the
|
||||||
build and its tests should pass at each commit in that history. A linear
|
build and its tests should pass at each commit in that history. A linear
|
||||||
always-working history is easier to understand and to bisect in case we want to
|
always-working history is easier to understand and to bisect in case we want to
|
||||||
find which commit introduced a bug. The
|
find which commit introduced a bug.
|
||||||
[Squash and Merge](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#squash-and-merge-your-commits)
|
|
||||||
button on the GitHub web interface. All other ways of merging on the web
|
|
||||||
interface have been disabled.
|
|
||||||
|
|
||||||
Before merging, we generally require:
|
### Initial merge setup
|
||||||
|
|
||||||
1. All tests except for the smoke test pass. See
|
The following steps should be done exactly once (when you are about to merge a
|
||||||
[failing smoke test](#failing-smoke-test).
|
PR for the first time):
|
||||||
1. The PR is approved by at least one of the maintainers. If the PR modifies
|
|
||||||
different parts of the code, then multiple reviewers might be necessary.
|
|
||||||
|
|
||||||
The squash-and-merge button will turn green when these requirements are met.
|
* It is assumed that upstream points to
|
||||||
Maintainers have the to power to merge even if the button is not green, but that
|
[git@github.com](mailto:git@github.com):KhronosGroup/SPIRV-Tools.git or
|
||||||
is discouraged.
|
https://github.com/KhronosGroup/SPIRV-Tools.git.
|
||||||
|
|
||||||
### Failing smoke test
|
* Find out the local name for the main github repo in your git configuration.
|
||||||
|
For example, in this configuration, it is labeled `upstream`.
|
||||||
|
|
||||||
The purpose of the smoke test is to let us know if
|
```
|
||||||
[shaderc](https://github.com/google/shaderc) fails to build with the change. If
|
git remote -v
|
||||||
it fails, the maintainer needs to determine if the reason for the failure is a
|
[ ... ]
|
||||||
problem in the current PR or if another repository needs to be changed. Most of
|
upstream https://github.com/KhronosGroup/SPIRV-Tools.git (fetch)
|
||||||
the time [Glslang](https://github.com/KhronosGroup/glslang) needs to be updated
|
upstream https://github.com/KhronosGroup/SPIRV-Tools.git (push)
|
||||||
to account for the change in SPIR-V Tools.
|
```
|
||||||
|
|
||||||
The PR can still be merged if the problem is not with that PR.
|
* Make sure that the `upstream` remote is set to fetch from the `refs/pull`
|
||||||
|
namespace:
|
||||||
|
|
||||||
## For maintainers: Running tests
|
```
|
||||||
|
git config --get-all remote.upstream.fetch
|
||||||
|
+refs/heads/*:refs/remotes/upstream/*
|
||||||
|
+refs/pull/*/head:refs/remotes/upstream/pr/*
|
||||||
|
```
|
||||||
|
|
||||||
For security reasons, not all tests will run automatically. When they do not, a
|
* If the line `+refs/pull/*/head:refs/remotes/upstream/pr/*` is not present in
|
||||||
maintainer will have to start the tests.
|
your configuration, you can add it with the command:
|
||||||
|
|
||||||
If the Github actions tests do not run on a PR, they can be initiated by closing
|
```
|
||||||
and reopening the PR.
|
git config --local --add remote.upstream.fetch '+refs/pull/*/head:refs/remotes/upstream/pr/*'
|
||||||
|
```
|
||||||
|
|
||||||
If the kokoro tests are not run, they can be run by adding the label
|
### Merge workflow
|
||||||
`kokoro:run` to the PR.
|
|
||||||
|
The following steps should be done for every PR that you intend to merge:
|
||||||
|
|
||||||
|
* Make sure your local copy of the master branch is up to date:
|
||||||
|
|
||||||
|
```
|
||||||
|
git checkout master
|
||||||
|
git pull
|
||||||
|
```
|
||||||
|
|
||||||
|
* Fetch all pull requests refs:
|
||||||
|
|
||||||
|
```
|
||||||
|
git fetch upstream
|
||||||
|
```
|
||||||
|
|
||||||
|
* Checkout the particular pull request you are going to review:
|
||||||
|
|
||||||
|
```
|
||||||
|
git checkout pr/1048
|
||||||
|
```
|
||||||
|
|
||||||
|
* Rebase the PR on top of the master branch. If there are conflicts, send it
|
||||||
|
back to the author and ask them to rebase. During the interactive rebase be
|
||||||
|
sure to squash all of the commits down to a single commit.
|
||||||
|
|
||||||
|
```
|
||||||
|
git rebase -i master
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Build and test the PR.**
|
||||||
|
|
||||||
|
* If all of the tests pass, push the commit `git push upstream HEAD:master`
|
||||||
|
|
||||||
|
* Close the PR and add a comment saying it was push using the commit that you
|
||||||
|
just pushed. See https://github.com/KhronosGroup/SPIRV-Tools/pull/935 as an
|
||||||
|
example.
|
||||||
|
21
DEPS
21
DEPS
@ -3,32 +3,19 @@ use_relative_paths = True
|
|||||||
vars = {
|
vars = {
|
||||||
'github': 'https://github.com',
|
'github': 'https://github.com',
|
||||||
|
|
||||||
'abseil_revision': '79ca5d7aad63973c83a4962a66ab07cd623131ea',
|
'effcee_revision': '35912e1b7778ec2ddcff7e7188177761539e59e0',
|
||||||
|
'googletest_revision': 'd9bb8412d60b993365abb53f00b6dad9b2c01b62',
|
||||||
'effcee_revision': '19b4aa87af25cb4ee779a071409732f34bfc305c',
|
're2_revision': 'd2836d1b1c34c4e330a85a1006201db474bf2c8a',
|
||||||
|
'spirv_headers_revision': '85a1ed200d50660786c1a88d9166e871123cce39',
|
||||||
'googletest_revision': 'b10fad38c4026a29ea6561ab15fc4818170d1c10',
|
|
||||||
|
|
||||||
# Use protobufs before they gained the dependency on abseil
|
|
||||||
'protobuf_revision': 'v21.12',
|
|
||||||
|
|
||||||
're2_revision': '7e0c1a9e2417e70e5f0efc323267ac71d1fa0685',
|
|
||||||
'spirv_headers_revision': '1c6bb2743599e6eb6f37b2969acc0aef812e32e3',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deps = {
|
deps = {
|
||||||
'external/abseil_cpp':
|
|
||||||
Var('github') + '/abseil/abseil-cpp.git@' + Var('abseil_revision'),
|
|
||||||
|
|
||||||
'external/effcee':
|
'external/effcee':
|
||||||
Var('github') + '/google/effcee.git@' + Var('effcee_revision'),
|
Var('github') + '/google/effcee.git@' + Var('effcee_revision'),
|
||||||
|
|
||||||
'external/googletest':
|
'external/googletest':
|
||||||
Var('github') + '/google/googletest.git@' + Var('googletest_revision'),
|
Var('github') + '/google/googletest.git@' + Var('googletest_revision'),
|
||||||
|
|
||||||
'external/protobuf':
|
|
||||||
Var('github') + '/protocolbuffers/protobuf.git@' + Var('protobuf_revision'),
|
|
||||||
|
|
||||||
'external/re2':
|
'external/re2':
|
||||||
Var('github') + '/google/re2.git@' + Var('re2_revision'),
|
Var('github') + '/google/re2.git@' + Var('re2_revision'),
|
||||||
|
|
||||||
|
@ -18,8 +18,6 @@ See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
|
|||||||
for more details about the presubmit API built into depot_tools.
|
for more details about the presubmit API built into depot_tools.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
USE_PYTHON3 = True
|
|
||||||
|
|
||||||
LINT_FILTERS = [
|
LINT_FILTERS = [
|
||||||
"-build/storage_class",
|
"-build/storage_class",
|
||||||
"-readability/casting",
|
"-readability/casting",
|
||||||
|
2
README.OpenSource
Executable file → Normal file
2
README.OpenSource
Executable file → Normal file
@ -3,7 +3,7 @@
|
|||||||
"Name": "spirv-tools",
|
"Name": "spirv-tools",
|
||||||
"License": "Apache-2.0",
|
"License": "Apache-2.0",
|
||||||
"License File": "LICENSE",
|
"License File": "LICENSE",
|
||||||
"Version Number": "sdk-1.3.275.0",
|
"Version Number": "v2022.4",
|
||||||
"Owner": "zhangleiyu1@huawei.com",
|
"Owner": "zhangleiyu1@huawei.com",
|
||||||
"Upstream URL": "https://github.com/KhronosGroup/SPIRV-Tools.git",
|
"Upstream URL": "https://github.com/KhronosGroup/SPIRV-Tools.git",
|
||||||
"Description": "The SPIR-V Tools project provides an API and commands for processing SPIR-V modules."
|
"Description": "The SPIR-V Tools project provides an API and commands for processing SPIR-V modules."
|
||||||
|
49
README.md
49
README.md
@ -1,7 +1,4 @@
|
|||||||
# SPIR-V Tools
|
# SPIR-V Tools
|
||||||
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/KhronosGroup/SPIRV-Tools/badge)](https://securityscorecards.dev/viewer/?uri=github.com/KhronosGroup/SPIRV-Tools)
|
|
||||||
|
|
||||||
NEWS 2023-01-11: Development occurs on the `main` branch.
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@ -26,7 +23,7 @@ headers, and XML registry.
|
|||||||
|
|
||||||
<img alt="Linux" src="kokoro/img/linux.png" width="20px" height="20px" hspace="2px"/>[![Linux Build Status](https://storage.googleapis.com/spirv-tools/badges/build_status_linux_clang_release.svg)](https://storage.googleapis.com/spirv-tools/badges/build_link_linux_clang_release.html)
|
<img alt="Linux" src="kokoro/img/linux.png" width="20px" height="20px" hspace="2px"/>[![Linux Build Status](https://storage.googleapis.com/spirv-tools/badges/build_status_linux_clang_release.svg)](https://storage.googleapis.com/spirv-tools/badges/build_link_linux_clang_release.html)
|
||||||
<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="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_vs2019_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](docs/downloads.md)
|
[More downloads](docs/downloads.md)
|
||||||
|
|
||||||
@ -99,10 +96,10 @@ and in-progress work.
|
|||||||
|
|
||||||
*Note*: The validator checks some Universal Limits, from section 2.17 of the SPIR-V spec.
|
*Note*: The validator checks some Universal Limits, from section 2.17 of the SPIR-V spec.
|
||||||
The validator will fail on a module that exceeds those minimum upper bound limits.
|
The validator will fail on a module that exceeds those minimum upper bound limits.
|
||||||
The validator has been parameterized to allow larger values, for use when targeting
|
It is [future work](https://github.com/KhronosGroup/SPIRV-Tools/projects/1#card-1052403)
|
||||||
a more-than-minimally-capable SPIR-V consumer.
|
to parameterize the validator to allow larger
|
||||||
|
limits accepted by a more than minimally capable SPIR-V consumer.
|
||||||
|
|
||||||
See [`tools/val/val.cpp`](tools/val/val.cpp) or run `spirv-val --help` for the command-line help.
|
|
||||||
|
|
||||||
### Optimizer
|
### Optimizer
|
||||||
|
|
||||||
@ -274,7 +271,7 @@ Contributions via merge request are welcome. Changes should:
|
|||||||
`clang-format version 5.0.0` for SPIRV-Tools. Settings are defined by
|
`clang-format version 5.0.0` for SPIRV-Tools. Settings are defined by
|
||||||
the included [.clang-format](.clang-format) file.
|
the included [.clang-format](.clang-format) file.
|
||||||
|
|
||||||
We intend to maintain a linear history on the GitHub `main` branch.
|
We intend to maintain a linear history on the GitHub `master` branch.
|
||||||
|
|
||||||
### Getting the source
|
### Getting the source
|
||||||
|
|
||||||
@ -293,18 +290,16 @@ For some kinds of development, you may need the latest sources from the third-pa
|
|||||||
git clone https://github.com/google/googletest.git spirv-tools/external/googletest
|
git clone https://github.com/google/googletest.git spirv-tools/external/googletest
|
||||||
git clone https://github.com/google/effcee.git spirv-tools/external/effcee
|
git clone https://github.com/google/effcee.git spirv-tools/external/effcee
|
||||||
git clone https://github.com/google/re2.git spirv-tools/external/re2
|
git clone https://github.com/google/re2.git spirv-tools/external/re2
|
||||||
git clone https://github.com/abseil/abseil-cpp.git spirv-tools/external/abseil_cpp
|
|
||||||
|
|
||||||
#### Dependency on Effcee
|
#### Dependency on Effcee
|
||||||
|
|
||||||
Some tests depend on the [Effcee][effcee] library for stateful matching.
|
Some tests depend on the [Effcee][effcee] library for stateful matching.
|
||||||
Effcee itself depends on [RE2][re2], and RE2 depends on [Abseil][abseil-cpp].
|
Effcee itself depends on [RE2][re2].
|
||||||
|
|
||||||
* If SPIRV-Tools is configured as part of a larger project that already uses
|
* If SPIRV-Tools is configured as part of a larger project that already uses
|
||||||
Effcee, then that project should include Effcee before SPIRV-Tools.
|
Effcee, then that project should include Effcee before SPIRV-Tools.
|
||||||
* Otherwise, SPIRV-Tools expects Effcee sources to appear in `external/effcee`,
|
* Otherwise, SPIRV-Tools expects Effcee sources to appear in `external/effcee`
|
||||||
RE2 sources to appear in `external/re2`, and Abseil sources to appear in
|
and RE2 sources to appear in `external/re2`.
|
||||||
`external/abseil_cpp`.
|
|
||||||
|
|
||||||
### Source code organization
|
### Source code organization
|
||||||
|
|
||||||
@ -316,9 +311,6 @@ Effcee itself depends on [RE2][re2], and RE2 depends on [Abseil][abseil-cpp].
|
|||||||
* `external/re2`: Location of [RE2][re2] sources, if the `re2` library is not already
|
* `external/re2`: Location of [RE2][re2] sources, if the `re2` library is not already
|
||||||
configured by an enclosing project.
|
configured by an enclosing project.
|
||||||
(The Effcee project already requires RE2.)
|
(The Effcee project already requires RE2.)
|
||||||
* `external/abseil_cpp`: Location of [Abseil][abseil-cpp] sources, if Abseil is
|
|
||||||
not already configured by an enclosing project.
|
|
||||||
(The RE2 project already requires Abseil.)
|
|
||||||
* `include/`: API clients should add this directory to the include search path
|
* `include/`: API clients should add this directory to the include search path
|
||||||
* `external/spirv-headers`: Intended location for
|
* `external/spirv-headers`: Intended location for
|
||||||
[SPIR-V headers][spirv-headers], not provided
|
[SPIR-V headers][spirv-headers], not provided
|
||||||
@ -386,11 +378,10 @@ fuzzer tests.
|
|||||||
|
|
||||||
### Build using Bazel
|
### Build using Bazel
|
||||||
You can also use [Bazel](https://bazel.build/) to build the project.
|
You can also use [Bazel](https://bazel.build/) to build the project.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
cd <spirv-dir>
|
||||||
bazel build :all
|
bazel build :all
|
||||||
```
|
```
|
||||||
|
|
||||||
### Build a node.js package using Emscripten
|
### Build a node.js package using Emscripten
|
||||||
|
|
||||||
The SPIRV-Tools core library can be built to a WebAssembly [node.js](https://nodejs.org)
|
The SPIRV-Tools core library can be built to a WebAssembly [node.js](https://nodejs.org)
|
||||||
@ -441,13 +432,10 @@ On MacOS
|
|||||||
- AppleClang 11.0
|
- AppleClang 11.0
|
||||||
|
|
||||||
On Windows
|
On Windows
|
||||||
|
- Visual Studio 2015
|
||||||
- Visual Studio 2017
|
- Visual Studio 2017
|
||||||
- Visual Studio 2019
|
|
||||||
- Visual Studio 2022
|
|
||||||
|
|
||||||
Note: Visual Studio 2017 has incomplete c++17 support. We might stop
|
Other compilers or later versions may work, but they are not tested.
|
||||||
testing it soon. Other compilers or later versions may work, but they are not
|
|
||||||
tested.
|
|
||||||
|
|
||||||
### CMake options
|
### CMake options
|
||||||
|
|
||||||
@ -479,12 +467,12 @@ iterator debugging.
|
|||||||
### Android ndk-build
|
### Android ndk-build
|
||||||
|
|
||||||
SPIR-V Tools supports building static libraries `libSPIRV-Tools.a` and
|
SPIR-V Tools supports building static libraries `libSPIRV-Tools.a` and
|
||||||
`libSPIRV-Tools-opt.a` for Android. Using the Android NDK r25c or later:
|
`libSPIRV-Tools-opt.a` for Android:
|
||||||
|
|
||||||
```
|
```
|
||||||
cd <spirv-dir>
|
cd <spirv-dir>
|
||||||
|
|
||||||
export ANDROID_NDK=/path/to/your/ndk # NDK r25c or later
|
export ANDROID_NDK=/path/to/your/ndk
|
||||||
|
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
mkdir libs
|
mkdir libs
|
||||||
@ -508,7 +496,7 @@ The script requires Chromium's
|
|||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
The internals of the library use C++17 features, and are exposed via both a C
|
The internals of the library use C++11 features, and are exposed via both a C
|
||||||
and C++ API.
|
and C++ API.
|
||||||
|
|
||||||
In order to use the library from an application, the include path should point
|
In order to use the library from an application, the include path should point
|
||||||
@ -730,16 +718,10 @@ Use `bazel test :all` to run all tests. This will run tests in parallel by defau
|
|||||||
To run a single test target, specify `:my_test_target` instead of `:all`. Test target
|
To run a single test target, specify `:my_test_target` instead of `:all`. Test target
|
||||||
names get printed when you run `bazel test :all`. For example, you can run
|
names get printed when you run `bazel test :all`. For example, you can run
|
||||||
`opt_def_use_test` with:
|
`opt_def_use_test` with:
|
||||||
|
|
||||||
on linux:
|
|
||||||
```shell
|
```shell
|
||||||
bazel test --cxxopt=-std=c++17 :opt_def_use_test
|
bazel test :opt_def_use_test
|
||||||
```
|
```
|
||||||
|
|
||||||
on windows:
|
|
||||||
```shell
|
|
||||||
bazel test --cxxopt=/std:c++17 :opt_def_use_test
|
|
||||||
```
|
|
||||||
|
|
||||||
## Future Work
|
## Future Work
|
||||||
<a name="future"></a>
|
<a name="future"></a>
|
||||||
@ -797,7 +779,6 @@ limitations under the License.
|
|||||||
[googletest-issue-610]: https://github.com/google/googletest/issues/610
|
[googletest-issue-610]: https://github.com/google/googletest/issues/610
|
||||||
[effcee]: https://github.com/google/effcee
|
[effcee]: https://github.com/google/effcee
|
||||||
[re2]: https://github.com/google/re2
|
[re2]: https://github.com/google/re2
|
||||||
[abseil-cpp]: https://github.com/abseil/abseil-cpp
|
|
||||||
[CMake]: https://cmake.org/
|
[CMake]: https://cmake.org/
|
||||||
[cpp-style-guide]: https://google.github.io/styleguide/cppguide.html
|
[cpp-style-guide]: https://google.github.io/styleguide/cppguide.html
|
||||||
[clang-sanitizers]: http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation
|
[clang-sanitizers]: http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation
|
||||||
|
13
SECURITY.md
13
SECURITY.md
@ -1,13 +0,0 @@
|
|||||||
# Security Policy
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
Security updates are applied only to the latest release.
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
|
|
||||||
|
|
||||||
Please disclose it at [security advisory](https://github.com/KhronosGroup/SPIRV-Tools/security/advisories/new).
|
|
||||||
|
|
||||||
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure.
|
|
13
WORKSPACE
13
WORKSPACE
@ -1,11 +1,3 @@
|
|||||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
|
||||||
|
|
||||||
http_archive(
|
|
||||||
name = "bazel_skylib",
|
|
||||||
strip_prefix = "bazel-skylib-main",
|
|
||||||
urls = ["https://github.com/bazelbuild/bazel-skylib/archive/main.zip"],
|
|
||||||
)
|
|
||||||
|
|
||||||
local_repository(
|
local_repository(
|
||||||
name = "spirv_headers",
|
name = "spirv_headers",
|
||||||
path = "external/spirv-headers",
|
path = "external/spirv-headers",
|
||||||
@ -25,8 +17,3 @@ local_repository(
|
|||||||
name = "com_google_effcee",
|
name = "com_google_effcee",
|
||||||
path = "external/effcee",
|
path = "external/effcee",
|
||||||
)
|
)
|
||||||
|
|
||||||
local_repository(
|
|
||||||
name = "com_google_absl",
|
|
||||||
path = "external/abseil_cpp",
|
|
||||||
)
|
|
||||||
|
@ -5,7 +5,7 @@ LOCAL_CPP_EXTENSION := .cc .cpp .cxx
|
|||||||
LOCAL_SRC_FILES:=test.cpp
|
LOCAL_SRC_FILES:=test.cpp
|
||||||
LOCAL_MODULE:=spirvtools_test
|
LOCAL_MODULE:=spirvtools_test
|
||||||
LOCAL_LDLIBS:=-landroid
|
LOCAL_LDLIBS:=-landroid
|
||||||
LOCAL_CXXFLAGS:=-std=c++17 -fno-exceptions -fno-rtti -Werror
|
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -Werror
|
||||||
LOCAL_STATIC_LIBRARIES=SPIRV-Tools SPIRV-Tools-opt
|
LOCAL_STATIC_LIBRARIES=SPIRV-Tools SPIRV-Tools-opt
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
APP_ABI := all
|
APP_ABI := all
|
||||||
APP_BUILD_SCRIPT := Android.mk
|
APP_BUILD_SCRIPT := Android.mk
|
||||||
APP_STL := c++_static
|
APP_STL := c++_static
|
||||||
APP_PLATFORM := android-24
|
APP_PLATFORM := android-9
|
||||||
NDK_TOOLCHAIN_VERSION := 4.9
|
NDK_TOOLCHAIN_VERSION := 4.9
|
||||||
|
426
build_defs.bzl
426
build_defs.bzl
@ -1,21 +1,20 @@
|
|||||||
"""Constants and macros for spirv-tools BUILD."""
|
|
||||||
|
|
||||||
COMMON_COPTS = [
|
COMMON_COPTS = [
|
||||||
"-DSPIRV_CHECK_CONTEXT",
|
"-DSPIRV_CHECK_CONTEXT",
|
||||||
"-DSPIRV_COLOR_TERMINAL",
|
"-DSPIRV_COLOR_TERMINAL",
|
||||||
] + select({
|
] + select({
|
||||||
"@platforms//os:windows": [],
|
"@bazel_tools//src/conditions:windows": [""],
|
||||||
"//conditions:default": [
|
"//conditions:default": [
|
||||||
"-DSPIRV_LINUX",
|
"-DSPIRV_LINUX",
|
||||||
"-DSPIRV_TIMER_ENABLED",
|
"-DSPIRV_TIMER_ENABLED",
|
||||||
"-fvisibility=hidden",
|
|
||||||
"-fno-exceptions",
|
|
||||||
"-fno-rtti",
|
|
||||||
"-Wall",
|
"-Wall",
|
||||||
"-Wextra",
|
"-Wextra",
|
||||||
"-Wnon-virtual-dtor",
|
"-Wnon-virtual-dtor",
|
||||||
"-Wno-missing-field-initializers",
|
"-Wno-missing-field-initializers",
|
||||||
"-Werror",
|
"-Werror",
|
||||||
|
"-std=c++11",
|
||||||
|
"-fvisibility=hidden",
|
||||||
|
"-fno-exceptions",
|
||||||
|
"-fno-rtti",
|
||||||
"-Wno-long-long",
|
"-Wno-long-long",
|
||||||
"-Wshadow",
|
"-Wshadow",
|
||||||
"-Wundef",
|
"-Wundef",
|
||||||
@ -24,211 +23,324 @@ COMMON_COPTS = [
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
TEST_COPTS = COMMON_COPTS + [
|
TEST_COPTS = COMMON_COPTS + select({
|
||||||
] + select({
|
"@bazel_tools//src/conditions:windows": [
|
||||||
"@platforms//os:windows": [
|
|
||||||
# Disable C4503 "decorated name length exceeded" warning,
|
# Disable C4503 "decorated name length exceeded" warning,
|
||||||
# triggered by some heavily templated types.
|
# triggered by some heavily templated types.
|
||||||
# We don't care much about that in test code.
|
# We don't care much about that in test code.
|
||||||
# Important to do since we have warnings-as-errors.
|
# Important to do since we have warnings-as-errors.
|
||||||
"/wd4503",
|
"/wd4503"
|
||||||
],
|
],
|
||||||
"//conditions:default": [
|
"//conditions:default": [
|
||||||
"-Wno-undef",
|
"-Wno-undef",
|
||||||
"-Wno-self-assign",
|
"-Wno-self-assign",
|
||||||
"-Wno-shadow",
|
"-Wno-shadow",
|
||||||
"-Wno-unused-parameter",
|
"-Wno-unused-parameter"
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
def incompatible_with(incompatible_constraints):
|
|
||||||
return select(_merge_dicts([{"//conditions:default": []}, {
|
|
||||||
constraint: ["@platforms//:incompatible"]
|
|
||||||
for constraint in incompatible_constraints
|
|
||||||
}]))
|
|
||||||
|
|
||||||
DEBUGINFO_GRAMMAR_JSON_FILE = "@spirv_headers//:spirv_ext_inst_debuginfo_grammar_unified1"
|
DEBUGINFO_GRAMMAR_JSON_FILE = "@spirv_headers//:spirv_ext_inst_debuginfo_grammar_unified1"
|
||||||
CLDEBUGINFO100_GRAMMAR_JSON_FILE = "@spirv_headers//:spirv_ext_inst_opencl_debuginfo_100_grammar_unified1"
|
CLDEBUGINFO100_GRAMMAR_JSON_FILE = "@spirv_headers//:spirv_ext_inst_opencl_debuginfo_100_grammar_unified1"
|
||||||
SHDEBUGINFO100_GRAMMAR_JSON_FILE = "@spirv_headers//:spirv_ext_inst_nonsemantic_shader_debuginfo_100_grammar_unified1"
|
SHDEBUGINFO100_GRAMMAR_JSON_FILE = "@spirv_headers//:spirv_ext_inst_nonsemantic_shader_debuginfo_100_grammar_unified1"
|
||||||
|
|
||||||
def _merge_dicts(dicts):
|
def generate_core_tables(version = None):
|
||||||
merged = {}
|
|
||||||
for d in dicts:
|
|
||||||
merged.update(d)
|
|
||||||
return merged
|
|
||||||
|
|
||||||
def generate_core_tables(version):
|
|
||||||
if not version:
|
if not version:
|
||||||
fail("Must specify version", "version")
|
fail("Must specify version", "version")
|
||||||
|
grammars = [
|
||||||
grammars = dict(
|
"@spirv_headers//:spirv_core_grammar_" + version,
|
||||||
core_grammar = "@spirv_headers//:spirv_core_grammar_{}".format(version),
|
DEBUGINFO_GRAMMAR_JSON_FILE,
|
||||||
debuginfo_grammar = DEBUGINFO_GRAMMAR_JSON_FILE,
|
CLDEBUGINFO100_GRAMMAR_JSON_FILE,
|
||||||
cldebuginfo_grammar = CLDEBUGINFO100_GRAMMAR_JSON_FILE,
|
]
|
||||||
)
|
outs = [
|
||||||
|
"core.insts-{}.inc".format(version),
|
||||||
outs = dict(
|
"operand.kinds-{}.inc".format(version),
|
||||||
core_insts_output = "core.insts-{}.inc".format(version),
|
]
|
||||||
operand_kinds_output = "operand.kinds-{}.inc".format(version),
|
fmtargs = grammars + outs
|
||||||
)
|
|
||||||
|
|
||||||
cmd = (
|
|
||||||
"$(location :generate_grammar_tables)" +
|
|
||||||
" --spirv-core-grammar=$(location {core_grammar})" +
|
|
||||||
" --extinst-debuginfo-grammar=$(location {debuginfo_grammar})" +
|
|
||||||
" --extinst-cldebuginfo100-grammar=$(location {cldebuginfo_grammar})" +
|
|
||||||
" --core-insts-output=$(location {core_insts_output})" +
|
|
||||||
" --operand-kinds-output=$(location {operand_kinds_output})" +
|
|
||||||
" --output-language=c++"
|
|
||||||
).format(**_merge_dicts([grammars, outs]))
|
|
||||||
|
|
||||||
native.genrule(
|
native.genrule(
|
||||||
name = "gen_core_tables_" + version,
|
name = "gen_core_tables_" + version,
|
||||||
srcs = grammars.values(),
|
srcs = grammars,
|
||||||
outs = outs.values(),
|
outs = outs,
|
||||||
cmd = cmd,
|
cmd = (
|
||||||
cmd_bat = cmd,
|
"$(location :generate_grammar_tables) " +
|
||||||
tools = [":generate_grammar_tables"],
|
"--spirv-core-grammar=$(location {0}) " +
|
||||||
|
"--extinst-debuginfo-grammar=$(location {1}) " +
|
||||||
|
"--extinst-cldebuginfo100-grammar=$(location {2}) " +
|
||||||
|
"--core-insts-output=$(location {3}) " +
|
||||||
|
"--operand-kinds-output=$(location {4})"
|
||||||
|
).format(*fmtargs),
|
||||||
|
cmd_bat = (
|
||||||
|
"$(location :generate_grammar_tables) " +
|
||||||
|
"--spirv-core-grammar=$(location {0}) " +
|
||||||
|
"--extinst-debuginfo-grammar=$(location {1}) " +
|
||||||
|
"--extinst-cldebuginfo100-grammar=$(location {2}) " +
|
||||||
|
"--core-insts-output=$(location {3}) " +
|
||||||
|
"--operand-kinds-output=$(location {4})"
|
||||||
|
).format(*fmtargs),
|
||||||
|
exec_tools = [":generate_grammar_tables"],
|
||||||
visibility = ["//visibility:private"],
|
visibility = ["//visibility:private"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_enum_string_mapping(version):
|
def generate_enum_string_mapping(version = None):
|
||||||
if not version:
|
if not version:
|
||||||
fail("Must specify version", "version")
|
fail("Must specify version", "version")
|
||||||
|
grammars = [
|
||||||
grammars = dict(
|
"@spirv_headers//:spirv_core_grammar_" + version,
|
||||||
core_grammar = "@spirv_headers//:spirv_core_grammar_{}".format(version),
|
DEBUGINFO_GRAMMAR_JSON_FILE,
|
||||||
debuginfo_grammar = DEBUGINFO_GRAMMAR_JSON_FILE,
|
CLDEBUGINFO100_GRAMMAR_JSON_FILE,
|
||||||
cldebuginfo_grammar = CLDEBUGINFO100_GRAMMAR_JSON_FILE,
|
]
|
||||||
)
|
outs = [
|
||||||
|
"extension_enum.inc",
|
||||||
outs = dict(
|
"enum_string_mapping.inc",
|
||||||
extension_enum_ouput = "extension_enum.inc",
|
]
|
||||||
enum_string_mapping_output = "enum_string_mapping.inc",
|
fmtargs = grammars + outs
|
||||||
)
|
|
||||||
|
|
||||||
cmd = (
|
|
||||||
"$(location :generate_grammar_tables)" +
|
|
||||||
" --spirv-core-grammar=$(location {core_grammar})" +
|
|
||||||
" --extinst-debuginfo-grammar=$(location {debuginfo_grammar})" +
|
|
||||||
" --extinst-cldebuginfo100-grammar=$(location {cldebuginfo_grammar})" +
|
|
||||||
" --extension-enum-output=$(location {extension_enum_ouput})" +
|
|
||||||
" --enum-string-mapping-output=$(location {enum_string_mapping_output})" +
|
|
||||||
" --output-language=c++"
|
|
||||||
).format(**_merge_dicts([grammars, outs]))
|
|
||||||
|
|
||||||
native.genrule(
|
native.genrule(
|
||||||
name = "gen_enum_string_mapping",
|
name = "gen_enum_string_mapping",
|
||||||
srcs = grammars.values(),
|
srcs = grammars,
|
||||||
outs = outs.values(),
|
outs = outs,
|
||||||
cmd = cmd,
|
cmd = (
|
||||||
cmd_bat = cmd,
|
"$(location :generate_grammar_tables) " +
|
||||||
tools = [":generate_grammar_tables"],
|
"--spirv-core-grammar=$(location {0}) " +
|
||||||
|
"--extinst-debuginfo-grammar=$(location {1}) " +
|
||||||
|
"--extinst-cldebuginfo100-grammar=$(location {2}) " +
|
||||||
|
"--extension-enum-output=$(location {3}) " +
|
||||||
|
"--enum-string-mapping-output=$(location {4})"
|
||||||
|
).format(*fmtargs),
|
||||||
|
cmd_bat = (
|
||||||
|
"$(location :generate_grammar_tables) " +
|
||||||
|
"--spirv-core-grammar=$(location {0}) " +
|
||||||
|
"--extinst-debuginfo-grammar=$(location {1}) " +
|
||||||
|
"--extinst-cldebuginfo100-grammar=$(location {2}) " +
|
||||||
|
"--extension-enum-output=$(location {3}) " +
|
||||||
|
"--enum-string-mapping-output=$(location {4})"
|
||||||
|
).format(*fmtargs),
|
||||||
|
exec_tools = [":generate_grammar_tables"],
|
||||||
visibility = ["//visibility:private"],
|
visibility = ["//visibility:private"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_opencl_tables(version):
|
def generate_opencl_tables(version = None):
|
||||||
if not version:
|
if not version:
|
||||||
fail("Must specify version", "version")
|
fail("Must specify version", "version")
|
||||||
|
grammars = [
|
||||||
grammars = dict(
|
"@spirv_headers//:spirv_opencl_grammar_" + version,
|
||||||
opencl_grammar = "@spirv_headers//:spirv_opencl_grammar_{}".format(version),
|
]
|
||||||
)
|
outs = ["opencl.std.insts.inc"]
|
||||||
|
fmtargs = grammars + outs
|
||||||
outs = dict(
|
|
||||||
opencl_insts_output = "opencl.std.insts.inc",
|
|
||||||
)
|
|
||||||
|
|
||||||
cmd = (
|
|
||||||
"$(location :generate_grammar_tables)" +
|
|
||||||
" --extinst-opencl-grammar=$(location {opencl_grammar})" +
|
|
||||||
" --opencl-insts-output=$(location {opencl_insts_output})"
|
|
||||||
).format(**_merge_dicts([grammars, outs]))
|
|
||||||
|
|
||||||
native.genrule(
|
native.genrule(
|
||||||
name = "gen_opencl_tables_" + version,
|
name = "gen_opencl_tables_" + version,
|
||||||
srcs = grammars.values(),
|
srcs = grammars,
|
||||||
outs = outs.values(),
|
outs = outs,
|
||||||
cmd = cmd,
|
cmd = (
|
||||||
cmd_bat = cmd,
|
"$(location :generate_grammar_tables) " +
|
||||||
tools = [":generate_grammar_tables"],
|
"--extinst-opencl-grammar=$(location {0}) " +
|
||||||
|
"--opencl-insts-output=$(location {1})"
|
||||||
|
).format(*fmtargs),
|
||||||
|
cmd_bat = (
|
||||||
|
"$(location :generate_grammar_tables) " +
|
||||||
|
"--extinst-opencl-grammar=$(location {0}) " +
|
||||||
|
"--opencl-insts-output=$(location {1})"
|
||||||
|
).format(*fmtargs),
|
||||||
|
exec_tools = [":generate_grammar_tables"],
|
||||||
visibility = ["//visibility:private"],
|
visibility = ["//visibility:private"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_glsl_tables(version):
|
def generate_glsl_tables(version = None):
|
||||||
if not version:
|
if not version:
|
||||||
fail("Must specify version", "version")
|
fail("Must specify version", "version")
|
||||||
|
grammars = [
|
||||||
grammars = dict(
|
"@spirv_headers//:spirv_glsl_grammar_" + version,
|
||||||
gsls_grammar = "@spirv_headers//:spirv_glsl_grammar_{}".format(version),
|
]
|
||||||
)
|
outs = ["glsl.std.450.insts.inc"]
|
||||||
outs = dict(
|
fmtargs = grammars + outs
|
||||||
gsls_insts_outs = "glsl.std.450.insts.inc",
|
|
||||||
)
|
|
||||||
|
|
||||||
cmd = (
|
|
||||||
"$(location :generate_grammar_tables)" +
|
|
||||||
" --extinst-glsl-grammar=$(location {gsls_grammar})" +
|
|
||||||
" --glsl-insts-output=$(location {gsls_insts_outs})" +
|
|
||||||
" --output-language=c++"
|
|
||||||
).format(**_merge_dicts([grammars, outs]))
|
|
||||||
|
|
||||||
native.genrule(
|
native.genrule(
|
||||||
name = "gen_glsl_tables_" + version,
|
name = "gen_glsl_tables_" + version,
|
||||||
srcs = grammars.values(),
|
srcs = grammars,
|
||||||
outs = outs.values(),
|
outs = outs,
|
||||||
cmd = cmd,
|
cmd = (
|
||||||
cmd_bat = cmd,
|
"$(location :generate_grammar_tables) " +
|
||||||
tools = [":generate_grammar_tables"],
|
"--extinst-glsl-grammar=$(location {0}) " +
|
||||||
|
"--glsl-insts-output=$(location {1})"
|
||||||
|
).format(*fmtargs),
|
||||||
|
cmd_bat = (
|
||||||
|
"$(location :generate_grammar_tables) " +
|
||||||
|
"--extinst-glsl-grammar=$(location {0}) " +
|
||||||
|
"--glsl-insts-output=$(location {1})"
|
||||||
|
).format(*fmtargs),
|
||||||
|
exec_tools = [":generate_grammar_tables"],
|
||||||
visibility = ["//visibility:private"],
|
visibility = ["//visibility:private"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_vendor_tables(extension, operand_kind_prefix = ""):
|
def generate_vendor_tables(extension, operand_kind_prefix = ""):
|
||||||
if not extension:
|
if not extension:
|
||||||
fail("Must specify extension", "extension")
|
fail("Must specify extension", "extension")
|
||||||
|
|
||||||
extension_rule = extension.replace("-", "_").replace(".", "_")
|
extension_rule = extension.replace("-", "_").replace(".", "_")
|
||||||
grammars = dict(
|
grammars = ["@spirv_headers//:spirv_ext_inst_{}_grammar_unified1".format(extension_rule)]
|
||||||
vendor_grammar = "@spirv_headers//:spirv_ext_inst_{}_grammar_unified1".format(extension_rule),
|
outs = ["{}.insts.inc".format(extension)]
|
||||||
)
|
prefices = [operand_kind_prefix]
|
||||||
outs = dict(
|
fmtargs = grammars + outs + prefices
|
||||||
vendor_insts_output = "{}.insts.inc".format(extension),
|
|
||||||
)
|
|
||||||
cmd = (
|
|
||||||
"$(location :generate_grammar_tables)" +
|
|
||||||
" --extinst-vendor-grammar=$(location {vendor_grammar})" +
|
|
||||||
" --vendor-insts-output=$(location {vendor_insts_output})" +
|
|
||||||
" --vendor-operand-kind-prefix={operand_kind_prefix}"
|
|
||||||
).format(operand_kind_prefix = operand_kind_prefix, **_merge_dicts([grammars, outs]))
|
|
||||||
|
|
||||||
native.genrule(
|
native.genrule(
|
||||||
name = "gen_vendor_tables_" + extension_rule,
|
name = "gen_vendor_tables_" + extension_rule,
|
||||||
srcs = grammars.values(),
|
srcs = grammars,
|
||||||
outs = outs.values(),
|
outs = outs,
|
||||||
cmd = cmd,
|
cmd = (
|
||||||
cmd_bat = cmd,
|
"$(location :generate_grammar_tables) " +
|
||||||
tools = [":generate_grammar_tables"],
|
"--extinst-vendor-grammar=$(location {0}) " +
|
||||||
|
"--vendor-insts-output=$(location {1}) " +
|
||||||
|
"--vendor-operand-kind-prefix={2}"
|
||||||
|
).format(*fmtargs),
|
||||||
|
cmd_bat = (
|
||||||
|
"$(location :generate_grammar_tables) " +
|
||||||
|
"--extinst-vendor-grammar=$(location {0}) " +
|
||||||
|
"--vendor-insts-output=$(location {1}) " +
|
||||||
|
"--vendor-operand-kind-prefix={2}"
|
||||||
|
).format(*fmtargs),
|
||||||
|
exec_tools = [":generate_grammar_tables"],
|
||||||
visibility = ["//visibility:private"],
|
visibility = ["//visibility:private"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_extinst_lang_headers(name, grammar = None):
|
def generate_extinst_lang_headers(name, grammar = None):
|
||||||
if not grammar:
|
if not grammar:
|
||||||
fail("Must specify grammar", "grammar")
|
fail("Must specify grammar", "grammar")
|
||||||
outs = dict(
|
outs = [name + ".h"]
|
||||||
extinst_output_path = name + ".h",
|
fmtargs = outs
|
||||||
)
|
|
||||||
cmd = (
|
|
||||||
"$(location :generate_language_headers)" +
|
|
||||||
" --extinst-grammar=$<" +
|
|
||||||
" --extinst-output-path=$(location {extinst_output_path})"
|
|
||||||
).format(**outs)
|
|
||||||
|
|
||||||
native.genrule(
|
native.genrule(
|
||||||
name = "gen_extinst_lang_headers_{}".format(name),
|
name = "gen_extinst_lang_headers_" + name,
|
||||||
srcs = [grammar],
|
srcs = [grammar],
|
||||||
outs = outs.values(),
|
outs = outs,
|
||||||
cmd = cmd,
|
cmd = (
|
||||||
cmd_bat = cmd,
|
"$(location :generate_language_headers) " +
|
||||||
tools = [":generate_language_headers"],
|
"--extinst-grammar=$< " +
|
||||||
|
"--extinst-output-path=$(location {0})"
|
||||||
|
).format(*fmtargs),
|
||||||
|
cmd_bat = (
|
||||||
|
"$(location :generate_language_headers) " +
|
||||||
|
"--extinst-grammar=$< " +
|
||||||
|
"--extinst-output-path=$(location {0})"
|
||||||
|
).format(*fmtargs),
|
||||||
|
exec_tools = [":generate_language_headers"],
|
||||||
visibility = ["//visibility:private"],
|
visibility = ["//visibility:private"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def base_test(name, srcs, deps = []):
|
||||||
|
if srcs == []:
|
||||||
|
return
|
||||||
|
if name[-5:] != "_test":
|
||||||
|
name = name + "_test"
|
||||||
|
native.cc_test(
|
||||||
|
name = "base_" + name,
|
||||||
|
srcs = srcs,
|
||||||
|
compatible_with = [],
|
||||||
|
copts = TEST_COPTS,
|
||||||
|
size = "large",
|
||||||
|
deps = [
|
||||||
|
":test_common",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
"@com_google_googletest//:gtest",
|
||||||
|
"@com_google_effcee//:effcee",
|
||||||
|
] + deps,
|
||||||
|
)
|
||||||
|
|
||||||
|
def lint_test(name, srcs, deps = []):
|
||||||
|
if name[-5:] != "_test":
|
||||||
|
name = name + "_test"
|
||||||
|
native.cc_test(
|
||||||
|
name = "lint_" + name,
|
||||||
|
srcs = srcs,
|
||||||
|
compatible_with = [],
|
||||||
|
copts = TEST_COPTS,
|
||||||
|
size = "large",
|
||||||
|
deps = [
|
||||||
|
":spirv_tools_lint",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
"@com_google_googletest//:gtest",
|
||||||
|
"@com_google_effcee//:effcee",
|
||||||
|
] + deps,
|
||||||
|
)
|
||||||
|
|
||||||
|
def link_test(name, srcs, deps = []):
|
||||||
|
if name[-5:] != "_test":
|
||||||
|
name = name + "_test"
|
||||||
|
native.cc_test(
|
||||||
|
name = "link_" + name,
|
||||||
|
srcs = srcs,
|
||||||
|
compatible_with = [],
|
||||||
|
copts = TEST_COPTS,
|
||||||
|
size = "large",
|
||||||
|
deps = [
|
||||||
|
":link_test_common",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
"@com_google_googletest//:gtest",
|
||||||
|
"@com_google_effcee//:effcee",
|
||||||
|
] + deps,
|
||||||
|
)
|
||||||
|
|
||||||
|
def opt_test(name, srcs, deps = []):
|
||||||
|
if name[-5:] != "_test":
|
||||||
|
name = name + "_test"
|
||||||
|
native.cc_test(
|
||||||
|
name = "opt_" + name,
|
||||||
|
srcs = srcs,
|
||||||
|
compatible_with = [],
|
||||||
|
copts = TEST_COPTS,
|
||||||
|
size = "large",
|
||||||
|
deps = [
|
||||||
|
":opt_test_common",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
"@com_google_googletest//:gtest",
|
||||||
|
"@com_google_effcee//:effcee",
|
||||||
|
] + deps,
|
||||||
|
)
|
||||||
|
|
||||||
|
def reduce_test(name, srcs, deps = []):
|
||||||
|
if name[-5:] != "_test":
|
||||||
|
name = name + "_test"
|
||||||
|
native.cc_test(
|
||||||
|
name = "reduce_" + name,
|
||||||
|
srcs = srcs,
|
||||||
|
compatible_with = [],
|
||||||
|
copts = TEST_COPTS,
|
||||||
|
size = "large",
|
||||||
|
deps = [
|
||||||
|
":reduce_test_common",
|
||||||
|
":spirv_tools_reduce",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
"@com_google_googletest//:gtest",
|
||||||
|
"@com_google_effcee//:effcee",
|
||||||
|
] + deps,
|
||||||
|
)
|
||||||
|
|
||||||
|
def util_test(name, srcs, deps = []):
|
||||||
|
if name[-5:] != "_test":
|
||||||
|
name = name + "_test"
|
||||||
|
native.cc_test(
|
||||||
|
name = "util_" + name,
|
||||||
|
srcs = srcs,
|
||||||
|
compatible_with = [],
|
||||||
|
copts = TEST_COPTS,
|
||||||
|
size = "large",
|
||||||
|
deps = [
|
||||||
|
":opt_test_common",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
"@com_google_googletest//:gtest",
|
||||||
|
"@com_google_effcee//:effcee",
|
||||||
|
] + deps,
|
||||||
|
)
|
||||||
|
|
||||||
|
def val_test(name, srcs = [], copts = [], deps = [], **kwargs):
|
||||||
|
if name[-5:] != "_test":
|
||||||
|
name = name + "_test"
|
||||||
|
if name[:4] != "val_":
|
||||||
|
name = "val_" + name
|
||||||
|
native.cc_test(
|
||||||
|
name = name,
|
||||||
|
srcs = srcs,
|
||||||
|
compatible_with = [],
|
||||||
|
copts = TEST_COPTS + copts,
|
||||||
|
size = "large",
|
||||||
|
deps = [
|
||||||
|
":val_test_common",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
"@com_google_googletest//:gtest",
|
||||||
|
"@com_google_effcee//:effcee",
|
||||||
|
] + deps,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
0
docker-compose.yml
Executable file → Normal file
0
docker-compose.yml
Executable file → Normal file
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Latest builds
|
## Latest builds
|
||||||
|
|
||||||
Download the latest builds of the [main](https://github.com/KhronosGroup/SPIRV-Tools/tree/main) branch.
|
Download the latest builds of the [master](https://github.com/KhronosGroup/SPIRV-Tools/tree/master) branch.
|
||||||
|
|
||||||
### Release build
|
### Release build
|
||||||
| Windows | Linux | MacOS |
|
| Windows | Linux | MacOS |
|
||||||
|
@ -34,7 +34,7 @@ through the project workflow:
|
|||||||
ones.
|
ones.
|
||||||
* They determine if the work for a card has been completed.
|
* They determine if the work for a card has been completed.
|
||||||
* Normally they are the person (or persons) who can approve and merge a pull
|
* Normally they are the person (or persons) who can approve and merge a pull
|
||||||
request into the `main` branch.
|
request into the `master` branch.
|
||||||
|
|
||||||
Our projects organize cards into the following columns:
|
Our projects organize cards into the following columns:
|
||||||
* `Ideas`: Work which could be done, captured either as Cards or Notes.
|
* `Ideas`: Work which could be done, captured either as Cards or Notes.
|
||||||
@ -51,7 +51,7 @@ Our projects organize cards into the following columns:
|
|||||||
claimed by someone.
|
claimed by someone.
|
||||||
* `Done`: Issues which have been resolved, by completing their work.
|
* `Done`: Issues which have been resolved, by completing their work.
|
||||||
* The changes have been applied to the repository, typically by being pushed
|
* The changes have been applied to the repository, typically by being pushed
|
||||||
into the `main` branch.
|
into the `master` branch.
|
||||||
* Other kinds of work could update repository settings, for example.
|
* Other kinds of work could update repository settings, for example.
|
||||||
* `Rejected ideas`: Work which has been considered, but which we don't want
|
* `Rejected ideas`: Work which has been considered, but which we don't want
|
||||||
implemented.
|
implemented.
|
||||||
|
28
external/CMakeLists.txt
vendored
28
external/CMakeLists.txt
vendored
@ -30,7 +30,11 @@ if (DEFINED SPIRV-Headers_SOURCE_DIR)
|
|||||||
# This allows flexible position of the SPIRV-Headers repo.
|
# This allows flexible position of the SPIRV-Headers repo.
|
||||||
set(SPIRV_HEADER_DIR ${SPIRV-Headers_SOURCE_DIR})
|
set(SPIRV_HEADER_DIR ${SPIRV-Headers_SOURCE_DIR})
|
||||||
else()
|
else()
|
||||||
set(SPIRV_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/spirv-headers)
|
if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/SPIRV-Headers)
|
||||||
|
set(SPIRV_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SPIRV-Headers)
|
||||||
|
else()
|
||||||
|
set(SPIRV_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/spirv-headers)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (IS_DIRECTORY ${SPIRV_HEADER_DIR})
|
if (IS_DIRECTORY ${SPIRV_HEADER_DIR})
|
||||||
@ -41,6 +45,8 @@ if (IS_DIRECTORY ${SPIRV_HEADER_DIR})
|
|||||||
# Do this so enclosing projects can use SPIRV-Headers_SOURCE_DIR to find
|
# Do this so enclosing projects can use SPIRV-Headers_SOURCE_DIR to find
|
||||||
# headers to include.
|
# headers to include.
|
||||||
if (NOT DEFINED SPIRV-Headers_SOURCE_DIR)
|
if (NOT DEFINED SPIRV-Headers_SOURCE_DIR)
|
||||||
|
set(SPIRV_HEADERS_SKIP_INSTALL ON)
|
||||||
|
set(SPIRV_HEADERS_SKIP_EXAMPLES ON)
|
||||||
add_subdirectory(${SPIRV_HEADER_DIR})
|
add_subdirectory(${SPIRV_HEADER_DIR})
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
@ -54,9 +60,7 @@ if (NOT ${SPIRV_SKIP_TESTS})
|
|||||||
if (TARGET gmock)
|
if (TARGET gmock)
|
||||||
message(STATUS "Google Mock already configured")
|
message(STATUS "Google Mock already configured")
|
||||||
else()
|
else()
|
||||||
if (NOT GMOCK_DIR)
|
set(GMOCK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/googletest)
|
||||||
set(GMOCK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/googletest)
|
|
||||||
endif()
|
|
||||||
if(EXISTS ${GMOCK_DIR})
|
if(EXISTS ${GMOCK_DIR})
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# Our tests use ::testing::Combine. Work around a compiler
|
# Our tests use ::testing::Combine. Work around a compiler
|
||||||
@ -73,7 +77,7 @@ if (NOT ${SPIRV_SKIP_TESTS})
|
|||||||
# gtest requires special defines for building as a shared
|
# gtest requires special defines for building as a shared
|
||||||
# library, simply always build as static.
|
# library, simply always build as static.
|
||||||
push_variable(BUILD_SHARED_LIBS 0)
|
push_variable(BUILD_SHARED_LIBS 0)
|
||||||
add_subdirectory(${GMOCK_DIR} ${CMAKE_CURRENT_BINARY_DIR}/googletest EXCLUDE_FROM_ALL)
|
add_subdirectory(${GMOCK_DIR} EXCLUDE_FROM_ALL)
|
||||||
pop_variable(BUILD_SHARED_LIBS)
|
pop_variable(BUILD_SHARED_LIBS)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@ -91,22 +95,10 @@ if (NOT ${SPIRV_SKIP_TESTS})
|
|||||||
|
|
||||||
# Find Effcee and RE2, for testing.
|
# Find Effcee and RE2, for testing.
|
||||||
|
|
||||||
# RE2 depends on Abseil. We set absl_SOURCE_DIR if it is not already set, so
|
|
||||||
# that effcee can find abseil.
|
|
||||||
if(NOT TARGET absl::base)
|
|
||||||
if (NOT absl_SOURCE_DIR)
|
|
||||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/abseil_cpp)
|
|
||||||
set(absl_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/abseil_cpp" CACHE STRING "Abseil source dir" )
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# First find RE2, since Effcee depends on it.
|
# First find RE2, since Effcee depends on it.
|
||||||
# If already configured, then use that. Otherwise, prefer to find it under 're2'
|
# If already configured, then use that. Otherwise, prefer to find it under 're2'
|
||||||
# in this directory.
|
# in this directory.
|
||||||
if (NOT TARGET re2)
|
if (NOT TARGET re2)
|
||||||
|
|
||||||
|
|
||||||
# If we are configuring RE2, then turn off its testing. It takes a long time and
|
# If we are configuring RE2, then turn off its testing. It takes a long time and
|
||||||
# does not add much value for us. If an enclosing project configured RE2, then it
|
# does not add much value for us. If an enclosing project configured RE2, then it
|
||||||
# has already chosen whether to enable RE2 testing.
|
# has already chosen whether to enable RE2 testing.
|
||||||
@ -164,7 +156,7 @@ if(SPIRV_BUILD_FUZZER)
|
|||||||
|
|
||||||
if(NOT TARGET protobuf::libprotobuf OR NOT TARGET protobuf::protoc)
|
if(NOT TARGET protobuf::libprotobuf OR NOT TARGET protobuf::protoc)
|
||||||
|
|
||||||
set(SPIRV_TOOLS_PROTOBUF_DIR ${CMAKE_CURRENT_SOURCE_DIR}/protobuf)
|
set(SPIRV_TOOLS_PROTOBUF_DIR ${CMAKE_CURRENT_SOURCE_DIR}/protobuf/cmake)
|
||||||
if (NOT IS_DIRECTORY ${SPIRV_TOOLS_PROTOBUF_DIR})
|
if (NOT IS_DIRECTORY ${SPIRV_TOOLS_PROTOBUF_DIR})
|
||||||
message(
|
message(
|
||||||
FATAL_ERROR
|
FATAL_ERROR
|
||||||
|
@ -36,25 +36,16 @@ namespace spvtools {
|
|||||||
// generated by InstrumentPass::GenDebugStreamWrite. This method is utilized
|
// generated by InstrumentPass::GenDebugStreamWrite. This method is utilized
|
||||||
// by InstBindlessCheckPass, InstBuffAddrCheckPass, and InstDebugPrintfPass.
|
// by InstBindlessCheckPass, InstBuffAddrCheckPass, and InstDebugPrintfPass.
|
||||||
//
|
//
|
||||||
// The 1st member of the debug output buffer contains a set of flags
|
// The first member of the debug output buffer contains the next available word
|
||||||
// controlling the behavior of instrumentation code.
|
|
||||||
static const int kDebugOutputFlagsOffset = 0;
|
|
||||||
|
|
||||||
// Values stored at kDebugOutputFlagsOffset
|
|
||||||
enum kInstFlags : unsigned int {
|
|
||||||
kInstBufferOOBEnable = 0x1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// The 2nd member of the debug output buffer contains the next available word
|
|
||||||
// in the data stream to be written. Shaders will atomically read and update
|
// in the data stream to be written. Shaders will atomically read and update
|
||||||
// this value so as not to overwrite each others records. This value must be
|
// this value so as not to overwrite each others records. This value must be
|
||||||
// initialized to zero
|
// initialized to zero
|
||||||
static const int kDebugOutputSizeOffset = 1;
|
static const int kDebugOutputSizeOffset = 0;
|
||||||
|
|
||||||
// The 3rd member of the output buffer is the start of the stream of records
|
// The second member of the output buffer is the start of the stream of records
|
||||||
// written by the instrumented shaders. Each record represents a validation
|
// written by the instrumented shaders. Each record represents a validation
|
||||||
// error. The format of the records is documented below.
|
// error. The format of the records is documented below.
|
||||||
static const int kDebugOutputDataOffset = 2;
|
static const int kDebugOutputDataOffset = 1;
|
||||||
|
|
||||||
// Common Stream Record Offsets
|
// Common Stream Record Offsets
|
||||||
//
|
//
|
||||||
@ -73,14 +64,196 @@ static const int kInstCommonOutShaderId = 1;
|
|||||||
// which generated the validation error.
|
// which generated the validation error.
|
||||||
static const int kInstCommonOutInstructionIdx = 2;
|
static const int kInstCommonOutInstructionIdx = 2;
|
||||||
|
|
||||||
|
// This is the stage which generated the validation error. This word is used
|
||||||
|
// to determine the contents of the next two words in the record.
|
||||||
|
// 0:Vert, 1:TessCtrl, 2:TessEval, 3:Geom, 4:Frag, 5:Compute
|
||||||
|
static const int kInstCommonOutStageIdx = 3;
|
||||||
|
static const int kInstCommonOutCnt = 4;
|
||||||
|
|
||||||
|
// Stage-specific Stream Record Offsets
|
||||||
|
//
|
||||||
|
// Each stage will contain different values in the next set of words of the
|
||||||
|
// record used to identify which instantiation of the shader generated the
|
||||||
|
// validation error.
|
||||||
|
//
|
||||||
|
// Vertex Shader Output Record Offsets
|
||||||
|
static const int kInstVertOutVertexIndex = kInstCommonOutCnt;
|
||||||
|
static const int kInstVertOutInstanceIndex = kInstCommonOutCnt + 1;
|
||||||
|
static const int kInstVertOutUnused = kInstCommonOutCnt + 2;
|
||||||
|
|
||||||
|
// Frag Shader Output Record Offsets
|
||||||
|
static const int kInstFragOutFragCoordX = kInstCommonOutCnt;
|
||||||
|
static const int kInstFragOutFragCoordY = kInstCommonOutCnt + 1;
|
||||||
|
static const int kInstFragOutUnused = kInstCommonOutCnt + 2;
|
||||||
|
|
||||||
|
// Compute Shader Output Record Offsets
|
||||||
|
static const int kInstCompOutGlobalInvocationIdX = kInstCommonOutCnt;
|
||||||
|
static const int kInstCompOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
|
||||||
|
static const int kInstCompOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
|
||||||
|
|
||||||
|
// Tessellation Control Shader Output Record Offsets
|
||||||
|
static const int kInstTessCtlOutInvocationId = kInstCommonOutCnt;
|
||||||
|
static const int kInstTessCtlOutPrimitiveId = kInstCommonOutCnt + 1;
|
||||||
|
static const int kInstTessCtlOutUnused = kInstCommonOutCnt + 2;
|
||||||
|
|
||||||
|
// Tessellation Eval Shader Output Record Offsets
|
||||||
|
static const int kInstTessEvalOutPrimitiveId = kInstCommonOutCnt;
|
||||||
|
static const int kInstTessEvalOutTessCoordU = kInstCommonOutCnt + 1;
|
||||||
|
static const int kInstTessEvalOutTessCoordV = kInstCommonOutCnt + 2;
|
||||||
|
|
||||||
|
// Geometry Shader Output Record Offsets
|
||||||
|
static const int kInstGeomOutPrimitiveId = kInstCommonOutCnt;
|
||||||
|
static const int kInstGeomOutInvocationId = kInstCommonOutCnt + 1;
|
||||||
|
static const int kInstGeomOutUnused = kInstCommonOutCnt + 2;
|
||||||
|
|
||||||
|
// Ray Tracing Shader Output Record Offsets
|
||||||
|
static const int kInstRayTracingOutLaunchIdX = kInstCommonOutCnt;
|
||||||
|
static const int kInstRayTracingOutLaunchIdY = kInstCommonOutCnt + 1;
|
||||||
|
static const int kInstRayTracingOutLaunchIdZ = kInstCommonOutCnt + 2;
|
||||||
|
|
||||||
|
// Mesh Shader Output Record Offsets
|
||||||
|
static const int kInstMeshOutGlobalInvocationIdX = kInstCommonOutCnt;
|
||||||
|
static const int kInstMeshOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
|
||||||
|
static const int kInstMeshOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
|
||||||
|
|
||||||
|
// Task Shader Output Record Offsets
|
||||||
|
static const int kInstTaskOutGlobalInvocationIdX = kInstCommonOutCnt;
|
||||||
|
static const int kInstTaskOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
|
||||||
|
static const int kInstTaskOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
|
||||||
|
|
||||||
|
// Size of Common and Stage-specific Members
|
||||||
|
static const int kInstStageOutCnt = kInstCommonOutCnt + 3;
|
||||||
|
|
||||||
|
// Validation Error Code Offset
|
||||||
|
//
|
||||||
|
// This identifies the validation error. It also helps to identify
|
||||||
|
// how many words follow in the record and their meaning.
|
||||||
|
static const int kInstValidationOutError = kInstStageOutCnt;
|
||||||
|
|
||||||
|
// Validation-specific Output Record Offsets
|
||||||
|
//
|
||||||
|
// Each different validation will generate a potentially different
|
||||||
|
// number of words at the end of the record giving more specifics
|
||||||
|
// about the validation error.
|
||||||
|
//
|
||||||
|
// A bindless bounds error will output the index and the bound.
|
||||||
|
static const int kInstBindlessBoundsOutDescIndex = kInstStageOutCnt + 1;
|
||||||
|
static const int kInstBindlessBoundsOutDescBound = kInstStageOutCnt + 2;
|
||||||
|
static const int kInstBindlessBoundsOutUnused = kInstStageOutCnt + 3;
|
||||||
|
static const int kInstBindlessBoundsOutCnt = kInstStageOutCnt + 4;
|
||||||
|
|
||||||
|
// A descriptor uninitialized error will output the index.
|
||||||
|
static const int kInstBindlessUninitOutDescIndex = kInstStageOutCnt + 1;
|
||||||
|
static const int kInstBindlessUninitOutUnused = kInstStageOutCnt + 2;
|
||||||
|
static const int kInstBindlessUninitOutUnused2 = kInstStageOutCnt + 3;
|
||||||
|
static const int kInstBindlessUninitOutCnt = kInstStageOutCnt + 4;
|
||||||
|
|
||||||
|
// A buffer out-of-bounds error will output the descriptor
|
||||||
|
// index, the buffer offset and the buffer size
|
||||||
|
static const int kInstBindlessBuffOOBOutDescIndex = kInstStageOutCnt + 1;
|
||||||
|
static const int kInstBindlessBuffOOBOutBuffOff = kInstStageOutCnt + 2;
|
||||||
|
static const int kInstBindlessBuffOOBOutBuffSize = kInstStageOutCnt + 3;
|
||||||
|
static const int kInstBindlessBuffOOBOutCnt = kInstStageOutCnt + 4;
|
||||||
|
|
||||||
|
// A buffer address unalloc error will output the 64-bit pointer in
|
||||||
|
// two 32-bit pieces, lower bits first.
|
||||||
|
static const int kInstBuffAddrUnallocOutDescPtrLo = kInstStageOutCnt + 1;
|
||||||
|
static const int kInstBuffAddrUnallocOutDescPtrHi = kInstStageOutCnt + 2;
|
||||||
|
static const int kInstBuffAddrUnallocOutCnt = kInstStageOutCnt + 3;
|
||||||
|
|
||||||
|
// Maximum Output Record Member Count
|
||||||
|
static const int kInstMaxOutCnt = kInstStageOutCnt + 4;
|
||||||
|
|
||||||
|
// Validation Error Codes
|
||||||
|
//
|
||||||
|
// These are the possible validation error codes.
|
||||||
|
static const int kInstErrorBindlessBounds = 0;
|
||||||
|
static const int kInstErrorBindlessUninit = 1;
|
||||||
|
static const int kInstErrorBuffAddrUnallocRef = 2;
|
||||||
|
// Deleted: static const int kInstErrorBindlessBuffOOB = 3;
|
||||||
|
// This comment will will remain for 2 releases to allow
|
||||||
|
// for the transition of all builds. Buffer OOB is
|
||||||
|
// generating the following four differentiated codes instead:
|
||||||
|
static const int kInstErrorBuffOOBUniform = 4;
|
||||||
|
static const int kInstErrorBuffOOBStorage = 5;
|
||||||
|
static const int kInstErrorBuffOOBUniformTexel = 6;
|
||||||
|
static const int kInstErrorBuffOOBStorageTexel = 7;
|
||||||
|
static const int kInstErrorMax = kInstErrorBuffOOBStorageTexel;
|
||||||
|
|
||||||
|
// Direct Input Buffer Offsets
|
||||||
|
//
|
||||||
|
// The following values provide member offsets into the input buffers
|
||||||
|
// consumed by InstrumentPass::GenDebugDirectRead(). This method is utilized
|
||||||
|
// by InstBindlessCheckPass.
|
||||||
|
//
|
||||||
|
// The only object in an input buffer is a runtime array of unsigned
|
||||||
|
// integers. Each validation will have its own formatting of this array.
|
||||||
|
static const int kDebugInputDataOffset = 0;
|
||||||
|
|
||||||
// Debug Buffer Bindings
|
// Debug Buffer Bindings
|
||||||
//
|
//
|
||||||
// These are the bindings for the different buffers which are
|
// These are the bindings for the different buffers which are
|
||||||
// read or written by the instrumentation passes.
|
// read or written by the instrumentation passes.
|
||||||
//
|
//
|
||||||
|
// This is the output buffer written by InstBindlessCheckPass,
|
||||||
|
// InstBuffAddrCheckPass, and possibly other future validations.
|
||||||
|
static const int kDebugOutputBindingStream = 0;
|
||||||
|
|
||||||
|
// The binding for the input buffer read by InstBindlessCheckPass.
|
||||||
|
static const int kDebugInputBindingBindless = 1;
|
||||||
|
|
||||||
|
// The binding for the input buffer read by InstBuffAddrCheckPass.
|
||||||
|
static const int kDebugInputBindingBuffAddr = 2;
|
||||||
|
|
||||||
// This is the output buffer written by InstDebugPrintfPass.
|
// This is the output buffer written by InstDebugPrintfPass.
|
||||||
static const int kDebugOutputPrintfStream = 3;
|
static const int kDebugOutputPrintfStream = 3;
|
||||||
|
|
||||||
|
// Bindless Validation Input Buffer Format
|
||||||
|
//
|
||||||
|
// An input buffer for bindless validation consists of a single array of
|
||||||
|
// unsigned integers we will call Data[]. This array is formatted as follows.
|
||||||
|
//
|
||||||
|
// At offset kDebugInputBindlessInitOffset in Data[] is a single uint which
|
||||||
|
// gives an offset to the start of the bindless initialization data. More
|
||||||
|
// specifically, if the following value is zero, we know that the descriptor at
|
||||||
|
// (set = s, binding = b, index = i) is not initialized; if the value is
|
||||||
|
// non-zero, and the descriptor points to a buffer, the value is the length of
|
||||||
|
// the buffer in bytes and can be used to check for out-of-bounds buffer
|
||||||
|
// references:
|
||||||
|
// Data[ i + Data[ b + Data[ s + Data[ kDebugInputBindlessInitOffset ] ] ] ]
|
||||||
|
static const int kDebugInputBindlessInitOffset = 0;
|
||||||
|
|
||||||
|
// At offset kDebugInputBindlessOffsetLengths is some number of uints which
|
||||||
|
// provide the bindless length data. More specifically, the number of
|
||||||
|
// descriptors at (set=s, binding=b) is:
|
||||||
|
// Data[ Data[ s + kDebugInputBindlessOffsetLengths ] + b ]
|
||||||
|
static const int kDebugInputBindlessOffsetLengths = 1;
|
||||||
|
|
||||||
|
// Buffer Device Address Input Buffer Format
|
||||||
|
//
|
||||||
|
// An input buffer for buffer device address validation consists of a single
|
||||||
|
// array of unsigned 64-bit integers we will call Data[]. This array is
|
||||||
|
// formatted as follows:
|
||||||
|
//
|
||||||
|
// At offset kDebugInputBuffAddrPtrOffset is a list of sorted valid buffer
|
||||||
|
// addresses. The list is terminated with the address 0xffffffffffffffff.
|
||||||
|
// If 0x0 is not a valid buffer address, this address is inserted at the
|
||||||
|
// start of the list.
|
||||||
|
//
|
||||||
|
static const int kDebugInputBuffAddrPtrOffset = 1;
|
||||||
|
//
|
||||||
|
// At offset kDebugInputBuffAddrLengthOffset in Data[] is a single uint64 which
|
||||||
|
// gives an offset to the start of the buffer length data. More
|
||||||
|
// specifically, for a buffer whose pointer is located at input buffer offset
|
||||||
|
// i, the length is located at:
|
||||||
|
//
|
||||||
|
// Data[ i - kDebugInputBuffAddrPtrOffset
|
||||||
|
// + Data[ kDebugInputBuffAddrLengthOffset ] ]
|
||||||
|
//
|
||||||
|
// The length associated with the 0xffffffffffffffff address is zero. If
|
||||||
|
// not a valid buffer, the length associated with the 0x0 address is zero.
|
||||||
|
static const int kDebugInputBuffAddrLengthOffset = 0;
|
||||||
|
|
||||||
} // namespace spvtools
|
} // namespace spvtools
|
||||||
|
|
||||||
#endif // INCLUDE_SPIRV_TOOLS_INSTRUMENT_HPP_
|
#endif // INCLUDE_SPIRV_TOOLS_INSTRUMENT_HPP_
|
||||||
|
@ -143,7 +143,6 @@ typedef enum spv_operand_type_t {
|
|||||||
// may be larger than 32, which would require such a typed literal value to
|
// may be larger than 32, which would require such a typed literal value to
|
||||||
// occupy multiple SPIR-V words.
|
// occupy multiple SPIR-V words.
|
||||||
SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
|
SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
|
||||||
SPV_OPERAND_TYPE_LITERAL_FLOAT, // Always 32-bit float.
|
|
||||||
|
|
||||||
// Set 3: The literal string operand type.
|
// Set 3: The literal string operand type.
|
||||||
SPV_OPERAND_TYPE_LITERAL_STRING,
|
SPV_OPERAND_TYPE_LITERAL_STRING,
|
||||||
@ -286,22 +285,6 @@ typedef enum spv_operand_type_t {
|
|||||||
// An optional packed vector format
|
// An optional packed vector format
|
||||||
SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT,
|
SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT,
|
||||||
|
|
||||||
// Concrete operand types for cooperative matrix.
|
|
||||||
SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS,
|
|
||||||
// An optional cooperative matrix operands
|
|
||||||
SPV_OPERAND_TYPE_OPTIONAL_COOPERATIVE_MATRIX_OPERANDS,
|
|
||||||
SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_LAYOUT,
|
|
||||||
SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_USE,
|
|
||||||
|
|
||||||
// Enum type from SPV_INTEL_global_variable_fpga_decorations
|
|
||||||
SPV_OPERAND_TYPE_INITIALIZATION_MODE_QUALIFIER,
|
|
||||||
// Enum type from SPV_INTEL_global_variable_host_access
|
|
||||||
SPV_OPERAND_TYPE_HOST_ACCESS_QUALIFIER,
|
|
||||||
// Enum type from SPV_INTEL_cache_controls
|
|
||||||
SPV_OPERAND_TYPE_LOAD_CACHE_CONTROL,
|
|
||||||
// Enum type from SPV_INTEL_cache_controls
|
|
||||||
SPV_OPERAND_TYPE_STORE_CACHE_CONTROL,
|
|
||||||
|
|
||||||
// This is a sentinel value, and does not represent an operand type.
|
// This is a sentinel value, and does not represent an operand type.
|
||||||
// It should come last.
|
// It should come last.
|
||||||
SPV_OPERAND_TYPE_NUM_OPERAND_TYPES,
|
SPV_OPERAND_TYPE_NUM_OPERAND_TYPES,
|
||||||
@ -419,19 +402,6 @@ typedef struct spv_parsed_instruction_t {
|
|||||||
uint16_t num_operands;
|
uint16_t num_operands;
|
||||||
} spv_parsed_instruction_t;
|
} spv_parsed_instruction_t;
|
||||||
|
|
||||||
typedef struct spv_parsed_header_t {
|
|
||||||
// The magic number of the SPIR-V module.
|
|
||||||
uint32_t magic;
|
|
||||||
// Version number.
|
|
||||||
uint32_t version;
|
|
||||||
// Generator's magic number.
|
|
||||||
uint32_t generator;
|
|
||||||
// IDs bound for this module (0 < id < bound).
|
|
||||||
uint32_t bound;
|
|
||||||
// reserved.
|
|
||||||
uint32_t reserved;
|
|
||||||
} spv_parsed_header_t;
|
|
||||||
|
|
||||||
typedef struct spv_const_binary_t {
|
typedef struct spv_const_binary_t {
|
||||||
const uint32_t* code;
|
const uint32_t* code;
|
||||||
const size_t wordCount;
|
const size_t wordCount;
|
||||||
@ -471,8 +441,6 @@ typedef struct spv_reducer_options_t spv_reducer_options_t;
|
|||||||
|
|
||||||
typedef struct spv_fuzzer_options_t spv_fuzzer_options_t;
|
typedef struct spv_fuzzer_options_t spv_fuzzer_options_t;
|
||||||
|
|
||||||
typedef struct spv_optimizer_t spv_optimizer_t;
|
|
||||||
|
|
||||||
// Type Definitions
|
// Type Definitions
|
||||||
|
|
||||||
typedef spv_const_binary_t* spv_const_binary;
|
typedef spv_const_binary_t* spv_const_binary;
|
||||||
@ -932,63 +900,6 @@ SPIRV_TOOLS_EXPORT spv_result_t spvBinaryParse(
|
|||||||
const size_t num_words, spv_parsed_header_fn_t parse_header,
|
const size_t num_words, spv_parsed_header_fn_t parse_header,
|
||||||
spv_parsed_instruction_fn_t parse_instruction, spv_diagnostic* diagnostic);
|
spv_parsed_instruction_fn_t parse_instruction, spv_diagnostic* diagnostic);
|
||||||
|
|
||||||
// The optimizer interface.
|
|
||||||
|
|
||||||
// A pointer to a function that accepts a log message from an optimizer.
|
|
||||||
typedef void (*spv_message_consumer)(
|
|
||||||
spv_message_level_t, const char*, const spv_position_t*, const char*);
|
|
||||||
|
|
||||||
// Creates and returns an optimizer object. This object must be passed to
|
|
||||||
// optimizer APIs below and is valid until passed to spvOptimizerDestroy.
|
|
||||||
SPIRV_TOOLS_EXPORT spv_optimizer_t* spvOptimizerCreate(spv_target_env env);
|
|
||||||
|
|
||||||
// Destroys the given optimizer object.
|
|
||||||
SPIRV_TOOLS_EXPORT void spvOptimizerDestroy(spv_optimizer_t* optimizer);
|
|
||||||
|
|
||||||
// Sets an spv_message_consumer on an optimizer object.
|
|
||||||
SPIRV_TOOLS_EXPORT void spvOptimizerSetMessageConsumer(
|
|
||||||
spv_optimizer_t* optimizer, spv_message_consumer consumer);
|
|
||||||
|
|
||||||
// Registers passes that attempt to legalize the generated code.
|
|
||||||
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterLegalizationPasses(
|
|
||||||
spv_optimizer_t* optimizer);
|
|
||||||
|
|
||||||
// Registers passes that attempt to improve performance of generated code.
|
|
||||||
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterPerformancePasses(
|
|
||||||
spv_optimizer_t* optimizer);
|
|
||||||
|
|
||||||
// Registers passes that attempt to improve the size of generated code.
|
|
||||||
SPIRV_TOOLS_EXPORT void spvOptimizerRegisterSizePasses(
|
|
||||||
spv_optimizer_t* optimizer);
|
|
||||||
|
|
||||||
// Registers a pass specified by a flag in an optimizer object.
|
|
||||||
SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassFromFlag(
|
|
||||||
spv_optimizer_t* optimizer, const char* flag);
|
|
||||||
|
|
||||||
// Registers passes specified by length number of flags in an optimizer object.
|
|
||||||
SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassesFromFlags(
|
|
||||||
spv_optimizer_t* optimizer, const char** flags, const size_t flag_count);
|
|
||||||
|
|
||||||
// Optimizes the SPIR-V code of size |word_count| pointed to by |binary| and
|
|
||||||
// returns an optimized spv_binary in |optimized_binary|.
|
|
||||||
//
|
|
||||||
// Returns SPV_SUCCESS on successful optimization, whether or not the module is
|
|
||||||
// modified. Returns an SPV_ERROR_* if the module fails to validate or if
|
|
||||||
// errors occur when processing using any of the registered passes. In that
|
|
||||||
// case, no further passes are executed and the |optimized_binary| contents may
|
|
||||||
// be invalid.
|
|
||||||
//
|
|
||||||
// By default, the binary is validated before any transforms are performed,
|
|
||||||
// and optionally after each transform. Validation uses SPIR-V spec rules
|
|
||||||
// for the SPIR-V version named in the binary's header (at word offset 1).
|
|
||||||
// Additionally, if the target environment is a client API (such as
|
|
||||||
// Vulkan 1.1), then validate for that client API version, to the extent
|
|
||||||
// that it is verifiable from data in the binary itself, or from the
|
|
||||||
// validator options set on the optimizer options.
|
|
||||||
SPIRV_TOOLS_EXPORT spv_result_t spvOptimizerRun(
|
|
||||||
spv_optimizer_t* optimizer, const uint32_t* binary, const size_t word_count,
|
|
||||||
spv_binary* optimized_binary, const spv_optimizer_options options);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,11 +31,6 @@ using MessageConsumer = std::function<void(
|
|||||||
const spv_position_t& /* position */, const char* /* message */
|
const spv_position_t& /* position */, const char* /* message */
|
||||||
)>;
|
)>;
|
||||||
|
|
||||||
using HeaderParser = std::function<spv_result_t(
|
|
||||||
const spv_endianness_t endianess, const spv_parsed_header_t& instruction)>;
|
|
||||||
using InstructionParser =
|
|
||||||
std::function<spv_result_t(const spv_parsed_instruction_t& instruction)>;
|
|
||||||
|
|
||||||
// C++ RAII wrapper around the C context object spv_context.
|
// C++ RAII wrapper around the C context object spv_context.
|
||||||
class Context {
|
class Context {
|
||||||
public:
|
public:
|
||||||
@ -341,23 +336,6 @@ class SpirvTools {
|
|||||||
std::string* text,
|
std::string* text,
|
||||||
uint32_t options = kDefaultDisassembleOption) const;
|
uint32_t options = kDefaultDisassembleOption) const;
|
||||||
|
|
||||||
// Parses a SPIR-V binary, specified as counted sequence of 32-bit words.
|
|
||||||
// Parsing feedback is provided via two callbacks provided as std::function.
|
|
||||||
// In a valid parse the parsed-header callback is called once, and
|
|
||||||
// then the parsed-instruction callback is called once for each instruction
|
|
||||||
// in the stream.
|
|
||||||
// Returns true on successful parsing.
|
|
||||||
// If diagnostic is non-null, a diagnostic is emitted on failed parsing.
|
|
||||||
// If diagnostic is null the context's message consumer
|
|
||||||
// will be used to emit any errors. If a callback returns anything other than
|
|
||||||
// SPV_SUCCESS, then that status code is returned, no further callbacks are
|
|
||||||
// issued, and no additional diagnostics are emitted.
|
|
||||||
// This is a wrapper around the C API spvBinaryParse.
|
|
||||||
bool Parse(const std::vector<uint32_t>& binary,
|
|
||||||
const HeaderParser& header_parser,
|
|
||||||
const InstructionParser& instruction_parser,
|
|
||||||
spv_diagnostic* diagnostic = nullptr);
|
|
||||||
|
|
||||||
// Validates the given SPIR-V |binary|. Returns true if no issues are found.
|
// Validates the given SPIR-V |binary|. Returns true if no issues are found.
|
||||||
// Otherwise, returns false and communicates issues via the message consumer
|
// Otherwise, returns false and communicates issues via the message consumer
|
||||||
// registered.
|
// registered.
|
||||||
|
@ -26,6 +26,11 @@ namespace spvtools {
|
|||||||
|
|
||||||
class LinkerOptions {
|
class LinkerOptions {
|
||||||
public:
|
public:
|
||||||
|
LinkerOptions()
|
||||||
|
: create_library_(false),
|
||||||
|
verify_ids_(false),
|
||||||
|
allow_partial_linkage_(false) {}
|
||||||
|
|
||||||
// Returns whether a library or an executable should be produced by the
|
// Returns whether a library or an executable should be produced by the
|
||||||
// linking phase.
|
// linking phase.
|
||||||
//
|
//
|
||||||
@ -58,16 +63,10 @@ class LinkerOptions {
|
|||||||
allow_partial_linkage_ = allow_partial_linkage;
|
allow_partial_linkage_ = allow_partial_linkage;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetUseHighestVersion() const { return use_highest_version_; }
|
|
||||||
void SetUseHighestVersion(bool use_highest_vers) {
|
|
||||||
use_highest_version_ = use_highest_vers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool create_library_{false};
|
bool create_library_;
|
||||||
bool verify_ids_{false};
|
bool verify_ids_;
|
||||||
bool allow_partial_linkage_{false};
|
bool allow_partial_linkage_;
|
||||||
bool use_highest_version_{false};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Links one or more SPIR-V modules into a new SPIR-V module. That is, combine
|
// Links one or more SPIR-V modules into a new SPIR-V module. That is, combine
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -97,24 +96,12 @@ class Optimizer {
|
|||||||
// Registers passes that attempt to improve performance of generated code.
|
// Registers passes that attempt to improve performance of generated code.
|
||||||
// This sequence of passes is subject to constant review and will change
|
// This sequence of passes is subject to constant review and will change
|
||||||
// from time to time.
|
// from time to time.
|
||||||
//
|
|
||||||
// If |preserve_interface| is true, all non-io variables in the entry point
|
|
||||||
// interface are considered live and are not eliminated.
|
|
||||||
// |preserve_interface| should be true if HLSL is generated
|
|
||||||
// from the SPIR-V bytecode.
|
|
||||||
Optimizer& RegisterPerformancePasses();
|
Optimizer& RegisterPerformancePasses();
|
||||||
Optimizer& RegisterPerformancePasses(bool preserve_interface);
|
|
||||||
|
|
||||||
// Registers passes that attempt to improve the size of generated code.
|
// Registers passes that attempt to improve the size of generated code.
|
||||||
// This sequence of passes is subject to constant review and will change
|
// This sequence of passes is subject to constant review and will change
|
||||||
// from time to time.
|
// from time to time.
|
||||||
//
|
|
||||||
// If |preserve_interface| is true, all non-io variables in the entry point
|
|
||||||
// interface are considered live and are not eliminated.
|
|
||||||
// |preserve_interface| should be true if HLSL is generated
|
|
||||||
// from the SPIR-V bytecode.
|
|
||||||
Optimizer& RegisterSizePasses();
|
Optimizer& RegisterSizePasses();
|
||||||
Optimizer& RegisterSizePasses(bool preserve_interface);
|
|
||||||
|
|
||||||
// Registers passes that attempt to legalize the generated code.
|
// Registers passes that attempt to legalize the generated code.
|
||||||
//
|
//
|
||||||
@ -124,13 +111,7 @@ class Optimizer {
|
|||||||
//
|
//
|
||||||
// This sequence of passes is subject to constant review and will change
|
// This sequence of passes is subject to constant review and will change
|
||||||
// from time to time.
|
// from time to time.
|
||||||
//
|
|
||||||
// If |preserve_interface| is true, all non-io variables in the entry point
|
|
||||||
// interface are considered live and are not eliminated.
|
|
||||||
// |preserve_interface| should be true if HLSL is generated
|
|
||||||
// from the SPIR-V bytecode.
|
|
||||||
Optimizer& RegisterLegalizationPasses();
|
Optimizer& RegisterLegalizationPasses();
|
||||||
Optimizer& RegisterLegalizationPasses(bool preserve_interface);
|
|
||||||
|
|
||||||
// Register passes specified in the list of |flags|. Each flag must be a
|
// Register passes specified in the list of |flags|. Each flag must be a
|
||||||
// string of a form accepted by Optimizer::FlagHasValidForm().
|
// string of a form accepted by Optimizer::FlagHasValidForm().
|
||||||
@ -539,14 +520,8 @@ Optimizer::PassToken CreateDeadInsertElimPass();
|
|||||||
// interface are considered live and are not eliminated. This mode is needed
|
// interface are considered live and are not eliminated. This mode is needed
|
||||||
// by GPU-Assisted validation instrumentation, where a change in the interface
|
// by GPU-Assisted validation instrumentation, where a change in the interface
|
||||||
// is not allowed.
|
// is not allowed.
|
||||||
//
|
|
||||||
// If |remove_outputs| is true, allow outputs to be removed from the interface.
|
|
||||||
// This is only safe if the caller knows that there is no corresponding input
|
|
||||||
// variable in the following shader. It is false by default.
|
|
||||||
Optimizer::PassToken CreateAggressiveDCEPass();
|
Optimizer::PassToken CreateAggressiveDCEPass();
|
||||||
Optimizer::PassToken CreateAggressiveDCEPass(bool preserve_interface);
|
Optimizer::PassToken CreateAggressiveDCEPass(bool preserve_interface);
|
||||||
Optimizer::PassToken CreateAggressiveDCEPass(bool preserve_interface,
|
|
||||||
bool remove_outputs);
|
|
||||||
|
|
||||||
// Creates a remove-unused-interface-variables pass.
|
// Creates a remove-unused-interface-variables pass.
|
||||||
// Removes variables referenced on the |OpEntryPoint| instruction that are not
|
// Removes variables referenced on the |OpEntryPoint| instruction that are not
|
||||||
@ -766,9 +741,19 @@ Optimizer::PassToken CreateCombineAccessChainsPass();
|
|||||||
// potentially de-optimizing the instrument code, for example, inlining
|
// potentially de-optimizing the instrument code, for example, inlining
|
||||||
// the debug record output function throughout the module.
|
// the debug record output function throughout the module.
|
||||||
//
|
//
|
||||||
// The instrumentation will write |shader_id| in each output record
|
// The instrumentation will read and write buffers in debug
|
||||||
|
// descriptor set |desc_set|. It will write |shader_id| in each output record
|
||||||
// to identify the shader module which generated the record.
|
// to identify the shader module which generated the record.
|
||||||
Optimizer::PassToken CreateInstBindlessCheckPass(uint32_t shader_id);
|
// |desc_length_enable| controls instrumentation of runtime descriptor array
|
||||||
|
// references, |desc_init_enable| controls instrumentation of descriptor
|
||||||
|
// initialization checking, and |buff_oob_enable| controls instrumentation
|
||||||
|
// of storage and uniform buffer bounds checking, all of which require input
|
||||||
|
// buffer support. |texbuff_oob_enable| controls instrumentation of texel
|
||||||
|
// buffers, which does not require input buffer support.
|
||||||
|
Optimizer::PassToken CreateInstBindlessCheckPass(
|
||||||
|
uint32_t desc_set, uint32_t shader_id, bool desc_length_enable = false,
|
||||||
|
bool desc_init_enable = false, bool buff_oob_enable = false,
|
||||||
|
bool texbuff_oob_enable = false);
|
||||||
|
|
||||||
// Create a pass to instrument physical buffer address checking
|
// Create a pass to instrument physical buffer address checking
|
||||||
// This pass instruments all physical buffer address references to check that
|
// This pass instruments all physical buffer address references to check that
|
||||||
@ -789,7 +774,8 @@ Optimizer::PassToken CreateInstBindlessCheckPass(uint32_t shader_id);
|
|||||||
// The instrumentation will read and write buffers in debug
|
// The instrumentation will read and write buffers in debug
|
||||||
// descriptor set |desc_set|. It will write |shader_id| in each output record
|
// descriptor set |desc_set|. It will write |shader_id| in each output record
|
||||||
// to identify the shader module which generated the record.
|
// to identify the shader module which generated the record.
|
||||||
Optimizer::PassToken CreateInstBuffAddrCheckPass(uint32_t shader_id);
|
Optimizer::PassToken CreateInstBuffAddrCheckPass(uint32_t desc_set,
|
||||||
|
uint32_t shader_id);
|
||||||
|
|
||||||
// Create a pass to instrument OpDebugPrintf instructions.
|
// Create a pass to instrument OpDebugPrintf instructions.
|
||||||
// This pass replaces all OpDebugPrintf instructions with instructions to write
|
// This pass replaces all OpDebugPrintf instructions with instructions to write
|
||||||
@ -901,59 +887,12 @@ Optimizer::PassToken CreateAmdExtToKhrPass();
|
|||||||
Optimizer::PassToken CreateInterpolateFixupPass();
|
Optimizer::PassToken CreateInterpolateFixupPass();
|
||||||
|
|
||||||
// Removes unused components from composite input variables. Current
|
// Removes unused components from composite input variables. Current
|
||||||
// implementation just removes trailing unused components from input arrays
|
// implementation just removes trailing unused components from input arrays.
|
||||||
// and structs. The pass performs best after maximizing dead code removal.
|
// The pass performs best after maximizing dead code removal. A subsequent dead
|
||||||
// A subsequent dead code elimination pass would be beneficial in removing
|
// code elimination pass would be beneficial in removing newly unused component
|
||||||
// newly unused component types.
|
// types.
|
||||||
//
|
|
||||||
// WARNING: This pass can only be safely applied standalone to vertex shaders
|
|
||||||
// as it can otherwise cause interface incompatibilities with the preceding
|
|
||||||
// shader in the pipeline. If applied to non-vertex shaders, the user should
|
|
||||||
// follow by applying EliminateDeadOutputStores and
|
|
||||||
// EliminateDeadOutputComponents to the preceding shader.
|
|
||||||
Optimizer::PassToken CreateEliminateDeadInputComponentsPass();
|
Optimizer::PassToken CreateEliminateDeadInputComponentsPass();
|
||||||
|
|
||||||
// Removes unused components from composite output variables. Current
|
|
||||||
// implementation just removes trailing unused components from output arrays
|
|
||||||
// and structs. The pass performs best after eliminating dead output stores.
|
|
||||||
// A subsequent dead code elimination pass would be beneficial in removing
|
|
||||||
// newly unused component types. Currently only supports vertex and fragment
|
|
||||||
// shaders.
|
|
||||||
//
|
|
||||||
// WARNING: This pass cannot be safely applied standalone as it can cause
|
|
||||||
// interface incompatibility with the following shader in the pipeline. The
|
|
||||||
// user should first apply EliminateDeadInputComponents to the following
|
|
||||||
// shader, then apply EliminateDeadOutputStores to this shader.
|
|
||||||
Optimizer::PassToken CreateEliminateDeadOutputComponentsPass();
|
|
||||||
|
|
||||||
// Removes unused components from composite input variables. This safe
|
|
||||||
// version will not cause interface incompatibilities since it only changes
|
|
||||||
// vertex shaders. The current implementation just removes trailing unused
|
|
||||||
// components from input structs and input arrays. The pass performs best
|
|
||||||
// after maximizing dead code removal. A subsequent dead code elimination
|
|
||||||
// pass would be beneficial in removing newly unused component types.
|
|
||||||
Optimizer::PassToken CreateEliminateDeadInputComponentsSafePass();
|
|
||||||
|
|
||||||
// Analyzes shader and populates |live_locs| and |live_builtins|. Best results
|
|
||||||
// will be obtained if shader has all dead code eliminated first. |live_locs|
|
|
||||||
// and |live_builtins| are subsequently used when calling
|
|
||||||
// CreateEliminateDeadOutputStoresPass on the preceding shader. Currently only
|
|
||||||
// supports tesc, tese, geom, and frag shaders.
|
|
||||||
Optimizer::PassToken CreateAnalyzeLiveInputPass(
|
|
||||||
std::unordered_set<uint32_t>* live_locs,
|
|
||||||
std::unordered_set<uint32_t>* live_builtins);
|
|
||||||
|
|
||||||
// Removes stores to output locations not listed in |live_locs| or
|
|
||||||
// |live_builtins|. Best results are obtained if constant propagation is
|
|
||||||
// performed first. A subsequent call to ADCE will eliminate any dead code
|
|
||||||
// created by the removal of the stores. A subsequent call to
|
|
||||||
// CreateEliminateDeadOutputComponentsPass will eliminate any dead output
|
|
||||||
// components created by the elimination of the stores. Currently only supports
|
|
||||||
// vert, tesc, tese, and geom shaders.
|
|
||||||
Optimizer::PassToken CreateEliminateDeadOutputStoresPass(
|
|
||||||
std::unordered_set<uint32_t>* live_locs,
|
|
||||||
std::unordered_set<uint32_t>* live_builtins);
|
|
||||||
|
|
||||||
// Creates a convert-to-sampled-image pass to convert images and/or
|
// Creates a convert-to-sampled-image pass to convert images and/or
|
||||||
// samplers with given pairs of descriptor set and binding to sampled image.
|
// samplers with given pairs of descriptor set and binding to sampled image.
|
||||||
// If a pair of an image and a sampler have the same pair of descriptor set and
|
// If a pair of an image and a sampler have the same pair of descriptor set and
|
||||||
@ -978,28 +917,6 @@ Optimizer::PassToken CreateRemoveDontInlinePass();
|
|||||||
// object, currently the pass would remove accesschain pointer argument passed
|
// object, currently the pass would remove accesschain pointer argument passed
|
||||||
// to the function
|
// to the function
|
||||||
Optimizer::PassToken CreateFixFuncCallArgumentsPass();
|
Optimizer::PassToken CreateFixFuncCallArgumentsPass();
|
||||||
|
|
||||||
// Creates a trim-capabilities pass.
|
|
||||||
// This pass removes unused capabilities for a given module, and if possible,
|
|
||||||
// associated extensions.
|
|
||||||
// See `trim_capabilities.h` for the list of supported capabilities.
|
|
||||||
//
|
|
||||||
// If the module contains unsupported capabilities, this pass will ignore them.
|
|
||||||
// This should be fine in most cases, but could yield to incorrect results if
|
|
||||||
// the unknown capability interacts with one of the trimmed capabilities.
|
|
||||||
Optimizer::PassToken CreateTrimCapabilitiesPass();
|
|
||||||
|
|
||||||
// Creates a switch-descriptorset pass.
|
|
||||||
// This pass changes any DescriptorSet decorations with the value |ds_from| to
|
|
||||||
// use the new value |ds_to|.
|
|
||||||
Optimizer::PassToken CreateSwitchDescriptorSetPass(uint32_t ds_from,
|
|
||||||
uint32_t ds_to);
|
|
||||||
|
|
||||||
// Creates an invocation interlock placement pass.
|
|
||||||
// This pass ensures that an entry point will have at most one
|
|
||||||
// OpBeginInterlockInvocationEXT and one OpEndInterlockInvocationEXT, in that
|
|
||||||
// order.
|
|
||||||
Optimizer::PassToken CreateInvocationInterlockPlacementPass();
|
|
||||||
} // namespace spvtools
|
} // namespace spvtools
|
||||||
|
|
||||||
#endif // INCLUDE_SPIRV_TOOLS_OPTIMIZER_HPP_
|
#endif // INCLUDE_SPIRV_TOOLS_OPTIMIZER_HPP_
|
||||||
|
@ -23,11 +23,6 @@ set -x
|
|||||||
BUILD_ROOT=$PWD
|
BUILD_ROOT=$PWD
|
||||||
SRC=$PWD/github/SPIRV-Tools
|
SRC=$PWD/github/SPIRV-Tools
|
||||||
|
|
||||||
# This is required to run any git command in the docker since owner will
|
|
||||||
# have changed between the clone environment, and the docker container.
|
|
||||||
# Marking the root of the repo as safe for ownership changes.
|
|
||||||
git config --global --add safe.directory $SRC
|
|
||||||
|
|
||||||
# Get clang-format-5.0.0.
|
# Get clang-format-5.0.0.
|
||||||
# Once kokoro upgrades the Ubuntu VMs, we can use 'apt-get install clang-format'
|
# Once kokoro upgrades the Ubuntu VMs, we can use 'apt-get install clang-format'
|
||||||
curl -L http://releases.llvm.org/5.0.0/clang+llvm-5.0.0-linux-x86_64-ubuntu14.04.tar.xz -o clang-llvm.tar.xz
|
curl -L http://releases.llvm.org/5.0.0/clang+llvm-5.0.0-linux-x86_64-ubuntu14.04.tar.xz -o clang-llvm.tar.xz
|
||||||
|
@ -22,3 +22,4 @@ set -x
|
|||||||
|
|
||||||
SCRIPT_DIR=`dirname "$BASH_SOURCE"`
|
SCRIPT_DIR=`dirname "$BASH_SOURCE"`
|
||||||
source $SCRIPT_DIR/../scripts/macos/build.sh Debug
|
source $SCRIPT_DIR/../scripts/macos/build.sh Debug
|
||||||
|
|
||||||
|
@ -24,22 +24,21 @@ CC=clang
|
|||||||
CXX=clang++
|
CXX=clang++
|
||||||
SRC=$PWD/github/SPIRV-Tools
|
SRC=$PWD/github/SPIRV-Tools
|
||||||
|
|
||||||
# This is required to run any git command in the docker since owner will
|
|
||||||
# have changed between the clone environment, and the docker container.
|
|
||||||
# Marking the root of the repo as safe for ownership changes.
|
|
||||||
git config --global --add safe.directory $SRC
|
|
||||||
|
|
||||||
cd $SRC
|
cd $SRC
|
||||||
/usr/bin/python3 utils/git-sync-deps --treeless
|
git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
|
||||||
|
git clone https://github.com/google/googletest external/googletest
|
||||||
|
cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd ..
|
||||||
|
git clone --depth=1 https://github.com/google/effcee external/effcee
|
||||||
|
git clone --depth=1 https://github.com/google/re2 external/re2
|
||||||
|
|
||||||
# Get bazel 5.0.0
|
# Get bazel 5.0.0
|
||||||
gsutil cp gs://bazel/5.0.0/release/bazel-5.0.0-darwin-x86_64 .
|
gsutil cp gs://bazel/5.0.0/release/bazel-5.0.0-darwin-x86_64 .
|
||||||
chmod +x bazel-5.0.0-darwin-x86_64
|
chmod +x bazel-5.0.0-darwin-x86_64
|
||||||
|
|
||||||
echo $(date): Build everything...
|
echo $(date): Build everything...
|
||||||
./bazel-5.0.0-darwin-x86_64 build --cxxopt=-std=c++17 :all
|
./bazel-5.0.0-darwin-x86_64 build :all
|
||||||
echo $(date): Build completed.
|
echo $(date): Build completed.
|
||||||
|
|
||||||
echo $(date): Starting bazel test...
|
echo $(date): Starting bazel test...
|
||||||
./bazel-5.0.0-darwin-x86_64 test --cxxopt=-std=c++17 :all
|
./bazel-5.0.0-darwin-x86_64 test :all
|
||||||
echo $(date): Bazel test completed.
|
echo $(date): Bazel test completed.
|
||||||
|
@ -22,3 +22,4 @@ set -x
|
|||||||
|
|
||||||
SCRIPT_DIR=`dirname "$BASH_SOURCE"`
|
SCRIPT_DIR=`dirname "$BASH_SOURCE"`
|
||||||
source $SCRIPT_DIR/../scripts/macos/build.sh RelWithDebInfo
|
source $SCRIPT_DIR/../scripts/macos/build.sh RelWithDebInfo
|
||||||
|
|
||||||
|
@ -20,11 +20,6 @@ set -e
|
|||||||
# Display commands being run.
|
# Display commands being run.
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
# This is required to run any git command in the docker since owner will
|
|
||||||
# have changed between the clone environment, and the docker container.
|
|
||||||
# Marking the root of the repo as safe for ownership changes.
|
|
||||||
git config --global --add safe.directory $ROOT_DIR
|
|
||||||
|
|
||||||
. /bin/using.sh # Declare the bash `using` function for configuring toolchains.
|
. /bin/using.sh # Declare the bash `using` function for configuring toolchains.
|
||||||
|
|
||||||
if [ $COMPILER = "clang" ]; then
|
if [ $COMPILER = "clang" ]; then
|
||||||
@ -35,6 +30,14 @@ fi
|
|||||||
|
|
||||||
cd $ROOT_DIR
|
cd $ROOT_DIR
|
||||||
|
|
||||||
|
function clone_if_missing() {
|
||||||
|
url=$1
|
||||||
|
dir=$2
|
||||||
|
if [[ ! -d "$dir" ]]; then
|
||||||
|
git clone ${@:3} "$url" "$dir"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
function clean_dir() {
|
function clean_dir() {
|
||||||
dir=$1
|
dir=$1
|
||||||
if [[ -d "$dir" ]]; then
|
if [[ -d "$dir" ]]; then
|
||||||
@ -43,10 +46,12 @@ function clean_dir() {
|
|||||||
mkdir "$dir"
|
mkdir "$dir"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ $TOOL != "cmake-smoketest" ]; then
|
clone_if_missing https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers --depth=1
|
||||||
# Get source for dependencies, as specified in the DEPS file
|
clone_if_missing https://github.com/google/googletest external/googletest
|
||||||
/usr/bin/python3 utils/git-sync-deps --treeless
|
pushd external/googletest; git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7; popd
|
||||||
fi
|
clone_if_missing https://github.com/google/effcee external/effcee --depth=1
|
||||||
|
clone_if_missing https://github.com/google/re2 external/re2 --depth=1
|
||||||
|
clone_if_missing https://github.com/protocolbuffers/protobuf external/protobuf --branch v3.13.0.1
|
||||||
|
|
||||||
if [ $TOOL = "cmake" ]; then
|
if [ $TOOL = "cmake" ]; then
|
||||||
using cmake-3.17.2
|
using cmake-3.17.2
|
||||||
@ -131,7 +136,6 @@ elif [ $TOOL = "cmake-smoketest" ]; then
|
|||||||
git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-headers
|
git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-headers
|
||||||
git clone https://github.com/google/re2
|
git clone https://github.com/google/re2
|
||||||
git clone https://github.com/google/effcee
|
git clone https://github.com/google/effcee
|
||||||
git clone https://github.com/abseil/abseil-cpp abseil_cpp
|
|
||||||
|
|
||||||
cd $SHADERC_DIR
|
cd $SHADERC_DIR
|
||||||
mkdir build
|
mkdir build
|
||||||
@ -142,7 +146,7 @@ elif [ $TOOL = "cmake-smoketest" ]; then
|
|||||||
cmake -GNinja -DRE2_BUILD_TESTING=OFF -DCMAKE_BUILD_TYPE="Release" ..
|
cmake -GNinja -DRE2_BUILD_TESTING=OFF -DCMAKE_BUILD_TYPE="Release" ..
|
||||||
|
|
||||||
echo $(date): Build glslang...
|
echo $(date): Build glslang...
|
||||||
ninja glslang-standalone
|
ninja glslangValidator
|
||||||
|
|
||||||
echo $(date): Build everything...
|
echo $(date): Build everything...
|
||||||
ninja
|
ninja
|
||||||
@ -156,7 +160,7 @@ elif [ $TOOL = "cmake-smoketest" ]; then
|
|||||||
echo $(date): ctest completed.
|
echo $(date): ctest completed.
|
||||||
elif [ $TOOL = "cmake-android-ndk" ]; then
|
elif [ $TOOL = "cmake-android-ndk" ]; then
|
||||||
using cmake-3.17.2
|
using cmake-3.17.2
|
||||||
using ndk-r25c
|
using ndk-r21d
|
||||||
using ninja-1.10.0
|
using ninja-1.10.0
|
||||||
|
|
||||||
clean_dir "$ROOT_DIR/build"
|
clean_dir "$ROOT_DIR/build"
|
||||||
@ -164,7 +168,7 @@ elif [ $TOOL = "cmake-android-ndk" ]; then
|
|||||||
|
|
||||||
echo $(date): Starting build...
|
echo $(date): Starting build...
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release \
|
cmake -DCMAKE_BUILD_TYPE=Release \
|
||||||
-DANDROID_NATIVE_API_LEVEL=android-24 \
|
-DANDROID_NATIVE_API_LEVEL=android-16 \
|
||||||
-DANDROID_ABI="armeabi-v7a with NEON" \
|
-DANDROID_ABI="armeabi-v7a with NEON" \
|
||||||
-DSPIRV_SKIP_TESTS=ON \
|
-DSPIRV_SKIP_TESTS=ON \
|
||||||
-DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \
|
-DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \
|
||||||
@ -176,7 +180,7 @@ elif [ $TOOL = "cmake-android-ndk" ]; then
|
|||||||
ninja
|
ninja
|
||||||
echo $(date): Build completed.
|
echo $(date): Build completed.
|
||||||
elif [ $TOOL = "android-ndk-build" ]; then
|
elif [ $TOOL = "android-ndk-build" ]; then
|
||||||
using ndk-r25c
|
using ndk-r21d
|
||||||
|
|
||||||
clean_dir "$ROOT_DIR/build"
|
clean_dir "$ROOT_DIR/build"
|
||||||
cd "$ROOT_DIR/build"
|
cd "$ROOT_DIR/build"
|
||||||
@ -194,10 +198,10 @@ elif [ $TOOL = "bazel" ]; then
|
|||||||
using bazel-5.0.0
|
using bazel-5.0.0
|
||||||
|
|
||||||
echo $(date): Build everything...
|
echo $(date): Build everything...
|
||||||
bazel build --cxxopt=-std=c++17 :all
|
bazel build :all
|
||||||
echo $(date): Build completed.
|
echo $(date): Build completed.
|
||||||
|
|
||||||
echo $(date): Starting bazel test...
|
echo $(date): Starting bazel test...
|
||||||
bazel test --cxxopt=-std=c++17 :all
|
bazel test :all
|
||||||
echo $(date): Bazel test completed.
|
echo $(date): Bazel test completed.
|
||||||
fi
|
fi
|
||||||
|
@ -26,18 +26,6 @@ COMPILER=$2
|
|||||||
TOOL=$3
|
TOOL=$3
|
||||||
BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
|
BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
|
||||||
|
|
||||||
# chown the given directory to the current user, if it exists.
|
|
||||||
# Docker creates files with the root user - this can upset the Kokoro artifact copier.
|
|
||||||
function chown_dir() {
|
|
||||||
dir=$1
|
|
||||||
if [[ -d "$dir" ]]; then
|
|
||||||
sudo chown -R "$(id -u):$(id -g)" "$dir"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
set +e
|
|
||||||
# Allow build failures
|
|
||||||
|
|
||||||
# "--privileged" is required to run ptrace in the asan builds.
|
# "--privileged" is required to run ptrace in the asan builds.
|
||||||
docker run --rm -i \
|
docker run --rm -i \
|
||||||
--privileged \
|
--privileged \
|
||||||
@ -53,11 +41,16 @@ docker run --rm -i \
|
|||||||
--env BUILD_SHA="${BUILD_SHA}" \
|
--env BUILD_SHA="${BUILD_SHA}" \
|
||||||
--entrypoint "${SCRIPT_DIR}/build-docker.sh" \
|
--entrypoint "${SCRIPT_DIR}/build-docker.sh" \
|
||||||
"gcr.io/shaderc-build/radial-build:latest"
|
"gcr.io/shaderc-build/radial-build:latest"
|
||||||
RESULT=$?
|
|
||||||
|
|
||||||
# This is important. If the permissions are not fixed, kokoro will fail
|
|
||||||
# to pull build artifacts, and put the build in tool-failure state, which
|
# chown the given directory to the current user, if it exists.
|
||||||
# blocks the logs.
|
# Docker creates files with the root user - this can upset the Kokoro artifact copier.
|
||||||
|
function chown_dir() {
|
||||||
|
dir=$1
|
||||||
|
if [[ -d "$dir" ]]; then
|
||||||
|
sudo chown -R "$(id -u):$(id -g)" "$dir"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
chown_dir "${ROOT_DIR}/build"
|
chown_dir "${ROOT_DIR}/build"
|
||||||
chown_dir "${ROOT_DIR}/external"
|
chown_dir "${ROOT_DIR}/external"
|
||||||
exit $RESULT
|
|
||||||
|
@ -24,11 +24,6 @@ BUILD_ROOT=$PWD
|
|||||||
SRC=$PWD/github/SPIRV-Tools
|
SRC=$PWD/github/SPIRV-Tools
|
||||||
BUILD_TYPE=$1
|
BUILD_TYPE=$1
|
||||||
|
|
||||||
# This is required to run any git command in the docker since owner will
|
|
||||||
# have changed between the clone environment, and the docker container.
|
|
||||||
# Marking the root of the repo as safe for ownership changes.
|
|
||||||
git config --global --add safe.directory $SRC
|
|
||||||
|
|
||||||
# Get NINJA.
|
# Get NINJA.
|
||||||
wget -q https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-mac.zip
|
wget -q https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-mac.zip
|
||||||
unzip -q ninja-mac.zip
|
unzip -q ninja-mac.zip
|
||||||
@ -36,16 +31,23 @@ chmod +x ninja
|
|||||||
export PATH="$PWD:$PATH"
|
export PATH="$PWD:$PATH"
|
||||||
|
|
||||||
cd $SRC
|
cd $SRC
|
||||||
python3 utils/git-sync-deps --treeless
|
git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
|
||||||
|
git clone https://github.com/google/googletest external/googletest
|
||||||
|
cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd ..
|
||||||
|
git clone --depth=1 https://github.com/google/effcee external/effcee
|
||||||
|
git clone --depth=1 https://github.com/google/re2 external/re2
|
||||||
|
git clone --depth=1 --branch v3.13.0.1 https://github.com/protocolbuffers/protobuf external/protobuf
|
||||||
|
|
||||||
mkdir build && cd $SRC/build
|
mkdir build && cd $SRC/build
|
||||||
|
|
||||||
# Invoke the build.
|
# Invoke the build.
|
||||||
BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
|
BUILD_SHA=${KOKORO_GITHUB_COMMIT:-$KOKORO_GITHUB_PULL_REQUEST_COMMIT}
|
||||||
echo $(date): Starting build...
|
echo $(date): Starting build...
|
||||||
|
# We need Python 3. At the moment python3.7 is the newest Python on Kokoro.
|
||||||
cmake \
|
cmake \
|
||||||
-GNinja \
|
-GNinja \
|
||||||
-DCMAKE_INSTALL_PREFIX=$KOKORO_ARTIFACTS_DIR/install \
|
-DCMAKE_INSTALL_PREFIX=$KOKORO_ARTIFACTS_DIR/install \
|
||||||
|
-DPYTHON_EXECUTABLE:FILEPATH=/usr/local/bin/python3.7 \
|
||||||
-DCMAKE_C_COMPILER=clang \
|
-DCMAKE_C_COMPILER=clang \
|
||||||
-DCMAKE_CXX_COMPILER=clang++ \
|
-DCMAKE_CXX_COMPILER=clang++ \
|
||||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||||
|
@ -24,23 +24,26 @@ set VS_VERSION=%2
|
|||||||
:: Force usage of python 3.6
|
:: Force usage of python 3.6
|
||||||
set PATH=C:\python36;"C:\Program Files\cmake-3.23.1-windows-x86_64\bin";%PATH%
|
set PATH=C:\python36;"C:\Program Files\cmake-3.23.1-windows-x86_64\bin";%PATH%
|
||||||
|
|
||||||
|
cd %SRC%
|
||||||
|
git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
|
||||||
|
git clone https://github.com/google/googletest external/googletest
|
||||||
|
cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd ..
|
||||||
|
git clone --depth=1 https://github.com/google/effcee external/effcee
|
||||||
|
git clone --depth=1 https://github.com/google/re2 external/re2
|
||||||
|
git clone --depth=1 --branch v3.13.0.1 https://github.com/protocolbuffers/protobuf external/protobuf
|
||||||
|
|
||||||
:: #########################################
|
:: #########################################
|
||||||
:: set up msvc build env
|
:: set up msvc build env
|
||||||
:: #########################################
|
:: #########################################
|
||||||
if %VS_VERSION% == 2017 (
|
if %VS_VERSION% == 2017 (
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
|
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||||
echo "Using VS 2017..."
|
echo "Using VS 2017..."
|
||||||
|
) else if %VS_VERSION% == 2015 (
|
||||||
:: RE2 does not support VS2017, we we must disable tests.
|
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
|
||||||
set BUILD_TESTS=NO
|
echo "Using VS 2015..."
|
||||||
) else if %VS_VERSION% == 2019 (
|
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
|
|
||||||
echo "Using VS 2019..."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cd %SRC%
|
cd %SRC%
|
||||||
python utils/git-sync-deps --treeless
|
|
||||||
|
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
|
|
||||||
@ -59,10 +62,6 @@ set CMAKE_FLAGS=-DCMAKE_INSTALL_PREFIX=%KOKORO_ARTIFACTS_DIR%\install -GNinja -D
|
|||||||
:: Build spirv-fuzz
|
:: Build spirv-fuzz
|
||||||
set CMAKE_FLAGS=%CMAKE_FLAGS% -DSPIRV_BUILD_FUZZER=ON
|
set CMAKE_FLAGS=%CMAKE_FLAGS% -DSPIRV_BUILD_FUZZER=ON
|
||||||
|
|
||||||
if "%BUILD_TESTS%" == "NO" (
|
|
||||||
set CMAKE_FLAGS=-DSPIRV_SKIP_TESTS=ON %CMAKE_FLAGS%
|
|
||||||
)
|
|
||||||
|
|
||||||
cmake %CMAKE_FLAGS% ..
|
cmake %CMAKE_FLAGS% ..
|
||||||
|
|
||||||
if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL%
|
if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL%
|
||||||
@ -78,12 +77,10 @@ setlocal ENABLEDELAYEDEXPANSION
|
|||||||
:: ################################################
|
:: ################################################
|
||||||
:: Run the tests
|
:: Run the tests
|
||||||
:: ################################################
|
:: ################################################
|
||||||
if "%BUILD_TESTS%" NEQ "NO" (
|
echo "Running Tests... %DATE% %TIME%"
|
||||||
echo "Running Tests... %DATE% %TIME%"
|
ctest -C %BUILD_TYPE% --output-on-failure --timeout 300
|
||||||
ctest -C %BUILD_TYPE% --output-on-failure --timeout 300
|
if !ERRORLEVEL! NEQ 0 exit /b !ERRORLEVEL!
|
||||||
if !ERRORLEVEL! NEQ 0 exit /b !ERRORLEVEL!
|
echo "Tests Completed %DATE% %TIME%"
|
||||||
echo "Tests Completed %DATE% %TIME%"
|
|
||||||
)
|
|
||||||
|
|
||||||
:: ################################################
|
:: ################################################
|
||||||
:: Install and package.
|
:: Install and package.
|
||||||
|
4
kokoro/windows-msvc-2019-release/build.bat → kokoro/windows-msvc-2013-release/build.bat
Executable file → Normal file
4
kokoro/windows-msvc-2019-release/build.bat → kokoro/windows-msvc-2013-release/build.bat
Executable file → Normal file
@ -1,4 +1,4 @@
|
|||||||
:: Copyright (c) 2023 Google LLC
|
:: Copyright (c) 2018 Google LLC.
|
||||||
::
|
::
|
||||||
:: Licensed under the Apache License, Version 2.0 (the "License");
|
:: Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
:: you may not use this file except in compliance with the License.
|
:: you may not use this file except in compliance with the License.
|
||||||
@ -20,5 +20,5 @@
|
|||||||
set SCRIPT_DIR=%~dp0
|
set SCRIPT_DIR=%~dp0
|
||||||
|
|
||||||
:: Call with correct parameter
|
:: Call with correct parameter
|
||||||
call %SCRIPT_DIR%\..\scripts\windows\build.bat RelWithDebInfo 2019
|
call %SCRIPT_DIR%\..\scripts\windows\build.bat RelWithDebInfo 2013
|
||||||
|
|
10
kokoro/windows-msvc-2019-release/continuous.cfg → kokoro/windows-msvc-2013-release/continuous.cfg
Executable file → Normal file
10
kokoro/windows-msvc-2019-release/continuous.cfg → kokoro/windows-msvc-2013-release/continuous.cfg
Executable file → Normal file
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2023 Google LLC.
|
# Copyright (c) 2018 Google LLC.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -13,10 +13,4 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# Continuous build configuration.
|
# Continuous build configuration.
|
||||||
build_file: "SPIRV-Tools/kokoro/windows-msvc-2019-release/build.bat"
|
build_file: "SPIRV-Tools/kokoro/windows-msvc-2013-release/build.bat"
|
||||||
|
|
||||||
action {
|
|
||||||
define_artifacts {
|
|
||||||
regex: "install.zip"
|
|
||||||
}
|
|
||||||
}
|
|
4
kokoro/windows-msvc-2019-release/presubmit.cfg → kokoro/windows-msvc-2013-release/presubmit.cfg
Executable file → Normal file
4
kokoro/windows-msvc-2019-release/presubmit.cfg → kokoro/windows-msvc-2013-release/presubmit.cfg
Executable file → Normal file
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2023 Google LLC.
|
# Copyright (c) 2018 Google LLC.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -13,4 +13,4 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# Presubmit build configuration.
|
# Presubmit build configuration.
|
||||||
build_file: "SPIRV-Tools/kokoro/windows-msvc-2019-release/build.bat"
|
build_file: "SPIRV-Tools/kokoro/windows-msvc-2013-release/build.bat"
|
59
kokoro/windows-msvc-2015-release-bazel/build.bat
Normal file
59
kokoro/windows-msvc-2015-release-bazel/build.bat
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
:: 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.
|
||||||
|
::
|
||||||
|
:: Windows Build Script.
|
||||||
|
|
||||||
|
@echo on
|
||||||
|
|
||||||
|
set SRC=%cd%\github\SPIRV-Tools
|
||||||
|
|
||||||
|
:: Force usage of python 3.6
|
||||||
|
set PATH=C:\python36;%PATH%
|
||||||
|
|
||||||
|
:: Get dependencies
|
||||||
|
cd %SRC%
|
||||||
|
git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
|
||||||
|
git clone https://github.com/google/googletest external/googletest
|
||||||
|
cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd ..
|
||||||
|
git clone --depth=1 https://github.com/google/effcee external/effcee
|
||||||
|
git clone --depth=1 https://github.com/google/re2 external/re2
|
||||||
|
|
||||||
|
:: REM Install Bazel.
|
||||||
|
wget -q https://github.com/bazelbuild/bazel/releases/download/5.0.0/bazel-5.0.0-windows-x86_64.zip
|
||||||
|
unzip -q bazel-5.0.0-windows-x86_64.zip
|
||||||
|
|
||||||
|
:: Set up MSVC
|
||||||
|
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
|
||||||
|
set BAZEL_VS=C:\Program Files (x86)\Microsoft Visual Studio 14.0
|
||||||
|
set BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
|
||||||
|
set BAZEL_PYTHON=c:\tools\python2\python.exe
|
||||||
|
|
||||||
|
:: #########################################
|
||||||
|
:: Start building.
|
||||||
|
:: #########################################
|
||||||
|
echo "Build everything... %DATE% %TIME%"
|
||||||
|
bazel.exe build :all
|
||||||
|
if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL%
|
||||||
|
echo "Build Completed %DATE% %TIME%"
|
||||||
|
|
||||||
|
:: ##############
|
||||||
|
:: Run the tests
|
||||||
|
:: ##############
|
||||||
|
echo "Running Tests... %DATE% %TIME%"
|
||||||
|
bazel.exe test :all
|
||||||
|
if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL%
|
||||||
|
echo "Tests Completed %DATE% %TIME%"
|
||||||
|
|
||||||
|
exit /b 0
|
||||||
|
|
16
kokoro/windows-msvc-2015-release-bazel/continuous.cfg
Normal file
16
kokoro/windows-msvc-2015-release-bazel/continuous.cfg
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
# Continuous build configuration.
|
||||||
|
build_file: "SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/build.bat"
|
16
kokoro/windows-msvc-2015-release-bazel/presubmit.cfg
Normal file
16
kokoro/windows-msvc-2015-release-bazel/presubmit.cfg
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
# Presubmit build configuration.
|
||||||
|
build_file: "SPIRV-Tools/kokoro/windows-msvc-2015-release-bazel/build.bat"
|
24
kokoro/windows-msvc-2015-release/build.bat
Normal file
24
kokoro/windows-msvc-2015-release/build.bat
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
:: Copyright (c) 2018 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.
|
||||||
|
::
|
||||||
|
:: Windows Build Script.
|
||||||
|
|
||||||
|
@echo on
|
||||||
|
|
||||||
|
:: Find out the directory of the common build script.
|
||||||
|
set SCRIPT_DIR=%~dp0
|
||||||
|
|
||||||
|
:: Call with correct parameter
|
||||||
|
call %SCRIPT_DIR%\..\scripts\windows\build.bat RelWithDebInfo 2015
|
||||||
|
|
16
kokoro/windows-msvc-2015-release/continuous.cfg
Normal file
16
kokoro/windows-msvc-2015-release/continuous.cfg
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Copyright (c) 2018 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.
|
||||||
|
|
||||||
|
# Continuous build configuration.
|
||||||
|
build_file: "SPIRV-Tools/kokoro/windows-msvc-2015-release/build.bat"
|
16
kokoro/windows-msvc-2015-release/presubmit.cfg
Normal file
16
kokoro/windows-msvc-2015-release/presubmit.cfg
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Copyright (c) 2018 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.
|
||||||
|
|
||||||
|
# Presubmit build configuration.
|
||||||
|
build_file: "SPIRV-Tools/kokoro/windows-msvc-2015-release/build.bat"
|
4
kokoro/windows-msvc-2019-debug/build.bat → kokoro/windows-msvc-2017-debug/build.bat
Executable file → Normal file
4
kokoro/windows-msvc-2019-debug/build.bat → kokoro/windows-msvc-2017-debug/build.bat
Executable file → Normal file
@ -1,4 +1,4 @@
|
|||||||
:: Copyright (c) 2023 Google LLC
|
:: Copyright (c) 2018 Google LLC.
|
||||||
::
|
::
|
||||||
:: Licensed under the Apache License, Version 2.0 (the "License");
|
:: Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
:: you may not use this file except in compliance with the License.
|
:: you may not use this file except in compliance with the License.
|
||||||
@ -20,4 +20,4 @@
|
|||||||
set SCRIPT_DIR=%~dp0
|
set SCRIPT_DIR=%~dp0
|
||||||
|
|
||||||
:: Call with correct parameter
|
:: Call with correct parameter
|
||||||
call %SCRIPT_DIR%\..\scripts\windows\build.bat Debug 2019
|
call %SCRIPT_DIR%\..\scripts\windows\build.bat Debug 2017
|
4
kokoro/windows-msvc-2019-debug/continuous.cfg → kokoro/windows-msvc-2017-debug/continuous.cfg
Executable file → Normal file
4
kokoro/windows-msvc-2019-debug/continuous.cfg → kokoro/windows-msvc-2017-debug/continuous.cfg
Executable file → Normal file
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2023 Google LLC
|
# Copyright (c) 2018 Google LLC.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -13,7 +13,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# Continuous build configuration.
|
# Continuous build configuration.
|
||||||
build_file: "SPIRV-Tools/kokoro/windows-msvc-2019-debug/build.bat"
|
build_file: "SPIRV-Tools/kokoro/windows-msvc-2017-debug/build.bat"
|
||||||
|
|
||||||
action {
|
action {
|
||||||
define_artifacts {
|
define_artifacts {
|
4
kokoro/windows-msvc-2019-debug/presubmit.cfg → kokoro/windows-msvc-2017-debug/presubmit.cfg
Executable file → Normal file
4
kokoro/windows-msvc-2019-debug/presubmit.cfg → kokoro/windows-msvc-2017-debug/presubmit.cfg
Executable file → Normal file
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2023 Google LLC
|
# Copyright (c) 2018 Google LLC.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -13,4 +13,4 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# Presubmit build configuration.
|
# Presubmit build configuration.
|
||||||
build_file: "SPIRV-Tools/kokoro/windows-msvc-2019-debug/build.bat"
|
build_file: "SPIRV-Tools/kokoro/windows-msvc-2017-debug/build.bat"
|
@ -31,13 +31,12 @@ macro(spvtools_core_tables CONFIG_VERSION)
|
|||||||
set(GRAMMAR_INSTS_INC_FILE "${spirv-tools_BINARY_DIR}/core.insts-${CONFIG_VERSION}.inc")
|
set(GRAMMAR_INSTS_INC_FILE "${spirv-tools_BINARY_DIR}/core.insts-${CONFIG_VERSION}.inc")
|
||||||
set(GRAMMAR_KINDS_INC_FILE "${spirv-tools_BINARY_DIR}/operand.kinds-${CONFIG_VERSION}.inc")
|
set(GRAMMAR_KINDS_INC_FILE "${spirv-tools_BINARY_DIR}/operand.kinds-${CONFIG_VERSION}.inc")
|
||||||
add_custom_command(OUTPUT ${GRAMMAR_INSTS_INC_FILE} ${GRAMMAR_KINDS_INC_FILE}
|
add_custom_command(OUTPUT ${GRAMMAR_INSTS_INC_FILE} ${GRAMMAR_KINDS_INC_FILE}
|
||||||
COMMAND Python3::Interpreter ${GRAMMAR_PROCESSING_SCRIPT}
|
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
|
||||||
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
|
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
|
||||||
--extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
|
--extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
|
||||||
--extinst-cldebuginfo100-grammar=${CLDEBUGINFO100_GRAMMAR_JSON_FILE}
|
--extinst-cldebuginfo100-grammar=${CLDEBUGINFO100_GRAMMAR_JSON_FILE}
|
||||||
--core-insts-output=${GRAMMAR_INSTS_INC_FILE}
|
--core-insts-output=${GRAMMAR_INSTS_INC_FILE}
|
||||||
--operand-kinds-output=${GRAMMAR_KINDS_INC_FILE}
|
--operand-kinds-output=${GRAMMAR_KINDS_INC_FILE}
|
||||||
--output-language=c++
|
|
||||||
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT}
|
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT}
|
||||||
${GRAMMAR_JSON_FILE}
|
${GRAMMAR_JSON_FILE}
|
||||||
${DEBUGINFO_GRAMMAR_JSON_FILE}
|
${DEBUGINFO_GRAMMAR_JSON_FILE}
|
||||||
@ -53,13 +52,12 @@ macro(spvtools_enum_string_mapping CONFIG_VERSION)
|
|||||||
set(GRAMMAR_ENUM_STRING_MAPPING_INC_FILE "${spirv-tools_BINARY_DIR}/enum_string_mapping.inc")
|
set(GRAMMAR_ENUM_STRING_MAPPING_INC_FILE "${spirv-tools_BINARY_DIR}/enum_string_mapping.inc")
|
||||||
add_custom_command(OUTPUT ${GRAMMAR_EXTENSION_ENUM_INC_FILE}
|
add_custom_command(OUTPUT ${GRAMMAR_EXTENSION_ENUM_INC_FILE}
|
||||||
${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}
|
${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}
|
||||||
COMMAND Python3::Interpreter ${GRAMMAR_PROCESSING_SCRIPT}
|
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
|
||||||
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
|
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
|
||||||
--extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
|
--extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
|
||||||
--extinst-cldebuginfo100-grammar=${CLDEBUGINFO100_GRAMMAR_JSON_FILE}
|
--extinst-cldebuginfo100-grammar=${CLDEBUGINFO100_GRAMMAR_JSON_FILE}
|
||||||
--extension-enum-output=${GRAMMAR_EXTENSION_ENUM_INC_FILE}
|
--extension-enum-output=${GRAMMAR_EXTENSION_ENUM_INC_FILE}
|
||||||
--enum-string-mapping-output=${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}
|
--enum-string-mapping-output=${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}
|
||||||
--output-language=c++
|
|
||||||
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT}
|
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT}
|
||||||
${GRAMMAR_JSON_FILE}
|
${GRAMMAR_JSON_FILE}
|
||||||
${DEBUGINFO_GRAMMAR_JSON_FILE}
|
${DEBUGINFO_GRAMMAR_JSON_FILE}
|
||||||
@ -75,7 +73,7 @@ macro(spvtools_vimsyntax CONFIG_VERSION CLVERSION)
|
|||||||
set(OPENCL_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${CONFIG_VERSION}/extinst.opencl.std.100.grammar.json")
|
set(OPENCL_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${CONFIG_VERSION}/extinst.opencl.std.100.grammar.json")
|
||||||
set(VIMSYNTAX_FILE "${spirv-tools_BINARY_DIR}/spvasm.vim")
|
set(VIMSYNTAX_FILE "${spirv-tools_BINARY_DIR}/spvasm.vim")
|
||||||
add_custom_command(OUTPUT ${VIMSYNTAX_FILE}
|
add_custom_command(OUTPUT ${VIMSYNTAX_FILE}
|
||||||
COMMAND Python3::Interpreter ${VIMSYNTAX_PROCESSING_SCRIPT}
|
COMMAND ${PYTHON_EXECUTABLE} ${VIMSYNTAX_PROCESSING_SCRIPT}
|
||||||
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
|
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
|
||||||
--extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
|
--extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
|
||||||
--extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
|
--extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
|
||||||
@ -91,10 +89,9 @@ macro(spvtools_glsl_tables CONFIG_VERSION)
|
|||||||
set(GLSL_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${CONFIG_VERSION}/extinst.glsl.std.450.grammar.json")
|
set(GLSL_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${CONFIG_VERSION}/extinst.glsl.std.450.grammar.json")
|
||||||
set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/glsl.std.450.insts.inc")
|
set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/glsl.std.450.insts.inc")
|
||||||
add_custom_command(OUTPUT ${GRAMMAR_INC_FILE}
|
add_custom_command(OUTPUT ${GRAMMAR_INC_FILE}
|
||||||
COMMAND Python3::Interpreter ${GRAMMAR_PROCESSING_SCRIPT}
|
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
|
||||||
--extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
|
--extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
|
||||||
--glsl-insts-output=${GRAMMAR_INC_FILE}
|
--glsl-insts-output=${GRAMMAR_INC_FILE}
|
||||||
--output-language=c++
|
|
||||||
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${GLSL_GRAMMAR_JSON_FILE}
|
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${GLSL_GRAMMAR_JSON_FILE}
|
||||||
COMMENT "Generate info tables for GLSL extended instructions and operands v${CONFIG_VERSION}.")
|
COMMENT "Generate info tables for GLSL extended instructions and operands v${CONFIG_VERSION}.")
|
||||||
list(APPEND EXTINST_CPP_DEPENDS ${GRAMMAR_INC_FILE})
|
list(APPEND EXTINST_CPP_DEPENDS ${GRAMMAR_INC_FILE})
|
||||||
@ -105,7 +102,7 @@ macro(spvtools_opencl_tables CONFIG_VERSION)
|
|||||||
set(OPENCL_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${CONFIG_VERSION}/extinst.opencl.std.100.grammar.json")
|
set(OPENCL_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${CONFIG_VERSION}/extinst.opencl.std.100.grammar.json")
|
||||||
set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/opencl.std.insts.inc")
|
set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/opencl.std.insts.inc")
|
||||||
add_custom_command(OUTPUT ${GRAMMAR_INC_FILE}
|
add_custom_command(OUTPUT ${GRAMMAR_INC_FILE}
|
||||||
COMMAND Python3::Interpreter ${GRAMMAR_PROCESSING_SCRIPT}
|
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
|
||||||
--extinst-opencl-grammar=${OPENCL_GRAMMAR_JSON_FILE}
|
--extinst-opencl-grammar=${OPENCL_GRAMMAR_JSON_FILE}
|
||||||
--opencl-insts-output=${GRAMMAR_INC_FILE}
|
--opencl-insts-output=${GRAMMAR_INC_FILE}
|
||||||
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${OPENCL_GRAMMAR_JSON_FILE}
|
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${OPENCL_GRAMMAR_JSON_FILE}
|
||||||
@ -120,7 +117,7 @@ macro(spvtools_vendor_tables VENDOR_TABLE SHORT_NAME OPERAND_KIND_PREFIX)
|
|||||||
set(GRAMMAR_FILE "${spirv-tools_SOURCE_DIR}/source/extinst.${VENDOR_TABLE}.grammar.json")
|
set(GRAMMAR_FILE "${spirv-tools_SOURCE_DIR}/source/extinst.${VENDOR_TABLE}.grammar.json")
|
||||||
endif()
|
endif()
|
||||||
add_custom_command(OUTPUT ${INSTS_FILE}
|
add_custom_command(OUTPUT ${INSTS_FILE}
|
||||||
COMMAND Python3::Interpreter ${GRAMMAR_PROCESSING_SCRIPT}
|
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
|
||||||
--extinst-vendor-grammar=${GRAMMAR_FILE}
|
--extinst-vendor-grammar=${GRAMMAR_FILE}
|
||||||
--vendor-insts-output=${INSTS_FILE}
|
--vendor-insts-output=${INSTS_FILE}
|
||||||
--vendor-operand-kind-prefix=${OPERAND_KIND_PREFIX}
|
--vendor-operand-kind-prefix=${OPERAND_KIND_PREFIX}
|
||||||
@ -134,7 +131,7 @@ endmacro(spvtools_vendor_tables)
|
|||||||
macro(spvtools_extinst_lang_headers NAME GRAMMAR_FILE)
|
macro(spvtools_extinst_lang_headers NAME GRAMMAR_FILE)
|
||||||
set(OUT_H ${spirv-tools_BINARY_DIR}/${NAME}.h)
|
set(OUT_H ${spirv-tools_BINARY_DIR}/${NAME}.h)
|
||||||
add_custom_command(OUTPUT ${OUT_H}
|
add_custom_command(OUTPUT ${OUT_H}
|
||||||
COMMAND Python3::Interpreter ${LANG_HEADER_PROCESSING_SCRIPT}
|
COMMAND ${PYTHON_EXECUTABLE} ${LANG_HEADER_PROCESSING_SCRIPT}
|
||||||
--extinst-grammar=${GRAMMAR_FILE}
|
--extinst-grammar=${GRAMMAR_FILE}
|
||||||
--extinst-output-path=${OUT_H}
|
--extinst-output-path=${OUT_H}
|
||||||
DEPENDS ${LANG_HEADER_PROCESSING_SCRIPT} ${GRAMMAR_FILE}
|
DEPENDS ${LANG_HEADER_PROCESSING_SCRIPT} ${GRAMMAR_FILE}
|
||||||
@ -168,7 +165,7 @@ set_property(TARGET spirv-tools-vimsyntax PROPERTY FOLDER "SPIRV-Tools utilities
|
|||||||
set(GENERATOR_INC_FILE ${spirv-tools_BINARY_DIR}/generators.inc)
|
set(GENERATOR_INC_FILE ${spirv-tools_BINARY_DIR}/generators.inc)
|
||||||
set(SPIRV_XML_REGISTRY_FILE ${SPIRV_HEADER_INCLUDE_DIR}/spirv/spir-v.xml)
|
set(SPIRV_XML_REGISTRY_FILE ${SPIRV_HEADER_INCLUDE_DIR}/spirv/spir-v.xml)
|
||||||
add_custom_command(OUTPUT ${GENERATOR_INC_FILE}
|
add_custom_command(OUTPUT ${GENERATOR_INC_FILE}
|
||||||
COMMAND Python3::Interpreter ${XML_REGISTRY_PROCESSING_SCRIPT}
|
COMMAND ${PYTHON_EXECUTABLE} ${XML_REGISTRY_PROCESSING_SCRIPT}
|
||||||
--xml=${SPIRV_XML_REGISTRY_FILE}
|
--xml=${SPIRV_XML_REGISTRY_FILE}
|
||||||
--generator-output=${GENERATOR_INC_FILE}
|
--generator-output=${GENERATOR_INC_FILE}
|
||||||
DEPENDS ${XML_REGISTRY_PROCESSING_SCRIPT} ${SPIRV_XML_REGISTRY_FILE}
|
DEPENDS ${XML_REGISTRY_PROCESSING_SCRIPT} ${SPIRV_XML_REGISTRY_FILE}
|
||||||
@ -198,7 +195,7 @@ set(SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR
|
|||||||
set(SPIRV_TOOLS_CHANGES_FILE
|
set(SPIRV_TOOLS_CHANGES_FILE
|
||||||
${spirv-tools_SOURCE_DIR}/CHANGES)
|
${spirv-tools_SOURCE_DIR}/CHANGES)
|
||||||
add_custom_command(OUTPUT ${SPIRV_TOOLS_BUILD_VERSION_INC}
|
add_custom_command(OUTPUT ${SPIRV_TOOLS_BUILD_VERSION_INC}
|
||||||
COMMAND Python3::Interpreter
|
COMMAND ${PYTHON_EXECUTABLE}
|
||||||
${SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR}
|
${SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR}
|
||||||
${SPIRV_TOOLS_CHANGES_FILE} ${SPIRV_TOOLS_BUILD_VERSION_INC}
|
${SPIRV_TOOLS_CHANGES_FILE} ${SPIRV_TOOLS_BUILD_VERSION_INC}
|
||||||
DEPENDS ${SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR}
|
DEPENDS ${SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR}
|
||||||
@ -328,7 +325,6 @@ set(SPIRV_SOURCES
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_primitives.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_primitives.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_ray_query.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_ray_query.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_ray_tracing.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_ray_tracing.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_ray_tracing_reorder.cpp
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_scopes.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_scopes.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_small_type_uses.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_small_type_uses.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_type.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/val/validate_type.cpp
|
||||||
@ -418,8 +414,17 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (ANDROID)
|
||||||
|
foreach(target ${SPIRV_TOOLS_TARGETS})
|
||||||
|
target_link_libraries(${target} PRIVATE android log)
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||||
install(TARGETS ${SPIRV_TOOLS_TARGETS} EXPORT ${SPIRV_TOOLS}Targets)
|
install(TARGETS ${SPIRV_TOOLS_TARGETS} EXPORT ${SPIRV_TOOLS}Targets
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
export(EXPORT ${SPIRV_TOOLS}Targets FILE ${SPIRV_TOOLS}Target.cmake)
|
export(EXPORT ${SPIRV_TOOLS}Targets FILE ${SPIRV_TOOLS}Target.cmake)
|
||||||
|
|
||||||
spvtools_config_package_dir(${SPIRV_TOOLS} PACKAGE_DIR)
|
spvtools_config_package_dir(${SPIRV_TOOLS} PACKAGE_DIR)
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include "source/ext_inst.h"
|
#include "source/ext_inst.h"
|
||||||
#include "source/opcode.h"
|
#include "source/opcode.h"
|
||||||
#include "source/operand.h"
|
#include "source/operand.h"
|
||||||
#include "source/spirv_target_env.h"
|
|
||||||
#include "source/table.h"
|
#include "source/table.h"
|
||||||
|
|
||||||
namespace spvtools {
|
namespace spvtools {
|
||||||
@ -79,16 +78,16 @@ spv_result_t spvTextParseMaskOperand(spv_target_env env,
|
|||||||
|
|
||||||
// Associates an opcode with its name.
|
// Associates an opcode with its name.
|
||||||
struct SpecConstantOpcodeEntry {
|
struct SpecConstantOpcodeEntry {
|
||||||
spv::Op opcode;
|
SpvOp opcode;
|
||||||
const char* name;
|
const char* name;
|
||||||
};
|
};
|
||||||
|
|
||||||
// All the opcodes allowed as the operation for OpSpecConstantOp.
|
// All the opcodes allowed as the operation for OpSpecConstantOp.
|
||||||
// The name does not have the usual "Op" prefix. For example opcode
|
// The name does not have the usual "Op" prefix. For example opcode SpvOpIAdd
|
||||||
// spv::Op::IAdd is associated with the name "IAdd".
|
// is associated with the name "IAdd".
|
||||||
//
|
//
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#define CASE(NAME) { spv::Op::Op##NAME, #NAME }
|
#define CASE(NAME) { SpvOp##NAME, #NAME }
|
||||||
const SpecConstantOpcodeEntry kOpSpecConstantOpcodes[] = {
|
const SpecConstantOpcodeEntry kOpSpecConstantOpcodes[] = {
|
||||||
// Conversion
|
// Conversion
|
||||||
CASE(SConvert),
|
CASE(SConvert),
|
||||||
@ -155,12 +154,11 @@ const SpecConstantOpcodeEntry kOpSpecConstantOpcodes[] = {
|
|||||||
CASE(InBoundsAccessChain),
|
CASE(InBoundsAccessChain),
|
||||||
CASE(PtrAccessChain),
|
CASE(PtrAccessChain),
|
||||||
CASE(InBoundsPtrAccessChain),
|
CASE(InBoundsPtrAccessChain),
|
||||||
CASE(CooperativeMatrixLengthNV),
|
CASE(CooperativeMatrixLengthNV)
|
||||||
CASE(CooperativeMatrixLengthKHR)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The 60 is determined by counting the opcodes listed in the spec.
|
// The 60 is determined by counting the opcodes listed in the spec.
|
||||||
static_assert(61 == sizeof(kOpSpecConstantOpcodes)/sizeof(kOpSpecConstantOpcodes[0]),
|
static_assert(60 == sizeof(kOpSpecConstantOpcodes)/sizeof(kOpSpecConstantOpcodes[0]),
|
||||||
"OpSpecConstantOp opcode table is incomplete");
|
"OpSpecConstantOp opcode table is incomplete");
|
||||||
#undef CASE
|
#undef CASE
|
||||||
// clang-format on
|
// clang-format on
|
||||||
@ -175,20 +173,17 @@ bool AssemblyGrammar::isValid() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CapabilitySet AssemblyGrammar::filterCapsAgainstTargetEnv(
|
CapabilitySet AssemblyGrammar::filterCapsAgainstTargetEnv(
|
||||||
const spv::Capability* cap_array, uint32_t count) const {
|
const SpvCapability* cap_array, uint32_t count) const {
|
||||||
CapabilitySet cap_set;
|
CapabilitySet cap_set;
|
||||||
const auto version = spvVersionForTargetEnv(target_env_);
|
|
||||||
for (uint32_t i = 0; i < count; ++i) {
|
for (uint32_t i = 0; i < count; ++i) {
|
||||||
spv_operand_desc entry = {};
|
spv_operand_desc cap_desc = {};
|
||||||
if (SPV_SUCCESS == lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
|
if (SPV_SUCCESS == lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
|
||||||
static_cast<uint32_t>(cap_array[i]),
|
static_cast<uint32_t>(cap_array[i]),
|
||||||
&entry)) {
|
&cap_desc)) {
|
||||||
// This token is visible in this environment if it's in an appropriate
|
// spvOperandTableValueLookup() filters capabilities internally
|
||||||
// core version, or it is enabled by a capability or an extension.
|
// according to the current target environment by itself. So we
|
||||||
if ((version >= entry->minVersion && version <= entry->lastVersion) ||
|
// should be safe to add this capability if the lookup succeeds.
|
||||||
entry->numExtensions > 0u || entry->numCapabilities > 0u) {
|
cap_set.Add(cap_array[i]);
|
||||||
cap_set.insert(cap_array[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cap_set;
|
return cap_set;
|
||||||
@ -199,7 +194,7 @@ spv_result_t AssemblyGrammar::lookupOpcode(const char* name,
|
|||||||
return spvOpcodeTableNameLookup(target_env_, opcodeTable_, name, desc);
|
return spvOpcodeTableNameLookup(target_env_, opcodeTable_, name, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
spv_result_t AssemblyGrammar::lookupOpcode(spv::Op opcode,
|
spv_result_t AssemblyGrammar::lookupOpcode(SpvOp opcode,
|
||||||
spv_opcode_desc* desc) const {
|
spv_opcode_desc* desc) const {
|
||||||
return spvOpcodeTableValueLookup(target_env_, opcodeTable_, opcode, desc);
|
return spvOpcodeTableValueLookup(target_env_, opcodeTable_, opcode, desc);
|
||||||
}
|
}
|
||||||
@ -219,7 +214,7 @@ spv_result_t AssemblyGrammar::lookupOperand(spv_operand_type_t type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(const char* name,
|
spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(const char* name,
|
||||||
spv::Op* opcode) const {
|
SpvOp* opcode) const {
|
||||||
const auto* last = kOpSpecConstantOpcodes + kNumOpSpecConstantOpcodes;
|
const auto* last = kOpSpecConstantOpcodes + kNumOpSpecConstantOpcodes;
|
||||||
const auto* found =
|
const auto* found =
|
||||||
std::find_if(kOpSpecConstantOpcodes, last,
|
std::find_if(kOpSpecConstantOpcodes, last,
|
||||||
@ -231,7 +226,7 @@ spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(const char* name,
|
|||||||
return SPV_SUCCESS;
|
return SPV_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(spv::Op opcode) const {
|
spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(SpvOp opcode) const {
|
||||||
const auto* last = kOpSpecConstantOpcodes + kNumOpSpecConstantOpcodes;
|
const auto* last = kOpSpecConstantOpcodes + kNumOpSpecConstantOpcodes;
|
||||||
const auto* found =
|
const auto* found =
|
||||||
std::find_if(kOpSpecConstantOpcodes, last,
|
std::find_if(kOpSpecConstantOpcodes, last,
|
||||||
|
@ -41,7 +41,7 @@ class AssemblyGrammar {
|
|||||||
|
|
||||||
// Removes capabilities not available in the current target environment and
|
// Removes capabilities not available in the current target environment and
|
||||||
// returns the rest.
|
// returns the rest.
|
||||||
CapabilitySet filterCapsAgainstTargetEnv(const spv::Capability* cap_array,
|
CapabilitySet filterCapsAgainstTargetEnv(const SpvCapability* cap_array,
|
||||||
uint32_t count) const;
|
uint32_t count) const;
|
||||||
|
|
||||||
// Fills in the desc parameter with the information about the opcode
|
// Fills in the desc parameter with the information about the opcode
|
||||||
@ -52,7 +52,7 @@ class AssemblyGrammar {
|
|||||||
// Fills in the desc parameter with the information about the opcode
|
// Fills in the desc parameter with the information about the opcode
|
||||||
// of the valid. Returns SPV_SUCCESS if the opcode was found, and
|
// of the valid. Returns SPV_SUCCESS if the opcode was found, and
|
||||||
// SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
|
// SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
|
||||||
spv_result_t lookupOpcode(spv::Op opcode, spv_opcode_desc* desc) const;
|
spv_result_t lookupOpcode(SpvOp opcode, spv_opcode_desc* desc) const;
|
||||||
|
|
||||||
// Fills in the desc parameter with the information about the given
|
// Fills in the desc parameter with the information about the given
|
||||||
// operand. Returns SPV_SUCCESS if the operand was found, and
|
// operand. Returns SPV_SUCCESS if the operand was found, and
|
||||||
@ -82,12 +82,11 @@ class AssemblyGrammar {
|
|||||||
// the integer add opcode for OpSpecConstantOp. On success, returns
|
// the integer add opcode for OpSpecConstantOp. On success, returns
|
||||||
// SPV_SUCCESS and sends the discovered operation code through the opcode
|
// SPV_SUCCESS and sends the discovered operation code through the opcode
|
||||||
// parameter. On failure, returns SPV_ERROR_INVALID_LOOKUP.
|
// parameter. On failure, returns SPV_ERROR_INVALID_LOOKUP.
|
||||||
spv_result_t lookupSpecConstantOpcode(const char* name,
|
spv_result_t lookupSpecConstantOpcode(const char* name, SpvOp* opcode) const;
|
||||||
spv::Op* opcode) const;
|
|
||||||
|
|
||||||
// Returns SPV_SUCCESS if the given opcode is valid as the opcode operand
|
// Returns SPV_SUCCESS if the given opcode is valid as the opcode operand
|
||||||
// to OpSpecConstantOp.
|
// to OpSpecConstantOp.
|
||||||
spv_result_t lookupSpecConstantOpcode(spv::Op opcode) const;
|
spv_result_t lookupSpecConstantOpcode(SpvOp opcode) const;
|
||||||
|
|
||||||
// Parses a mask expression string for the given operand type.
|
// Parses a mask expression string for the given operand type.
|
||||||
//
|
//
|
||||||
|
@ -156,7 +156,7 @@ class Parser {
|
|||||||
// Issues a diagnostic describing an exhaustion of input condition when
|
// Issues a diagnostic describing an exhaustion of input condition when
|
||||||
// trying to decode an instruction operand, and returns
|
// trying to decode an instruction operand, and returns
|
||||||
// SPV_ERROR_INVALID_BINARY.
|
// SPV_ERROR_INVALID_BINARY.
|
||||||
spv_result_t exhaustedInputDiagnostic(size_t inst_offset, spv::Op opcode,
|
spv_result_t exhaustedInputDiagnostic(size_t inst_offset, SpvOp opcode,
|
||||||
spv_operand_type_t type) {
|
spv_operand_type_t type) {
|
||||||
return diagnostic() << "End of input reached while decoding Op"
|
return diagnostic() << "End of input reached while decoding Op"
|
||||||
<< spvOpcodeString(opcode) << " starting at word "
|
<< spvOpcodeString(opcode) << " starting at word "
|
||||||
@ -318,7 +318,7 @@ spv_result_t Parser::parseInstruction() {
|
|||||||
<< inst_word_count;
|
<< inst_word_count;
|
||||||
}
|
}
|
||||||
spv_opcode_desc opcode_desc;
|
spv_opcode_desc opcode_desc;
|
||||||
if (grammar_.lookupOpcode(static_cast<spv::Op>(inst.opcode), &opcode_desc))
|
if (grammar_.lookupOpcode(static_cast<SpvOp>(inst.opcode), &opcode_desc))
|
||||||
return diagnostic() << "Invalid opcode: " << inst.opcode;
|
return diagnostic() << "Invalid opcode: " << inst.opcode;
|
||||||
|
|
||||||
// Advance past the opcode word. But remember the of the start
|
// Advance past the opcode word. But remember the of the start
|
||||||
@ -418,7 +418,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
|||||||
std::vector<uint32_t>* words,
|
std::vector<uint32_t>* words,
|
||||||
std::vector<spv_parsed_operand_t>* operands,
|
std::vector<spv_parsed_operand_t>* operands,
|
||||||
spv_operand_pattern_t* expected_operands) {
|
spv_operand_pattern_t* expected_operands) {
|
||||||
const spv::Op opcode = static_cast<spv::Op>(inst->opcode);
|
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||||
// We'll fill in this result as we go along.
|
// We'll fill in this result as we go along.
|
||||||
spv_parsed_operand_t parsed_operand;
|
spv_parsed_operand_t parsed_operand;
|
||||||
parsed_operand.offset = uint16_t(_.word_index - inst_offset);
|
parsed_operand.offset = uint16_t(_.word_index - inst_offset);
|
||||||
@ -473,7 +473,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
|||||||
if (!word) return diagnostic(SPV_ERROR_INVALID_ID) << "Id is 0";
|
if (!word) return diagnostic(SPV_ERROR_INVALID_ID) << "Id is 0";
|
||||||
parsed_operand.type = SPV_OPERAND_TYPE_ID;
|
parsed_operand.type = SPV_OPERAND_TYPE_ID;
|
||||||
|
|
||||||
if (opcode == spv::Op::OpExtInst && parsed_operand.offset == 3) {
|
if (opcode == SpvOpExtInst && parsed_operand.offset == 3) {
|
||||||
// The current word is the extended instruction set Id.
|
// The current word is the extended instruction set Id.
|
||||||
// Set the extended instruction set type for the current instruction.
|
// Set the extended instruction set type for the current instruction.
|
||||||
auto ext_inst_type_iter = _.import_id_to_ext_inst_type.find(word);
|
auto ext_inst_type_iter = _.import_id_to_ext_inst_type.find(word);
|
||||||
@ -494,7 +494,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
|
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
|
||||||
assert(spv::Op::OpExtInst == opcode);
|
assert(SpvOpExtInst == opcode);
|
||||||
assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE);
|
assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE);
|
||||||
spv_ext_inst_desc ext_inst;
|
spv_ext_inst_desc ext_inst;
|
||||||
if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst) ==
|
if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst) ==
|
||||||
@ -516,14 +516,14 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
|
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
|
||||||
assert(spv::Op::OpSpecConstantOp == opcode);
|
assert(SpvOpSpecConstantOp == opcode);
|
||||||
if (word > static_cast<uint32_t>(spv::Op::Max) ||
|
if (word > static_cast<uint32_t>(SpvOp::SpvOpMax) ||
|
||||||
grammar_.lookupSpecConstantOpcode(spv::Op(word))) {
|
grammar_.lookupSpecConstantOpcode(SpvOp(word))) {
|
||||||
return diagnostic()
|
return diagnostic()
|
||||||
<< "Invalid " << spvOperandTypeStr(type) << ": " << word;
|
<< "Invalid " << spvOperandTypeStr(type) << ": " << word;
|
||||||
}
|
}
|
||||||
spv_opcode_desc opcode_entry = nullptr;
|
spv_opcode_desc opcode_entry = nullptr;
|
||||||
if (grammar_.lookupOpcode(spv::Op(word), &opcode_entry)) {
|
if (grammar_.lookupOpcode(SpvOp(word), &opcode_entry)) {
|
||||||
return diagnostic(SPV_ERROR_INTERNAL)
|
return diagnostic(SPV_ERROR_INTERNAL)
|
||||||
<< "OpSpecConstant opcode table out of sync";
|
<< "OpSpecConstant opcode table out of sync";
|
||||||
}
|
}
|
||||||
@ -546,17 +546,10 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
|||||||
parsed_operand.number_bit_width = 32;
|
parsed_operand.number_bit_width = 32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPV_OPERAND_TYPE_LITERAL_FLOAT:
|
|
||||||
// These are regular single-word literal float operands.
|
|
||||||
parsed_operand.type = SPV_OPERAND_TYPE_LITERAL_FLOAT;
|
|
||||||
parsed_operand.number_kind = SPV_NUMBER_FLOATING;
|
|
||||||
parsed_operand.number_bit_width = 32;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
|
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
|
||||||
case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
|
case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
|
||||||
parsed_operand.type = SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
|
parsed_operand.type = SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
|
||||||
if (opcode == spv::Op::OpSwitch) {
|
if (opcode == SpvOpSwitch) {
|
||||||
// The literal operands have the same type as the value
|
// The literal operands have the same type as the value
|
||||||
// referenced by the selector Id.
|
// referenced by the selector Id.
|
||||||
const uint32_t selector_id = peekAt(inst_offset + 1);
|
const uint32_t selector_id = peekAt(inst_offset + 1);
|
||||||
@ -582,8 +575,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
|||||||
<< " is not a scalar integer";
|
<< " is not a scalar integer";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(opcode == spv::Op::OpConstant ||
|
assert(opcode == SpvOpConstant || opcode == SpvOpSpecConstant);
|
||||||
opcode == spv::Op::OpSpecConstant);
|
|
||||||
// The literal number type is determined by the type Id for the
|
// The literal number type is determined by the type Id for the
|
||||||
// constant.
|
// constant.
|
||||||
assert(inst->type_id);
|
assert(inst->type_id);
|
||||||
@ -615,7 +607,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
|||||||
parsed_operand.num_words = uint16_t(string_num_words);
|
parsed_operand.num_words = uint16_t(string_num_words);
|
||||||
parsed_operand.type = SPV_OPERAND_TYPE_LITERAL_STRING;
|
parsed_operand.type = SPV_OPERAND_TYPE_LITERAL_STRING;
|
||||||
|
|
||||||
if (spv::Op::OpExtInstImport == opcode) {
|
if (SpvOpExtInstImport == opcode) {
|
||||||
// Record the extended instruction type for the ID for this import.
|
// Record the extended instruction type for the ID for this import.
|
||||||
// There is only one string literal argument to OpExtInstImport,
|
// There is only one string literal argument to OpExtInstImport,
|
||||||
// so it's sufficient to guard this just on the opcode.
|
// so it's sufficient to guard this just on the opcode.
|
||||||
@ -633,6 +625,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SPV_OPERAND_TYPE_CAPABILITY:
|
case SPV_OPERAND_TYPE_CAPABILITY:
|
||||||
|
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||||
case SPV_OPERAND_TYPE_EXECUTION_MODEL:
|
case SPV_OPERAND_TYPE_EXECUTION_MODEL:
|
||||||
case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
|
case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
|
||||||
case SPV_OPERAND_TYPE_MEMORY_MODEL:
|
case SPV_OPERAND_TYPE_MEMORY_MODEL:
|
||||||
@ -689,21 +682,6 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
|||||||
spvPushOperandTypes(entry->operandTypes, expected_operands);
|
spvPushOperandTypes(entry->operandTypes, expected_operands);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE: {
|
|
||||||
spv_operand_desc entry;
|
|
||||||
if (grammar_.lookupOperand(type, word, &entry)) {
|
|
||||||
return diagnostic()
|
|
||||||
<< "Invalid " << spvOperandTypeStr(parsed_operand.type)
|
|
||||||
<< " operand: " << word
|
|
||||||
<< ", if you are creating a new source language please use "
|
|
||||||
"value 0 "
|
|
||||||
"(Unknown) and when ready, add your source language to "
|
|
||||||
"SPRIV-Headers";
|
|
||||||
}
|
|
||||||
// Prepare to accept operands to this operand, if needed.
|
|
||||||
spvPushOperandTypes(entry->operandTypes, expected_operands);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
|
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
|
||||||
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
|
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
|
||||||
case SPV_OPERAND_TYPE_LOOP_CONTROL:
|
case SPV_OPERAND_TYPE_LOOP_CONTROL:
|
||||||
@ -712,9 +690,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
|||||||
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
|
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
|
||||||
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
|
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
|
||||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
|
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
|
||||||
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
|
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: {
|
||||||
case SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS:
|
|
||||||
case SPV_OPERAND_TYPE_OPTIONAL_COOPERATIVE_MATRIX_OPERANDS: {
|
|
||||||
// This operand is a mask.
|
// This operand is a mask.
|
||||||
|
|
||||||
// Map an optional operand type to its corresponding concrete type.
|
// Map an optional operand type to its corresponding concrete type.
|
||||||
@ -722,8 +698,6 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
|||||||
parsed_operand.type = SPV_OPERAND_TYPE_IMAGE;
|
parsed_operand.type = SPV_OPERAND_TYPE_IMAGE;
|
||||||
else if (type == SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS)
|
else if (type == SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS)
|
||||||
parsed_operand.type = SPV_OPERAND_TYPE_MEMORY_ACCESS;
|
parsed_operand.type = SPV_OPERAND_TYPE_MEMORY_ACCESS;
|
||||||
if (type == SPV_OPERAND_TYPE_OPTIONAL_COOPERATIVE_MATRIX_OPERANDS)
|
|
||||||
parsed_operand.type = SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS;
|
|
||||||
|
|
||||||
// Check validity of set mask bits. Also prepare for operands for those
|
// Check validity of set mask bits. Also prepare for operands for those
|
||||||
// masks if they have any. To get operand order correct, scan from
|
// masks if they have any. To get operand order correct, scan from
|
||||||
@ -815,14 +789,14 @@ spv_result_t Parser::setNumericTypeInfoForType(
|
|||||||
|
|
||||||
void Parser::recordNumberType(size_t inst_offset,
|
void Parser::recordNumberType(size_t inst_offset,
|
||||||
const spv_parsed_instruction_t* inst) {
|
const spv_parsed_instruction_t* inst) {
|
||||||
const spv::Op opcode = static_cast<spv::Op>(inst->opcode);
|
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||||
if (spvOpcodeGeneratesType(opcode)) {
|
if (spvOpcodeGeneratesType(opcode)) {
|
||||||
NumberType info = {SPV_NUMBER_NONE, 0};
|
NumberType info = {SPV_NUMBER_NONE, 0};
|
||||||
if (spv::Op::OpTypeInt == opcode) {
|
if (SpvOpTypeInt == opcode) {
|
||||||
const bool is_signed = peekAt(inst_offset + 3) != 0;
|
const bool is_signed = peekAt(inst_offset + 3) != 0;
|
||||||
info.type = is_signed ? SPV_NUMBER_SIGNED_INT : SPV_NUMBER_UNSIGNED_INT;
|
info.type = is_signed ? SPV_NUMBER_SIGNED_INT : SPV_NUMBER_UNSIGNED_INT;
|
||||||
info.bit_width = peekAt(inst_offset + 2);
|
info.bit_width = peekAt(inst_offset + 2);
|
||||||
} else if (spv::Op::OpTypeFloat == opcode) {
|
} else if (SpvOpTypeFloat == opcode) {
|
||||||
info.type = SPV_NUMBER_FLOATING;
|
info.type = SPV_NUMBER_FLOATING;
|
||||||
info.bit_width = peekAt(inst_offset + 2);
|
info.bit_width = peekAt(inst_offset + 2);
|
||||||
}
|
}
|
||||||
|
@ -275,16 +275,10 @@ std::vector<std::pair<BB*, BB*>> CFA<BB>::CalculateDominators(
|
|||||||
|
|
||||||
std::vector<std::pair<bb_ptr, bb_ptr>> out;
|
std::vector<std::pair<bb_ptr, bb_ptr>> out;
|
||||||
for (auto idom : idoms) {
|
for (auto idom : idoms) {
|
||||||
// At this point if there is no dominator for the node, just make it
|
|
||||||
// reflexive.
|
|
||||||
auto dominator = std::get<1>(idom).dominator;
|
|
||||||
if (dominator == undefined_dom) {
|
|
||||||
dominator = std::get<1>(idom).postorder_index;
|
|
||||||
}
|
|
||||||
// NOTE: performing a const cast for convenient usage with
|
// NOTE: performing a const cast for convenient usage with
|
||||||
// UpdateImmediateDominators
|
// UpdateImmediateDominators
|
||||||
out.push_back({const_cast<BB*>(std::get<0>(idom)),
|
out.push_back({const_cast<BB*>(std::get<0>(idom)),
|
||||||
const_cast<BB*>(postorder[dominator])});
|
const_cast<BB*>(postorder[std::get<1>(idom).dominator])});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort by postorder index to generate a deterministic ordering of edges.
|
// Sort by postorder index to generate a deterministic ordering of edges.
|
||||||
|
@ -39,7 +39,10 @@ set_property(TARGET SPIRV-Tools-diff PROPERTY FOLDER "SPIRV-Tools libraries")
|
|||||||
spvtools_check_symbol_exports(SPIRV-Tools-diff)
|
spvtools_check_symbol_exports(SPIRV-Tools-diff)
|
||||||
|
|
||||||
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||||
install(TARGETS SPIRV-Tools-diff EXPORT SPIRV-Tools-diffTargets)
|
install(TARGETS SPIRV-Tools-diff EXPORT SPIRV-Tools-diffTargets
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
export(EXPORT SPIRV-Tools-diffTargets FILE SPIRV-Tools-diffTargets.cmake)
|
export(EXPORT SPIRV-Tools-diffTargets FILE SPIRV-Tools-diffTargets.cmake)
|
||||||
|
|
||||||
spvtools_config_package_dir(SPIRV-Tools-diff PACKAGE_DIR)
|
spvtools_config_package_dir(SPIRV-Tools-diff PACKAGE_DIR)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -244,7 +244,7 @@ void InstructionDisassembler::EmitHeaderSchema(uint32_t schema) {
|
|||||||
|
|
||||||
void InstructionDisassembler::EmitInstruction(
|
void InstructionDisassembler::EmitInstruction(
|
||||||
const spv_parsed_instruction_t& inst, size_t inst_byte_offset) {
|
const spv_parsed_instruction_t& inst, size_t inst_byte_offset) {
|
||||||
auto opcode = static_cast<spv::Op>(inst.opcode);
|
auto opcode = static_cast<SpvOp>(inst.opcode);
|
||||||
|
|
||||||
if (inst.result_id) {
|
if (inst.result_id) {
|
||||||
SetBlue();
|
SetBlue();
|
||||||
@ -268,7 +268,7 @@ void InstructionDisassembler::EmitInstruction(
|
|||||||
EmitOperand(inst, i);
|
EmitOperand(inst, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comment_ && opcode == spv::Op::OpName) {
|
if (comment_ && opcode == SpvOpName) {
|
||||||
const spv_parsed_operand_t& operand = inst.operands[0];
|
const spv_parsed_operand_t& operand = inst.operands[0];
|
||||||
const uint32_t word = inst.words[operand.offset];
|
const uint32_t word = inst.words[operand.offset];
|
||||||
stream_ << " ; id %" << word;
|
stream_ << " ; id %" << word;
|
||||||
@ -290,8 +290,8 @@ void InstructionDisassembler::EmitInstruction(
|
|||||||
void InstructionDisassembler::EmitSectionComment(
|
void InstructionDisassembler::EmitSectionComment(
|
||||||
const spv_parsed_instruction_t& inst, bool& inserted_decoration_space,
|
const spv_parsed_instruction_t& inst, bool& inserted_decoration_space,
|
||||||
bool& inserted_debug_space, bool& inserted_type_space) {
|
bool& inserted_debug_space, bool& inserted_type_space) {
|
||||||
auto opcode = static_cast<spv::Op>(inst.opcode);
|
auto opcode = static_cast<SpvOp>(inst.opcode);
|
||||||
if (comment_ && opcode == spv::Op::OpFunction) {
|
if (comment_ && opcode == SpvOpFunction) {
|
||||||
stream_ << std::endl;
|
stream_ << std::endl;
|
||||||
stream_ << std::string(indent_, ' ');
|
stream_ << std::string(indent_, ' ');
|
||||||
stream_ << "; Function " << name_mapper_(inst.result_id) << std::endl;
|
stream_ << "; Function " << name_mapper_(inst.result_id) << std::endl;
|
||||||
@ -351,14 +351,13 @@ void InstructionDisassembler::EmitOperand(const spv_parsed_instruction_t& inst,
|
|||||||
} break;
|
} break;
|
||||||
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
|
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
|
||||||
spv_opcode_desc opcode_desc;
|
spv_opcode_desc opcode_desc;
|
||||||
if (grammar_.lookupOpcode(spv::Op(word), &opcode_desc))
|
if (grammar_.lookupOpcode(SpvOp(word), &opcode_desc))
|
||||||
assert(false && "should have caught this earlier");
|
assert(false && "should have caught this earlier");
|
||||||
SetRed();
|
SetRed();
|
||||||
stream_ << opcode_desc->name;
|
stream_ << opcode_desc->name;
|
||||||
} break;
|
} break;
|
||||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER:
|
case SPV_OPERAND_TYPE_LITERAL_INTEGER:
|
||||||
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
|
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: {
|
||||||
case SPV_OPERAND_TYPE_LITERAL_FLOAT: {
|
|
||||||
SetRed();
|
SetRed();
|
||||||
EmitNumericLiteral(&stream_, inst, operand);
|
EmitNumericLiteral(&stream_, inst, operand);
|
||||||
ResetColor();
|
ResetColor();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2023 Google Inc.
|
// Copyright (c) 2016 Google Inc.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -12,457 +12,196 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <functional>
|
|
||||||
#include <initializer_list>
|
|
||||||
#include <limits>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#ifndef SOURCE_ENUM_SET_H_
|
#ifndef SOURCE_ENUM_SET_H_
|
||||||
#define SOURCE_ENUM_SET_H_
|
#define SOURCE_ENUM_SET_H_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "source/latest_version_spirv_header.h"
|
#include "source/latest_version_spirv_header.h"
|
||||||
|
#include "source/util/make_unique.h"
|
||||||
|
|
||||||
namespace spvtools {
|
namespace spvtools {
|
||||||
|
|
||||||
// This container is optimized to store and retrieve unsigned enum values.
|
// A set of values of a 32-bit enum type.
|
||||||
// The base model for this implementation is an open-addressing hashtable with
|
// It is fast and compact for the common case, where enum values
|
||||||
// linear probing. For small enums (max index < 64), all operations are O(1).
|
// are at most 63. But it can represent enums with larger values,
|
||||||
//
|
// as may appear in extensions.
|
||||||
// - Enums are stored in buckets (64 contiguous values max per bucket)
|
template <typename EnumType>
|
||||||
// - Buckets ranges don't overlap, but don't have to be contiguous.
|
|
||||||
// - Enums are packed into 64-bits buckets, using 1 bit per enum value.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
// - MyEnum { A = 0, B = 1, C = 64, D = 65 }
|
|
||||||
// - 2 buckets are required:
|
|
||||||
// - bucket 0, storing values in the range [ 0; 64[
|
|
||||||
// - bucket 1, storing values in the range [64; 128[
|
|
||||||
//
|
|
||||||
// - Buckets are stored in a sorted vector (sorted by bucket range).
|
|
||||||
// - Retrieval is done by computing the theoretical bucket index using the enum
|
|
||||||
// value, and
|
|
||||||
// doing a linear scan from this position.
|
|
||||||
// - Insertion is done by retrieving the bucket and either:
|
|
||||||
// - inserting a new bucket in the sorted vector when no buckets has a
|
|
||||||
// compatible range.
|
|
||||||
// - setting the corresponding bit in the bucket.
|
|
||||||
// This means insertion in the middle/beginning can cause a memmove when no
|
|
||||||
// bucket is available. In our case, this happens at most 23 times for the
|
|
||||||
// largest enum we have (Opcodes).
|
|
||||||
template <typename T>
|
|
||||||
class EnumSet {
|
class EnumSet {
|
||||||
private:
|
private:
|
||||||
using BucketType = uint64_t;
|
// The ForEach method will call the functor on enum values in
|
||||||
using ElementType = std::underlying_type_t<T>;
|
// enum value order (lowest to highest). To make that easier, use
|
||||||
static_assert(std::is_enum_v<T>, "EnumSets only works with enums.");
|
// an ordered set for the overflow values.
|
||||||
static_assert(std::is_signed_v<ElementType> == false,
|
using OverflowSetType = std::set<uint32_t>;
|
||||||
"EnumSet doesn't supports signed enums.");
|
|
||||||
|
|
||||||
// Each bucket can hold up to `kBucketSize` distinct, contiguous enum values.
|
|
||||||
// The first value a bucket can hold must be aligned on `kBucketSize`.
|
|
||||||
struct Bucket {
|
|
||||||
// bit mask to store `kBucketSize` enums.
|
|
||||||
BucketType data;
|
|
||||||
// 1st enum this bucket can represent.
|
|
||||||
T start;
|
|
||||||
|
|
||||||
friend bool operator==(const Bucket& lhs, const Bucket& rhs) {
|
|
||||||
return lhs.start == rhs.start && lhs.data == rhs.data;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// How many distinct values can a bucket hold? 1 bit per value.
|
|
||||||
static constexpr size_t kBucketSize = sizeof(BucketType) * 8ULL;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Iterator {
|
// Construct an empty set.
|
||||||
public:
|
EnumSet() {}
|
||||||
typedef Iterator self_type;
|
// Construct an set with just the given enum value.
|
||||||
typedef T value_type;
|
explicit EnumSet(EnumType c) { Add(c); }
|
||||||
typedef T& reference;
|
// Construct an set from an initializer list of enum values.
|
||||||
typedef T* pointer;
|
EnumSet(std::initializer_list<EnumType> cs) {
|
||||||
typedef std::forward_iterator_tag iterator_category;
|
for (auto c : cs) Add(c);
|
||||||
typedef size_t difference_type;
|
|
||||||
|
|
||||||
Iterator(const Iterator& other)
|
|
||||||
: set_(other.set_),
|
|
||||||
bucketIndex_(other.bucketIndex_),
|
|
||||||
bucketOffset_(other.bucketOffset_) {}
|
|
||||||
|
|
||||||
Iterator& operator++() {
|
|
||||||
do {
|
|
||||||
if (bucketIndex_ >= set_->buckets_.size()) {
|
|
||||||
bucketIndex_ = set_->buckets_.size();
|
|
||||||
bucketOffset_ = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bucketOffset_ + 1 == kBucketSize) {
|
|
||||||
bucketOffset_ = 0;
|
|
||||||
++bucketIndex_;
|
|
||||||
} else {
|
|
||||||
++bucketOffset_;
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (bucketIndex_ < set_->buckets_.size() &&
|
|
||||||
!set_->HasEnumAt(bucketIndex_, bucketOffset_));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator operator++(int) {
|
|
||||||
Iterator old = *this;
|
|
||||||
operator++();
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
T operator*() const {
|
|
||||||
assert(set_->HasEnumAt(bucketIndex_, bucketOffset_) &&
|
|
||||||
"operator*() called on an invalid iterator.");
|
|
||||||
return GetValueFromBucket(set_->buckets_[bucketIndex_], bucketOffset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const Iterator& other) const {
|
|
||||||
return set_ != other.set_ || bucketOffset_ != other.bucketOffset_ ||
|
|
||||||
bucketIndex_ != other.bucketIndex_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const Iterator& other) const {
|
|
||||||
return !(operator!=(other));
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator& operator=(const Iterator& other) {
|
|
||||||
set_ = other.set_;
|
|
||||||
bucketIndex_ = other.bucketIndex_;
|
|
||||||
bucketOffset_ = other.bucketOffset_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Iterator(const EnumSet* set, size_t bucketIndex, ElementType bucketOffset)
|
|
||||||
: set_(set), bucketIndex_(bucketIndex), bucketOffset_(bucketOffset) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const EnumSet* set_ = nullptr;
|
|
||||||
// Index of the bucket in the vector.
|
|
||||||
size_t bucketIndex_ = 0;
|
|
||||||
// Offset in bits in the current bucket.
|
|
||||||
ElementType bucketOffset_ = 0;
|
|
||||||
|
|
||||||
friend class EnumSet;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Required to allow the use of std::inserter.
|
|
||||||
using value_type = T;
|
|
||||||
using const_iterator = Iterator;
|
|
||||||
using iterator = Iterator;
|
|
||||||
|
|
||||||
public:
|
|
||||||
iterator cbegin() const noexcept {
|
|
||||||
auto it = iterator(this, /* bucketIndex= */ 0, /* bucketOffset= */ 0);
|
|
||||||
if (buckets_.size() == 0) {
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The iterator has the logic to find the next valid bit. If the value 0
|
|
||||||
// is not stored, use it to find the next valid bit.
|
|
||||||
if (!HasEnumAt(it.bucketIndex_, it.bucketOffset_)) {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
return it;
|
|
||||||
}
|
}
|
||||||
|
EnumSet(uint32_t count, const EnumType* ptr) {
|
||||||
iterator begin() const noexcept { return cbegin(); }
|
for (uint32_t i = 0; i < count; ++i) Add(ptr[i]);
|
||||||
|
|
||||||
iterator cend() const noexcept {
|
|
||||||
return iterator(this, buckets_.size(), /* bucketOffset= */ 0);
|
|
||||||
}
|
}
|
||||||
|
// Copy constructor.
|
||||||
iterator end() const noexcept { return cend(); }
|
EnumSet(const EnumSet& other) { *this = other; }
|
||||||
|
// Move constructor. The moved-from set is emptied.
|
||||||
// Creates an empty set.
|
EnumSet(EnumSet&& other) {
|
||||||
EnumSet() : buckets_(0), size_(0) {}
|
mask_ = other.mask_;
|
||||||
|
overflow_ = std::move(other.overflow_);
|
||||||
// Creates a set and store `value` in it.
|
other.mask_ = 0;
|
||||||
EnumSet(T value) : EnumSet() { insert(value); }
|
other.overflow_.reset(nullptr);
|
||||||
|
|
||||||
// Creates a set and stores each `values` in it.
|
|
||||||
EnumSet(std::initializer_list<T> values) : EnumSet() {
|
|
||||||
for (auto item : values) {
|
|
||||||
insert(item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Assignment operator.
|
||||||
// Creates a set, and insert `count` enum values pointed by `array` in it.
|
|
||||||
EnumSet(ElementType count, const T* array) : EnumSet() {
|
|
||||||
for (ElementType i = 0; i < count; i++) {
|
|
||||||
insert(array[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a set initialized with the content of the range [begin; end[.
|
|
||||||
template <class InputIt>
|
|
||||||
EnumSet(InputIt begin, InputIt end) : EnumSet() {
|
|
||||||
for (; begin != end; ++begin) {
|
|
||||||
insert(*begin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copies the EnumSet `other` into a new EnumSet.
|
|
||||||
EnumSet(const EnumSet& other)
|
|
||||||
: buckets_(other.buckets_), size_(other.size_) {}
|
|
||||||
|
|
||||||
// Moves the EnumSet `other` into a new EnumSet.
|
|
||||||
EnumSet(EnumSet&& other)
|
|
||||||
: buckets_(std::move(other.buckets_)), size_(other.size_) {}
|
|
||||||
|
|
||||||
// Deep-copies the EnumSet `other` into this EnumSet.
|
|
||||||
EnumSet& operator=(const EnumSet& other) {
|
EnumSet& operator=(const EnumSet& other) {
|
||||||
buckets_ = other.buckets_;
|
if (&other != this) {
|
||||||
size_ = other.size_;
|
mask_ = other.mask_;
|
||||||
|
overflow_.reset(other.overflow_ ? new OverflowSetType(*other.overflow_)
|
||||||
|
: nullptr);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matches std::unordered_set::insert behavior.
|
friend bool operator==(const EnumSet& a, const EnumSet& b) {
|
||||||
std::pair<iterator, bool> insert(const T& value) {
|
if (a.mask_ != b.mask_) {
|
||||||
const size_t index = FindBucketForValue(value);
|
|
||||||
const ElementType offset = ComputeBucketOffset(value);
|
|
||||||
|
|
||||||
if (index >= buckets_.size() ||
|
|
||||||
buckets_[index].start != ComputeBucketStart(value)) {
|
|
||||||
size_ += 1;
|
|
||||||
InsertBucketFor(index, value);
|
|
||||||
return std::make_pair(Iterator(this, index, offset), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& bucket = buckets_[index];
|
|
||||||
const auto mask = ComputeMaskForValue(value);
|
|
||||||
if (bucket.data & mask) {
|
|
||||||
return std::make_pair(Iterator(this, index, offset), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_ += 1;
|
|
||||||
bucket.data |= ComputeMaskForValue(value);
|
|
||||||
return std::make_pair(Iterator(this, index, offset), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inserts `value` in the set if possible.
|
|
||||||
// Similar to `std::unordered_set::insert`, except the hint is ignored.
|
|
||||||
// Returns an iterator to the inserted element, or the element preventing
|
|
||||||
// insertion.
|
|
||||||
iterator insert(const_iterator, const T& value) {
|
|
||||||
return insert(value).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inserts `value` in the set if possible.
|
|
||||||
// Similar to `std::unordered_set::insert`, except the hint is ignored.
|
|
||||||
// Returns an iterator to the inserted element, or the element preventing
|
|
||||||
// insertion.
|
|
||||||
iterator insert(const_iterator, T&& value) { return insert(value).first; }
|
|
||||||
|
|
||||||
// Inserts all the values in the range [`first`; `last[.
|
|
||||||
// Similar to `std::unordered_set::insert`.
|
|
||||||
template <class InputIt>
|
|
||||||
void insert(InputIt first, InputIt last) {
|
|
||||||
for (auto it = first; it != last; ++it) {
|
|
||||||
insert(*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes the value `value` into the set.
|
|
||||||
// Similar to `std::unordered_set::erase`.
|
|
||||||
// Returns the number of erased elements.
|
|
||||||
size_t erase(const T& value) {
|
|
||||||
const size_t index = FindBucketForValue(value);
|
|
||||||
if (index >= buckets_.size() ||
|
|
||||||
buckets_[index].start != ComputeBucketStart(value)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& bucket = buckets_[index];
|
|
||||||
const auto mask = ComputeMaskForValue(value);
|
|
||||||
if (!(bucket.data & mask)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_ -= 1;
|
|
||||||
bucket.data &= ~mask;
|
|
||||||
if (bucket.data == 0) {
|
|
||||||
buckets_.erase(buckets_.cbegin() + index);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if `value` is present in the set.
|
|
||||||
bool contains(T value) const {
|
|
||||||
const size_t index = FindBucketForValue(value);
|
|
||||||
if (index >= buckets_.size() ||
|
|
||||||
buckets_[index].start != ComputeBucketStart(value)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto& bucket = buckets_[index];
|
|
||||||
return bucket.data & ComputeMaskForValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the 1 if `value` is present in the set, `0` otherwise.
|
if (a.overflow_ == nullptr && b.overflow_ == nullptr) {
|
||||||
inline size_t count(T value) const { return contains(value) ? 1 : 0; }
|
|
||||||
|
|
||||||
// Returns true if the set is holds no values.
|
|
||||||
inline bool empty() const { return size_ == 0; }
|
|
||||||
|
|
||||||
// Returns the number of enums stored in this set.
|
|
||||||
size_t size() const { return size_; }
|
|
||||||
|
|
||||||
// Returns true if this set contains at least one value contained in `in_set`.
|
|
||||||
// Note: If `in_set` is empty, this function returns true.
|
|
||||||
bool HasAnyOf(const EnumSet<T>& in_set) const {
|
|
||||||
if (in_set.empty()) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lhs = buckets_.cbegin();
|
if (a.overflow_ == nullptr || b.overflow_ == nullptr) {
|
||||||
auto rhs = in_set.buckets_.cbegin();
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
while (lhs != buckets_.cend() && rhs != in_set.buckets_.cend()) {
|
return *a.overflow_ == *b.overflow_;
|
||||||
if (lhs->start == rhs->start) {
|
}
|
||||||
if (lhs->data & rhs->data) {
|
|
||||||
// At least 1 bit is shared. Early return.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
lhs++;
|
friend bool operator!=(const EnumSet& a, const EnumSet& b) {
|
||||||
rhs++;
|
return !(a == b);
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// LHS bucket is smaller than the current RHS bucket. Catching up on RHS.
|
// Adds the given enum value to the set. This has no effect if the
|
||||||
if (lhs->start < rhs->start) {
|
// enum value is already in the set.
|
||||||
lhs++;
|
void Add(EnumType c) { AddWord(ToWord(c)); }
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, RHS needs to catch up on LHS.
|
// Removes the given enum value from the set. This has no effect if the
|
||||||
rhs++;
|
// enum value is not in the set.
|
||||||
|
void Remove(EnumType c) { RemoveWord(ToWord(c)); }
|
||||||
|
|
||||||
|
// Returns true if this enum value is in the set.
|
||||||
|
bool Contains(EnumType c) const { return ContainsWord(ToWord(c)); }
|
||||||
|
|
||||||
|
// Applies f to each enum in the set, in order from smallest enum
|
||||||
|
// value to largest.
|
||||||
|
void ForEach(std::function<void(EnumType)> f) const {
|
||||||
|
for (uint32_t i = 0; i < 64; ++i) {
|
||||||
|
if (mask_ & AsMask(i)) f(static_cast<EnumType>(i));
|
||||||
|
}
|
||||||
|
if (overflow_) {
|
||||||
|
for (uint32_t c : *overflow_) f(static_cast<EnumType>(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the set is empty.
|
||||||
|
bool IsEmpty() const {
|
||||||
|
if (mask_) return false;
|
||||||
|
if (overflow_ && !overflow_->empty()) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the set contains ANY of the elements of |in_set|,
|
||||||
|
// or if |in_set| is empty.
|
||||||
|
bool HasAnyOf(const EnumSet<EnumType>& in_set) const {
|
||||||
|
if (in_set.IsEmpty()) return true;
|
||||||
|
|
||||||
|
if (mask_ & in_set.mask_) return true;
|
||||||
|
|
||||||
|
if (!overflow_ || !in_set.overflow_) return false;
|
||||||
|
|
||||||
|
for (uint32_t item : *in_set.overflow_) {
|
||||||
|
if (overflow_->find(item) != overflow_->end()) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Returns the index of the last bucket in which `value` could be stored.
|
// Adds the given enum value (as a 32-bit word) to the set. This has no
|
||||||
static constexpr inline size_t ComputeLargestPossibleBucketIndexFor(T value) {
|
// effect if the enum value is already in the set.
|
||||||
return static_cast<size_t>(value) / kBucketSize;
|
void AddWord(uint32_t word) {
|
||||||
}
|
if (auto new_bits = AsMask(word)) {
|
||||||
|
mask_ |= new_bits;
|
||||||
// Returns the smallest enum value that could be contained in the same bucket
|
} else {
|
||||||
// as `value`.
|
Overflow().insert(word);
|
||||||
static constexpr inline T ComputeBucketStart(T value) {
|
|
||||||
return static_cast<T>(kBucketSize *
|
|
||||||
ComputeLargestPossibleBucketIndexFor(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the index of the bit that corresponds to `value` in the bucket.
|
|
||||||
static constexpr inline ElementType ComputeBucketOffset(T value) {
|
|
||||||
return static_cast<ElementType>(value) % kBucketSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the bitmask used to represent the enum `value` in its bucket.
|
|
||||||
static constexpr inline BucketType ComputeMaskForValue(T value) {
|
|
||||||
return 1ULL << ComputeBucketOffset(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the `enum` stored in `bucket` at `offset`.
|
|
||||||
// `offset` is the bit-offset in the bucket storage.
|
|
||||||
static constexpr inline T GetValueFromBucket(const Bucket& bucket,
|
|
||||||
BucketType offset) {
|
|
||||||
return static_cast<T>(static_cast<ElementType>(bucket.start) + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For a given enum `value`, finds the bucket index that could contain this
|
|
||||||
// value. If no such bucket is found, the index at which the new bucket should
|
|
||||||
// be inserted is returned.
|
|
||||||
size_t FindBucketForValue(T value) const {
|
|
||||||
// Set is empty, insert at 0.
|
|
||||||
if (buckets_.size() == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const T wanted_start = ComputeBucketStart(value);
|
// Removes the given enum value (as a 32-bit word) from the set. This has no
|
||||||
assert(buckets_.size() > 0 &&
|
// effect if the enum value is not in the set.
|
||||||
"Size must not be 0 here. Has the code above changed?");
|
void RemoveWord(uint32_t word) {
|
||||||
size_t index = std::min(buckets_.size() - 1,
|
if (auto new_bits = AsMask(word)) {
|
||||||
ComputeLargestPossibleBucketIndexFor(value));
|
mask_ &= ~new_bits;
|
||||||
|
} else {
|
||||||
// This loops behaves like std::upper_bound with a reverse iterator.
|
auto itr = Overflow().find(word);
|
||||||
// Buckets are sorted. 3 main cases:
|
if (itr != Overflow().end()) Overflow().erase(itr);
|
||||||
// - The bucket matches
|
|
||||||
// => returns the bucket index.
|
|
||||||
// - The found bucket is larger
|
|
||||||
// => scans left until it finds the correct bucket, or insertion point.
|
|
||||||
// - The found bucket is smaller
|
|
||||||
// => We are at the end, so we return past-end index for insertion.
|
|
||||||
for (; buckets_[index].start >= wanted_start; index--) {
|
|
||||||
if (index == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return index + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new bucket to store `value` and inserts it at `index`.
|
// Returns true if the enum represented as a 32-bit word is in the set.
|
||||||
// If the `index` is past the end, the bucket is inserted at the end of the
|
bool ContainsWord(uint32_t word) const {
|
||||||
// vector.
|
// We shouldn't call Overflow() since this is a const method.
|
||||||
void InsertBucketFor(size_t index, T value) {
|
if (auto bits = AsMask(word)) {
|
||||||
const T bucket_start = ComputeBucketStart(value);
|
return (mask_ & bits) != 0;
|
||||||
Bucket bucket = {1ULL << ComputeBucketOffset(value), bucket_start};
|
} else if (auto overflow = overflow_.get()) {
|
||||||
auto it = buckets_.emplace(buckets_.begin() + index, std::move(bucket));
|
return overflow->find(word) != overflow->end();
|
||||||
#if defined(NDEBUG)
|
|
||||||
(void)it; // Silencing unused variable warning.
|
|
||||||
#else
|
|
||||||
assert(std::next(it) == buckets_.end() ||
|
|
||||||
std::next(it)->start > bucket_start);
|
|
||||||
assert(it == buckets_.begin() || std::prev(it)->start < bucket_start);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if the bucket at `bucketIndex/ stores the enum at
|
|
||||||
// `bucketOffset`, false otherwise.
|
|
||||||
bool HasEnumAt(size_t bucketIndex, BucketType bucketOffset) const {
|
|
||||||
assert(bucketIndex < buckets_.size());
|
|
||||||
assert(bucketOffset < kBucketSize);
|
|
||||||
return buckets_[bucketIndex].data & (1ULL << bucketOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if `lhs` and `rhs` hold the exact same values.
|
|
||||||
friend bool operator==(const EnumSet& lhs, const EnumSet& rhs) {
|
|
||||||
if (lhs.size_ != rhs.size_) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
// The word is large, but the set doesn't have large members, so
|
||||||
|
// it doesn't have an overflow set.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (lhs.buckets_.size() != rhs.buckets_.size()) {
|
// Returns the enum value as a uint32_t.
|
||||||
return false;
|
uint32_t ToWord(EnumType value) const {
|
||||||
|
static_assert(sizeof(EnumType) <= sizeof(uint32_t),
|
||||||
|
"EnumType must statically castable to uint32_t");
|
||||||
|
return static_cast<uint32_t>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determines whether the given enum value can be represented
|
||||||
|
// as a bit in a uint64_t mask. If so, then returns that mask bit.
|
||||||
|
// Otherwise, returns 0.
|
||||||
|
uint64_t AsMask(uint32_t word) const {
|
||||||
|
if (word > 63) return 0;
|
||||||
|
return uint64_t(1) << word;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensures that overflow_set_ references a set. A new empty set is
|
||||||
|
// allocated if one doesn't exist yet. Returns overflow_set_.
|
||||||
|
OverflowSetType& Overflow() {
|
||||||
|
if (overflow_.get() == nullptr) {
|
||||||
|
overflow_ = MakeUnique<OverflowSetType>();
|
||||||
}
|
}
|
||||||
return lhs.buckets_ == rhs.buckets_;
|
return *overflow_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if `lhs` and `rhs` hold at least 1 different value.
|
// Enums with values up to 63 are stored as bits in this mask.
|
||||||
friend bool operator!=(const EnumSet& lhs, const EnumSet& rhs) {
|
uint64_t mask_ = 0;
|
||||||
return !(lhs == rhs);
|
// Enums with values larger than 63 are stored in this set.
|
||||||
}
|
// This set should normally be empty or very small.
|
||||||
|
std::unique_ptr<OverflowSetType> overflow_ = {};
|
||||||
// Storage for the buckets.
|
|
||||||
std::vector<Bucket> buckets_;
|
|
||||||
// How many enums is this set storing.
|
|
||||||
size_t size_ = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// A set of spv::Capability.
|
// A set of SpvCapability, optimized for small capability values.
|
||||||
using CapabilitySet = EnumSet<spv::Capability>;
|
using CapabilitySet = EnumSet<SpvCapability>;
|
||||||
|
|
||||||
} // namespace spvtools
|
} // namespace spvtools
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ bool GetExtensionFromString(const char* str, Extension* extension);
|
|||||||
const char* ExtensionToString(Extension extension);
|
const char* ExtensionToString(Extension extension);
|
||||||
|
|
||||||
// Returns text string corresponding to |capability|.
|
// Returns text string corresponding to |capability|.
|
||||||
const char* CapabilityToString(spv::Capability capability);
|
const char* CapabilityToString(SpvCapability capability);
|
||||||
|
|
||||||
} // namespace spvtools
|
} // namespace spvtools
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
namespace spvtools {
|
namespace spvtools {
|
||||||
|
|
||||||
std::string GetExtensionString(const spv_parsed_instruction_t* inst) {
|
std::string GetExtensionString(const spv_parsed_instruction_t* inst) {
|
||||||
if (inst->opcode != static_cast<uint16_t>(spv::Op::OpExtension)) {
|
if (inst->opcode != SpvOpExtension) return "ERROR_not_op_extension";
|
||||||
return "ERROR_not_op_extension";
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(inst->num_operands == 1);
|
assert(inst->num_operands == 1);
|
||||||
|
|
||||||
@ -40,9 +38,8 @@ std::string GetExtensionString(const spv_parsed_instruction_t* inst) {
|
|||||||
|
|
||||||
std::string ExtensionSetToString(const ExtensionSet& extensions) {
|
std::string ExtensionSetToString(const ExtensionSet& extensions) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
for (auto extension : extensions) {
|
extensions.ForEach(
|
||||||
ss << ExtensionToString(extension) << " ";
|
[&ss](Extension ext) { ss << ExtensionToString(ext) << " "; });
|
||||||
}
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
#ifndef SOURCE_EXTENSIONS_H_
|
#ifndef SOURCE_EXTENSIONS_H_
|
||||||
#define SOURCE_EXTENSIONS_H_
|
#define SOURCE_EXTENSIONS_H_
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "source/enum_set.h"
|
#include "source/enum_set.h"
|
||||||
@ -24,7 +23,7 @@
|
|||||||
namespace spvtools {
|
namespace spvtools {
|
||||||
|
|
||||||
// The known SPIR-V extensions.
|
// The known SPIR-V extensions.
|
||||||
enum Extension : uint32_t {
|
enum Extension {
|
||||||
#include "extension_enum.inc"
|
#include "extension_enum.inc"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -470,7 +470,10 @@ if(SPIRV_BUILD_FUZZER)
|
|||||||
spvtools_check_symbol_exports(SPIRV-Tools-fuzz)
|
spvtools_check_symbol_exports(SPIRV-Tools-fuzz)
|
||||||
|
|
||||||
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||||
install(TARGETS SPIRV-Tools-fuzz EXPORT SPIRV-Tools-fuzzTargets)
|
install(TARGETS SPIRV-Tools-fuzz EXPORT SPIRV-Tools-fuzzTargets
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
export(EXPORT SPIRV-Tools-fuzzTargets FILE SPIRV-Tools-fuzzTarget.cmake)
|
export(EXPORT SPIRV-Tools-fuzzTargets FILE SPIRV-Tools-fuzzTarget.cmake)
|
||||||
|
|
||||||
spvtools_config_package_dir(SPIRV-Tools-fuzz PACKAGE_DIR)
|
spvtools_config_package_dir(SPIRV-Tools-fuzz PACKAGE_DIR)
|
||||||
|
@ -130,7 +130,7 @@ bool AddedFunctionReducer::InterestingnessFunctionForReducingAddedFunction(
|
|||||||
binary_under_reduction.size());
|
binary_under_reduction.size());
|
||||||
assert(ir_context != nullptr && "The binary should be parsable.");
|
assert(ir_context != nullptr && "The binary should be parsable.");
|
||||||
for (auto& type_or_value : ir_context->module()->types_values()) {
|
for (auto& type_or_value : ir_context->module()->types_values()) {
|
||||||
if (type_or_value.opcode() != spv::Op::OpVariable) {
|
if (type_or_value.opcode() != SpvOpVariable) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (irrelevant_pointee_global_variables.count(type_or_value.result_id())) {
|
if (irrelevant_pointee_global_variables.count(type_or_value.result_id())) {
|
||||||
@ -202,7 +202,7 @@ void AddedFunctionReducer::ReplayPrefixAndAddFunction(
|
|||||||
auto* ir_context = replay_result.transformed_module.get();
|
auto* ir_context = replay_result.transformed_module.get();
|
||||||
|
|
||||||
for (auto& type_or_value : ir_context->module()->types_values()) {
|
for (auto& type_or_value : ir_context->module()->types_values()) {
|
||||||
if (type_or_value.opcode() != spv::Op::OpVariable) {
|
if (type_or_value.opcode() != SpvOpVariable) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (replay_result.transformation_context->GetFactManager()
|
if (replay_result.transformation_context->GetFactManager()
|
||||||
|
@ -54,7 +54,7 @@ void CallGraph::BuildGraphAndGetDepthOfFunctionCalls(
|
|||||||
// Consider every function call instruction in every block.
|
// Consider every function call instruction in every block.
|
||||||
for (auto& block : function) {
|
for (auto& block : function) {
|
||||||
for (auto& instruction : block) {
|
for (auto& instruction : block) {
|
||||||
if (instruction.opcode() != spv::Op::OpFunctionCall) {
|
if (instruction.opcode() != SpvOpFunctionCall) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Get the id of the function being called.
|
// Get the id of the function being called.
|
||||||
|
@ -63,7 +63,7 @@ std::vector<uint32_t> ConstantUniformFacts::GetConstantWords(
|
|||||||
bool ConstantUniformFacts::DataMatches(
|
bool ConstantUniformFacts::DataMatches(
|
||||||
const opt::Instruction& constant_instruction,
|
const opt::Instruction& constant_instruction,
|
||||||
const protobufs::FactConstantUniform& constant_uniform_fact) {
|
const protobufs::FactConstantUniform& constant_uniform_fact) {
|
||||||
assert(constant_instruction.opcode() == spv::Op::OpConstant);
|
assert(constant_instruction.opcode() == SpvOpConstant);
|
||||||
std::vector<uint32_t> data_in_constant;
|
std::vector<uint32_t> data_in_constant;
|
||||||
for (uint32_t i = 0; i < constant_instruction.NumInOperands(); i++) {
|
for (uint32_t i = 0; i < constant_instruction.NumInOperands(); i++) {
|
||||||
data_in_constant.push_back(constant_instruction.GetSingleWordInOperand(i));
|
data_in_constant.push_back(constant_instruction.GetSingleWordInOperand(i));
|
||||||
@ -95,7 +95,7 @@ ConstantUniformFacts::GetUniformDescriptorsForConstant(
|
|||||||
uint32_t constant_id) const {
|
uint32_t constant_id) const {
|
||||||
std::vector<protobufs::UniformBufferElementDescriptor> result;
|
std::vector<protobufs::UniformBufferElementDescriptor> result;
|
||||||
auto constant_inst = ir_context_->get_def_use_mgr()->GetDef(constant_id);
|
auto constant_inst = ir_context_->get_def_use_mgr()->GetDef(constant_id);
|
||||||
assert(constant_inst->opcode() == spv::Op::OpConstant &&
|
assert(constant_inst->opcode() == SpvOpConstant &&
|
||||||
"The given id must be that of a constant");
|
"The given id must be that of a constant");
|
||||||
auto type_id = constant_inst->type_id();
|
auto type_id = constant_inst->type_id();
|
||||||
for (auto& fact_and_type_id : facts_and_type_ids_) {
|
for (auto& fact_and_type_id : facts_and_type_ids_) {
|
||||||
@ -175,9 +175,8 @@ bool ConstantUniformFacts::MaybeAddFact(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(spv::Op::OpVariable == uniform_variable->opcode());
|
assert(SpvOpVariable == uniform_variable->opcode());
|
||||||
assert(spv::StorageClass::Uniform ==
|
assert(SpvStorageClassUniform == uniform_variable->GetSingleWordInOperand(0));
|
||||||
spv::StorageClass(uniform_variable->GetSingleWordInOperand(0)));
|
|
||||||
|
|
||||||
auto should_be_uniform_pointer_type =
|
auto should_be_uniform_pointer_type =
|
||||||
ir_context_->get_type_mgr()->GetType(uniform_variable->type_id());
|
ir_context_->get_type_mgr()->GetType(uniform_variable->type_id());
|
||||||
@ -185,7 +184,7 @@ bool ConstantUniformFacts::MaybeAddFact(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (should_be_uniform_pointer_type->AsPointer()->storage_class() !=
|
if (should_be_uniform_pointer_type->AsPointer()->storage_class() !=
|
||||||
spv::StorageClass::Uniform) {
|
SpvStorageClassUniform) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto should_be_uniform_pointer_instruction =
|
auto should_be_uniform_pointer_instruction =
|
||||||
|
@ -23,7 +23,7 @@ namespace fact_manager {
|
|||||||
size_t DataSynonymAndIdEquationFacts::OperationHash::operator()(
|
size_t DataSynonymAndIdEquationFacts::OperationHash::operator()(
|
||||||
const Operation& operation) const {
|
const Operation& operation) const {
|
||||||
std::u32string hash;
|
std::u32string hash;
|
||||||
hash.push_back(uint32_t(operation.opcode));
|
hash.push_back(operation.opcode);
|
||||||
for (auto operand : operation.operands) {
|
for (auto operand : operation.operands) {
|
||||||
hash.push_back(static_cast<uint32_t>(DataDescriptorHash()(operand)));
|
hash.push_back(static_cast<uint32_t>(DataDescriptorHash()(operand)));
|
||||||
}
|
}
|
||||||
@ -104,8 +104,7 @@ bool DataSynonymAndIdEquationFacts::MaybeAddFact(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now add the fact.
|
// Now add the fact.
|
||||||
AddEquationFactRecursive(lhs_dd, static_cast<spv::Op>(fact.opcode()),
|
AddEquationFactRecursive(lhs_dd, static_cast<SpvOp>(fact.opcode()), rhs_dds);
|
||||||
rhs_dds);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +119,7 @@ DataSynonymAndIdEquationFacts::GetEquations(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
|
void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
|
||||||
const protobufs::DataDescriptor& lhs_dd, spv::Op opcode,
|
const protobufs::DataDescriptor& lhs_dd, SpvOp opcode,
|
||||||
const std::vector<const protobufs::DataDescriptor*>& rhs_dds) {
|
const std::vector<const protobufs::DataDescriptor*>& rhs_dds) {
|
||||||
assert(synonymous_.Exists(lhs_dd) &&
|
assert(synonymous_.Exists(lhs_dd) &&
|
||||||
"The LHS must be known to the equivalence relation.");
|
"The LHS must be known to the equivalence relation.");
|
||||||
@ -156,21 +155,21 @@ void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
|
|||||||
// Now try to work out corollaries implied by the new equation and existing
|
// Now try to work out corollaries implied by the new equation and existing
|
||||||
// facts.
|
// facts.
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case spv::Op::OpConvertSToF:
|
case SpvOpConvertSToF:
|
||||||
case spv::Op::OpConvertUToF:
|
case SpvOpConvertUToF:
|
||||||
ComputeConversionDataSynonymFacts(*rhs_dds[0]);
|
ComputeConversionDataSynonymFacts(*rhs_dds[0]);
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpBitcast: {
|
case SpvOpBitcast: {
|
||||||
assert(DataDescriptorsAreWellFormedAndComparable(lhs_dd, *rhs_dds[0]) &&
|
assert(DataDescriptorsAreWellFormedAndComparable(lhs_dd, *rhs_dds[0]) &&
|
||||||
"Operands of OpBitcast equation fact must have compatible types");
|
"Operands of OpBitcast equation fact must have compatible types");
|
||||||
if (!synonymous_.IsEquivalent(lhs_dd, *rhs_dds[0])) {
|
if (!synonymous_.IsEquivalent(lhs_dd, *rhs_dds[0])) {
|
||||||
AddDataSynonymFactRecursive(lhs_dd, *rhs_dds[0]);
|
AddDataSynonymFactRecursive(lhs_dd, *rhs_dds[0]);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpIAdd: {
|
case SpvOpIAdd: {
|
||||||
// Equation form: "a = b + c"
|
// Equation form: "a = b + c"
|
||||||
for (const auto& equation : GetEquations(rhs_dds[0])) {
|
for (const auto& equation : GetEquations(rhs_dds[0])) {
|
||||||
if (equation.opcode == spv::Op::OpISub) {
|
if (equation.opcode == SpvOpISub) {
|
||||||
// Equation form: "a = (d - e) + c"
|
// Equation form: "a = (d - e) + c"
|
||||||
if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[1])) {
|
if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[1])) {
|
||||||
// Equation form: "a = (d - c) + c"
|
// Equation form: "a = (d - c) + c"
|
||||||
@ -180,7 +179,7 @@ void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto& equation : GetEquations(rhs_dds[1])) {
|
for (const auto& equation : GetEquations(rhs_dds[1])) {
|
||||||
if (equation.opcode == spv::Op::OpISub) {
|
if (equation.opcode == SpvOpISub) {
|
||||||
// Equation form: "a = b + (d - e)"
|
// Equation form: "a = b + (d - e)"
|
||||||
if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
|
if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
|
||||||
// Equation form: "a = b + (d - b)"
|
// Equation form: "a = b + (d - b)"
|
||||||
@ -191,10 +190,10 @@ void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case spv::Op::OpISub: {
|
case SpvOpISub: {
|
||||||
// Equation form: "a = b - c"
|
// Equation form: "a = b - c"
|
||||||
for (const auto& equation : GetEquations(rhs_dds[0])) {
|
for (const auto& equation : GetEquations(rhs_dds[0])) {
|
||||||
if (equation.opcode == spv::Op::OpIAdd) {
|
if (equation.opcode == SpvOpIAdd) {
|
||||||
// Equation form: "a = (d + e) - c"
|
// Equation form: "a = (d + e) - c"
|
||||||
if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
|
if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
|
||||||
// Equation form: "a = (c + e) - c"
|
// Equation form: "a = (c + e) - c"
|
||||||
@ -208,34 +207,34 @@ void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (equation.opcode == spv::Op::OpISub) {
|
if (equation.opcode == SpvOpISub) {
|
||||||
// Equation form: "a = (d - e) - c"
|
// Equation form: "a = (d - e) - c"
|
||||||
if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
|
if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
|
||||||
// Equation form: "a = (c - e) - c"
|
// Equation form: "a = (c - e) - c"
|
||||||
// We can thus infer "a = -e"
|
// We can thus infer "a = -e"
|
||||||
AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
|
AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
|
||||||
{equation.operands[1]});
|
{equation.operands[1]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& equation : GetEquations(rhs_dds[1])) {
|
for (const auto& equation : GetEquations(rhs_dds[1])) {
|
||||||
if (equation.opcode == spv::Op::OpIAdd) {
|
if (equation.opcode == SpvOpIAdd) {
|
||||||
// Equation form: "a = b - (d + e)"
|
// Equation form: "a = b - (d + e)"
|
||||||
if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
|
if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
|
||||||
// Equation form: "a = b - (b + e)"
|
// Equation form: "a = b - (b + e)"
|
||||||
// We can thus infer "a = -e"
|
// We can thus infer "a = -e"
|
||||||
AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
|
AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
|
||||||
{equation.operands[1]});
|
{equation.operands[1]});
|
||||||
}
|
}
|
||||||
if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
|
if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
|
||||||
// Equation form: "a = b - (d + b)"
|
// Equation form: "a = b - (d + b)"
|
||||||
// We can thus infer "a = -d"
|
// We can thus infer "a = -d"
|
||||||
AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
|
AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
|
||||||
{equation.operands[0]});
|
{equation.operands[0]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (equation.opcode == spv::Op::OpISub) {
|
if (equation.opcode == SpvOpISub) {
|
||||||
// Equation form: "a = b - (d - e)"
|
// Equation form: "a = b - (d - e)"
|
||||||
if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
|
if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
|
||||||
// Equation form: "a = b - (b - e)"
|
// Equation form: "a = b - (b - e)"
|
||||||
@ -246,8 +245,8 @@ void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case spv::Op::OpLogicalNot:
|
case SpvOpLogicalNot:
|
||||||
case spv::Op::OpSNegate: {
|
case SpvOpSNegate: {
|
||||||
// Equation form: "a = !b" or "a = -b"
|
// Equation form: "a = !b" or "a = -b"
|
||||||
for (const auto& equation : GetEquations(rhs_dds[0])) {
|
for (const auto& equation : GetEquations(rhs_dds[0])) {
|
||||||
if (equation.opcode == opcode) {
|
if (equation.opcode == opcode) {
|
||||||
@ -322,9 +321,9 @@ void DataSynonymAndIdEquationFacts::ComputeConversionDataSynonymFacts(
|
|||||||
|
|
||||||
for (const auto& equation : fact.second) {
|
for (const auto& equation : fact.second) {
|
||||||
if (synonymous_.IsEquivalent(*equation.operands[0], dd)) {
|
if (synonymous_.IsEquivalent(*equation.operands[0], dd)) {
|
||||||
if (equation.opcode == spv::Op::OpConvertSToF) {
|
if (equation.opcode == SpvOpConvertSToF) {
|
||||||
convert_s_to_f_lhs.push_back(*dd_it);
|
convert_s_to_f_lhs.push_back(*dd_it);
|
||||||
} else if (equation.opcode == spv::Op::OpConvertUToF) {
|
} else if (equation.opcode == SpvOpConvertUToF) {
|
||||||
convert_u_to_f_lhs.push_back(*dd_it);
|
convert_u_to_f_lhs.push_back(*dd_it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -809,9 +808,9 @@ bool DataSynonymAndIdEquationFacts::DataDescriptorsAreWellFormedAndComparable(
|
|||||||
}
|
}
|
||||||
// Neither end type is allowed to be void.
|
// Neither end type is allowed to be void.
|
||||||
if (ir_context_->get_def_use_mgr()->GetDef(end_type_id_1)->opcode() ==
|
if (ir_context_->get_def_use_mgr()->GetDef(end_type_id_1)->opcode() ==
|
||||||
spv::Op::OpTypeVoid ||
|
SpvOpTypeVoid ||
|
||||||
ir_context_->get_def_use_mgr()->GetDef(end_type_id_2)->opcode() ==
|
ir_context_->get_def_use_mgr()->GetDef(end_type_id_2)->opcode() ==
|
||||||
spv::Op::OpTypeVoid) {
|
SpvOpTypeVoid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// If the end types are the same, the data descriptors are comparable.
|
// If the end types are the same, the data descriptors are comparable.
|
||||||
|
@ -79,7 +79,7 @@ class DataSynonymAndIdEquationFacts {
|
|||||||
// This helper struct represents the right hand side of an equation as an
|
// This helper struct represents the right hand side of an equation as an
|
||||||
// operator applied to a number of data descriptor operands.
|
// operator applied to a number of data descriptor operands.
|
||||||
struct Operation {
|
struct Operation {
|
||||||
spv::Op opcode;
|
SpvOp opcode;
|
||||||
std::vector<const protobufs::DataDescriptor*> operands;
|
std::vector<const protobufs::DataDescriptor*> operands;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ class DataSynonymAndIdEquationFacts {
|
|||||||
// corollaries, in the form of data synonym or equation facts, that follow
|
// corollaries, in the form of data synonym or equation facts, that follow
|
||||||
// from this and other known facts.
|
// from this and other known facts.
|
||||||
void AddEquationFactRecursive(
|
void AddEquationFactRecursive(
|
||||||
const protobufs::DataDescriptor& lhs_dd, spv::Op opcode,
|
const protobufs::DataDescriptor& lhs_dd, SpvOp opcode,
|
||||||
const std::vector<const protobufs::DataDescriptor*>& rhs_dds);
|
const std::vector<const protobufs::DataDescriptor*>& rhs_dds);
|
||||||
|
|
||||||
// Returns true if and only if |dd.object()| still exists in the module.
|
// Returns true if and only if |dd.object()| still exists in the module.
|
||||||
|
@ -64,7 +64,7 @@ std::string ToString(const protobufs::FactDataSynonym& fact) {
|
|||||||
std::string ToString(const protobufs::FactIdEquation& fact) {
|
std::string ToString(const protobufs::FactIdEquation& fact) {
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
stream << fact.lhs_id();
|
stream << fact.lhs_id();
|
||||||
stream << " " << fact.opcode();
|
stream << " " << static_cast<SpvOp>(fact.opcode());
|
||||||
for (auto rhs_id : fact.rhs_id()) {
|
for (auto rhs_id : fact.rhs_id()) {
|
||||||
stream << " " << rhs_id;
|
stream << " " << rhs_id;
|
||||||
}
|
}
|
||||||
@ -255,11 +255,11 @@ void FactManager::AddFactIdIsIrrelevant(uint32_t result_id) {
|
|||||||
assert(success && "|result_id| is invalid");
|
assert(success && "|result_id| is invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
void FactManager::AddFactIdEquation(uint32_t lhs_id, spv::Op opcode,
|
void FactManager::AddFactIdEquation(uint32_t lhs_id, SpvOp opcode,
|
||||||
const std::vector<uint32_t>& rhs_id) {
|
const std::vector<uint32_t>& rhs_id) {
|
||||||
protobufs::FactIdEquation fact;
|
protobufs::FactIdEquation fact;
|
||||||
fact.set_lhs_id(lhs_id);
|
fact.set_lhs_id(lhs_id);
|
||||||
fact.set_opcode(uint32_t(opcode));
|
fact.set_opcode(opcode);
|
||||||
for (auto an_rhs_id : rhs_id) {
|
for (auto an_rhs_id : rhs_id) {
|
||||||
fact.add_rhs_id(an_rhs_id);
|
fact.add_rhs_id(an_rhs_id);
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ class FactManager {
|
|||||||
// |lhs_id| = |opcode| |rhs_id[0]| ... |rhs_id[N-1]|
|
// |lhs_id| = |opcode| |rhs_id[0]| ... |rhs_id[N-1]|
|
||||||
//
|
//
|
||||||
// Neither |lhs_id| nor any of |rhs_id| may be irrelevant.
|
// Neither |lhs_id| nor any of |rhs_id| may be irrelevant.
|
||||||
void AddFactIdEquation(uint32_t lhs_id, spv::Op opcode,
|
void AddFactIdEquation(uint32_t lhs_id, SpvOp opcode,
|
||||||
const std::vector<uint32_t>& rhs_id);
|
const std::vector<uint32_t>& rhs_id);
|
||||||
|
|
||||||
// Inspects all known facts and adds corollary facts; e.g. if we know that
|
// Inspects all known facts and adds corollary facts; e.g. if we know that
|
||||||
|
@ -36,9 +36,8 @@ opt::Function* FindFragmentShaderEntryPoint(opt::IRContext* ir_context,
|
|||||||
// Check that this is a fragment shader
|
// Check that this is a fragment shader
|
||||||
bool found_capability_shader = false;
|
bool found_capability_shader = false;
|
||||||
for (auto& capability : ir_context->capabilities()) {
|
for (auto& capability : ir_context->capabilities()) {
|
||||||
assert(capability.opcode() == spv::Op::OpCapability);
|
assert(capability.opcode() == SpvOpCapability);
|
||||||
if (spv::Capability(capability.GetSingleWordInOperand(0)) ==
|
if (capability.GetSingleWordInOperand(0) == SpvCapabilityShader) {
|
||||||
spv::Capability::Shader) {
|
|
||||||
found_capability_shader = true;
|
found_capability_shader = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -52,8 +51,7 @@ opt::Function* FindFragmentShaderEntryPoint(opt::IRContext* ir_context,
|
|||||||
|
|
||||||
opt::Instruction* fragment_entry_point = nullptr;
|
opt::Instruction* fragment_entry_point = nullptr;
|
||||||
for (auto& entry_point : ir_context->module()->entry_points()) {
|
for (auto& entry_point : ir_context->module()->entry_points()) {
|
||||||
if (spv::ExecutionModel(entry_point.GetSingleWordInOperand(0)) ==
|
if (entry_point.GetSingleWordInOperand(0) == SpvExecutionModelFragment) {
|
||||||
spv::ExecutionModel::Fragment) {
|
|
||||||
fragment_entry_point = &entry_point;
|
fragment_entry_point = &entry_point;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -83,9 +81,8 @@ opt::Instruction* FindVec4OutputVariable(opt::IRContext* ir_context,
|
|||||||
MessageConsumer message_consumer) {
|
MessageConsumer message_consumer) {
|
||||||
opt::Instruction* output_variable = nullptr;
|
opt::Instruction* output_variable = nullptr;
|
||||||
for (auto& inst : ir_context->types_values()) {
|
for (auto& inst : ir_context->types_values()) {
|
||||||
if (inst.opcode() == spv::Op::OpVariable &&
|
if (inst.opcode() == SpvOpVariable &&
|
||||||
spv::StorageClass(inst.GetSingleWordInOperand(0)) ==
|
inst.GetSingleWordInOperand(0) == SpvStorageClassOutput) {
|
||||||
spv::StorageClass::Output) {
|
|
||||||
if (output_variable != nullptr) {
|
if (output_variable != nullptr) {
|
||||||
message_consumer(SPV_MSG_ERROR, nullptr, {},
|
message_consumer(SPV_MSG_ERROR, nullptr, {},
|
||||||
"Only one output variable can be handled at present; "
|
"Only one output variable can be handled at present; "
|
||||||
@ -147,11 +144,10 @@ MakeConstantUniformReplacement(opt::IRContext* ir_context,
|
|||||||
uint32_t greater_than_instruction,
|
uint32_t greater_than_instruction,
|
||||||
uint32_t in_operand_index) {
|
uint32_t in_operand_index) {
|
||||||
return MakeUnique<TransformationReplaceConstantWithUniform>(
|
return MakeUnique<TransformationReplaceConstantWithUniform>(
|
||||||
MakeIdUseDescriptor(
|
MakeIdUseDescriptor(constant_id,
|
||||||
constant_id,
|
MakeInstructionDescriptor(greater_than_instruction,
|
||||||
MakeInstructionDescriptor(greater_than_instruction,
|
SpvOpFOrdGreaterThan, 0),
|
||||||
spv::Op::OpFOrdGreaterThan, 0),
|
in_operand_index),
|
||||||
in_operand_index),
|
|
||||||
fact_manager.GetUniformDescriptorsForConstant(constant_id)[0],
|
fact_manager.GetUniformDescriptorsForConstant(constant_id)[0],
|
||||||
ir_context->TakeNextId(), ir_context->TakeNextId());
|
ir_context->TakeNextId(), ir_context->TakeNextId());
|
||||||
}
|
}
|
||||||
@ -208,21 +204,20 @@ bool ForceRenderRed(
|
|||||||
// Make the new exit block
|
// Make the new exit block
|
||||||
auto new_exit_block_id = ir_context->TakeNextId();
|
auto new_exit_block_id = ir_context->TakeNextId();
|
||||||
{
|
{
|
||||||
auto label = MakeUnique<opt::Instruction>(
|
auto label = MakeUnique<opt::Instruction>(ir_context.get(), SpvOpLabel, 0,
|
||||||
ir_context.get(), spv::Op::OpLabel, 0, new_exit_block_id,
|
new_exit_block_id,
|
||||||
opt::Instruction::OperandList());
|
opt::Instruction::OperandList());
|
||||||
auto new_exit_block = MakeUnique<opt::BasicBlock>(std::move(label));
|
auto new_exit_block = MakeUnique<opt::BasicBlock>(std::move(label));
|
||||||
new_exit_block->AddInstruction(
|
new_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
|
||||||
MakeUnique<opt::Instruction>(ir_context.get(), spv::Op::OpReturn, 0, 0,
|
ir_context.get(), SpvOpReturn, 0, 0, opt::Instruction::OperandList()));
|
||||||
opt::Instruction::OperandList()));
|
|
||||||
entry_point_function->AddBasicBlock(std::move(new_exit_block));
|
entry_point_function->AddBasicBlock(std::move(new_exit_block));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the new entry block
|
// Make the new entry block
|
||||||
{
|
{
|
||||||
auto label = MakeUnique<opt::Instruction>(
|
auto label = MakeUnique<opt::Instruction>(ir_context.get(), SpvOpLabel, 0,
|
||||||
ir_context.get(), spv::Op::OpLabel, 0, ir_context->TakeNextId(),
|
ir_context->TakeNextId(),
|
||||||
opt::Instruction::OperandList());
|
opt::Instruction::OperandList());
|
||||||
auto new_entry_block = MakeUnique<opt::BasicBlock>(std::move(label));
|
auto new_entry_block = MakeUnique<opt::BasicBlock>(std::move(label));
|
||||||
|
|
||||||
// Make an instruction to construct vec4(1.0, 0.0, 0.0, 1.0), representing
|
// Make an instruction to construct vec4(1.0, 0.0, 0.0, 1.0), representing
|
||||||
@ -234,7 +229,7 @@ bool ForceRenderRed(
|
|||||||
auto temp_vec4 = opt::analysis::Vector(float_type, 4);
|
auto temp_vec4 = opt::analysis::Vector(float_type, 4);
|
||||||
auto vec4_id = ir_context->get_type_mgr()->GetId(&temp_vec4);
|
auto vec4_id = ir_context->get_type_mgr()->GetId(&temp_vec4);
|
||||||
auto red = MakeUnique<opt::Instruction>(
|
auto red = MakeUnique<opt::Instruction>(
|
||||||
ir_context.get(), spv::Op::OpCompositeConstruct, vec4_id,
|
ir_context.get(), SpvOpCompositeConstruct, vec4_id,
|
||||||
ir_context->TakeNextId(), op_composite_construct_operands);
|
ir_context->TakeNextId(), op_composite_construct_operands);
|
||||||
auto red_id = red->result_id();
|
auto red_id = red->result_id();
|
||||||
new_entry_block->AddInstruction(std::move(red));
|
new_entry_block->AddInstruction(std::move(red));
|
||||||
@ -246,7 +241,7 @@ bool ForceRenderRed(
|
|||||||
opt::Instruction::OperandList op_store_operands = {variable_to_store_into,
|
opt::Instruction::OperandList op_store_operands = {variable_to_store_into,
|
||||||
value_to_be_stored};
|
value_to_be_stored};
|
||||||
new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
|
new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
|
||||||
ir_context.get(), spv::Op::OpStore, 0, 0, op_store_operands));
|
ir_context.get(), SpvOpStore, 0, 0, op_store_operands));
|
||||||
|
|
||||||
// We are going to attempt to construct 'false' as an expression of the form
|
// We are going to attempt to construct 'false' as an expression of the form
|
||||||
// 'literal1 > literal2'. If we succeed, we will later replace each literal
|
// 'literal1 > literal2'. If we succeed, we will later replace each literal
|
||||||
@ -318,7 +313,7 @@ bool ForceRenderRed(
|
|||||||
{SPV_OPERAND_TYPE_ID, {smaller_constant}},
|
{SPV_OPERAND_TYPE_ID, {smaller_constant}},
|
||||||
{SPV_OPERAND_TYPE_ID, {larger_constant}}};
|
{SPV_OPERAND_TYPE_ID, {larger_constant}}};
|
||||||
new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
|
new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
|
||||||
ir_context.get(), spv::Op::OpFOrdGreaterThan,
|
ir_context.get(), SpvOpFOrdGreaterThan,
|
||||||
ir_context->get_type_mgr()->GetId(registered_bool_type),
|
ir_context->get_type_mgr()->GetId(registered_bool_type),
|
||||||
id_guaranteed_to_be_false, greater_than_operands));
|
id_guaranteed_to_be_false, greater_than_operands));
|
||||||
|
|
||||||
@ -349,9 +344,9 @@ bool ForceRenderRed(
|
|||||||
opt::Operand else_block = {SPV_OPERAND_TYPE_ID, {new_exit_block_id}};
|
opt::Operand else_block = {SPV_OPERAND_TYPE_ID, {new_exit_block_id}};
|
||||||
opt::Instruction::OperandList op_branch_conditional_operands = {
|
opt::Instruction::OperandList op_branch_conditional_operands = {
|
||||||
false_condition, then_block, else_block};
|
false_condition, then_block, else_block};
|
||||||
new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
|
new_entry_block->AddInstruction(
|
||||||
ir_context.get(), spv::Op::OpBranchConditional, 0, 0,
|
MakeUnique<opt::Instruction>(ir_context.get(), SpvOpBranchConditional,
|
||||||
op_branch_conditional_operands));
|
0, 0, op_branch_conditional_operands));
|
||||||
|
|
||||||
entry_point_function->InsertBasicBlockBefore(
|
entry_point_function->InsertBasicBlockBefore(
|
||||||
std::move(new_entry_block), entry_point_function->entry().get());
|
std::move(new_entry_block), entry_point_function->entry().get());
|
||||||
|
@ -131,15 +131,14 @@ void FuzzerPass::ForEachInstructionWithInstructionDescriptor(
|
|||||||
// should skip when searching from 'base' for the desired instruction.
|
// should skip when searching from 'base' for the desired instruction.
|
||||||
// (An instruction that has a result id is represented by its own opcode,
|
// (An instruction that has a result id is represented by its own opcode,
|
||||||
// itself as 'base', and a skip-count of 0.)
|
// itself as 'base', and a skip-count of 0.)
|
||||||
std::vector<std::tuple<uint32_t, spv::Op, uint32_t>>
|
std::vector<std::tuple<uint32_t, SpvOp, uint32_t>> base_opcode_skip_triples;
|
||||||
base_opcode_skip_triples;
|
|
||||||
|
|
||||||
// The initial base instruction is the block label.
|
// The initial base instruction is the block label.
|
||||||
uint32_t base = block->id();
|
uint32_t base = block->id();
|
||||||
|
|
||||||
// Counts the number of times we have seen each opcode since we reset the
|
// Counts the number of times we have seen each opcode since we reset the
|
||||||
// base instruction.
|
// base instruction.
|
||||||
std::map<spv::Op, uint32_t> skip_count;
|
std::map<SpvOp, uint32_t> skip_count;
|
||||||
|
|
||||||
// Consider every instruction in the block. The label is excluded: it is
|
// Consider every instruction in the block. The label is excluded: it is
|
||||||
// only necessary to consider it as a base in case the first instruction
|
// only necessary to consider it as a base in case the first instruction
|
||||||
@ -152,7 +151,7 @@ void FuzzerPass::ForEachInstructionWithInstructionDescriptor(
|
|||||||
base = inst_it->result_id();
|
base = inst_it->result_id();
|
||||||
skip_count.clear();
|
skip_count.clear();
|
||||||
}
|
}
|
||||||
const spv::Op opcode = inst_it->opcode();
|
const SpvOp opcode = inst_it->opcode();
|
||||||
|
|
||||||
// Invoke the provided function, which might apply a transformation.
|
// Invoke the provided function, which might apply a transformation.
|
||||||
action(block, inst_it,
|
action(block, inst_it,
|
||||||
@ -331,7 +330,7 @@ uint32_t FuzzerPass::FindOrCreateStructType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id,
|
uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id,
|
||||||
spv::StorageClass storage_class) {
|
SpvStorageClass storage_class) {
|
||||||
// We do not use the type manager here, due to problems related to isomorphic
|
// We do not use the type manager here, due to problems related to isomorphic
|
||||||
// but distinct structs not being regarded as different.
|
// but distinct structs not being regarded as different.
|
||||||
auto existing_id = fuzzerutil::MaybeGetPointerType(
|
auto existing_id = fuzzerutil::MaybeGetPointerType(
|
||||||
@ -346,7 +345,7 @@ uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FuzzerPass::FindOrCreatePointerToIntegerType(
|
uint32_t FuzzerPass::FindOrCreatePointerToIntegerType(
|
||||||
uint32_t width, bool is_signed, spv::StorageClass storage_class) {
|
uint32_t width, bool is_signed, SpvStorageClass storage_class) {
|
||||||
return FindOrCreatePointerType(FindOrCreateIntegerType(width, is_signed),
|
return FindOrCreatePointerType(FindOrCreateIntegerType(width, is_signed),
|
||||||
storage_class);
|
storage_class);
|
||||||
}
|
}
|
||||||
@ -433,7 +432,7 @@ uint32_t FuzzerPass::FindOrCreateCompositeConstant(
|
|||||||
|
|
||||||
uint32_t FuzzerPass::FindOrCreateGlobalUndef(uint32_t type_id) {
|
uint32_t FuzzerPass::FindOrCreateGlobalUndef(uint32_t type_id) {
|
||||||
for (auto& inst : GetIRContext()->types_values()) {
|
for (auto& inst : GetIRContext()->types_values()) {
|
||||||
if (inst.opcode() == spv::Op::OpUndef && inst.type_id() == type_id) {
|
if (inst.opcode() == SpvOpUndef && inst.type_id() == type_id) {
|
||||||
return inst.result_id();
|
return inst.result_id();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -465,7 +464,7 @@ uint32_t FuzzerPass::FindOrCreateNullConstant(uint32_t type_id) {
|
|||||||
|
|
||||||
std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
|
std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
|
||||||
FuzzerPass::GetAvailableBasicTypesAndPointers(
|
FuzzerPass::GetAvailableBasicTypesAndPointers(
|
||||||
spv::StorageClass storage_class) const {
|
SpvStorageClass storage_class) const {
|
||||||
// Records all of the basic types available in the module.
|
// Records all of the basic types available in the module.
|
||||||
std::set<uint32_t> basic_types;
|
std::set<uint32_t> basic_types;
|
||||||
|
|
||||||
@ -481,23 +480,23 @@ FuzzerPass::GetAvailableBasicTypesAndPointers(
|
|||||||
// For pointer types with basic pointee types, associate the pointer type
|
// For pointer types with basic pointee types, associate the pointer type
|
||||||
// with the basic type.
|
// with the basic type.
|
||||||
switch (inst.opcode()) {
|
switch (inst.opcode()) {
|
||||||
case spv::Op::OpTypeBool:
|
case SpvOpTypeBool:
|
||||||
case spv::Op::OpTypeFloat:
|
case SpvOpTypeFloat:
|
||||||
case spv::Op::OpTypeInt:
|
case SpvOpTypeInt:
|
||||||
case spv::Op::OpTypeMatrix:
|
case SpvOpTypeMatrix:
|
||||||
case spv::Op::OpTypeVector:
|
case SpvOpTypeVector:
|
||||||
// These are all basic types.
|
// These are all basic types.
|
||||||
basic_types.insert(inst.result_id());
|
basic_types.insert(inst.result_id());
|
||||||
basic_type_to_pointers.insert({inst.result_id(), {}});
|
basic_type_to_pointers.insert({inst.result_id(), {}});
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpTypeArray:
|
case SpvOpTypeArray:
|
||||||
// An array type is basic if its base type is basic.
|
// An array type is basic if its base type is basic.
|
||||||
if (basic_types.count(inst.GetSingleWordInOperand(0))) {
|
if (basic_types.count(inst.GetSingleWordInOperand(0))) {
|
||||||
basic_types.insert(inst.result_id());
|
basic_types.insert(inst.result_id());
|
||||||
basic_type_to_pointers.insert({inst.result_id(), {}});
|
basic_type_to_pointers.insert({inst.result_id(), {}});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpTypeStruct: {
|
case SpvOpTypeStruct: {
|
||||||
// A struct type is basic if it does not have the Block/BufferBlock
|
// A struct type is basic if it does not have the Block/BufferBlock
|
||||||
// decoration, and if all of its members are basic.
|
// decoration, and if all of its members are basic.
|
||||||
if (!fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),
|
if (!fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),
|
||||||
@ -516,12 +515,11 @@ FuzzerPass::GetAvailableBasicTypesAndPointers(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case spv::Op::OpTypePointer: {
|
case SpvOpTypePointer: {
|
||||||
// We are interested in the pointer if its pointee type is basic and it
|
// We are interested in the pointer if its pointee type is basic and it
|
||||||
// has the right storage class.
|
// has the right storage class.
|
||||||
auto pointee_type = inst.GetSingleWordInOperand(1);
|
auto pointee_type = inst.GetSingleWordInOperand(1);
|
||||||
if (spv::StorageClass(inst.GetSingleWordInOperand(0)) ==
|
if (inst.GetSingleWordInOperand(0) == storage_class &&
|
||||||
storage_class &&
|
|
||||||
basic_types.count(pointee_type)) {
|
basic_types.count(pointee_type)) {
|
||||||
// The pointer has the desired storage class, and its pointee type is
|
// The pointer has the desired storage class, and its pointee type is
|
||||||
// a basic type, so we are interested in it. Associate it with its
|
// a basic type, so we are interested in it. Associate it with its
|
||||||
@ -543,22 +541,22 @@ uint32_t FuzzerPass::FindOrCreateZeroConstant(
|
|||||||
GetIRContext()->get_def_use_mgr()->GetDef(scalar_or_composite_type_id);
|
GetIRContext()->get_def_use_mgr()->GetDef(scalar_or_composite_type_id);
|
||||||
assert(type_instruction && "The type instruction must exist.");
|
assert(type_instruction && "The type instruction must exist.");
|
||||||
switch (type_instruction->opcode()) {
|
switch (type_instruction->opcode()) {
|
||||||
case spv::Op::OpTypeBool:
|
case SpvOpTypeBool:
|
||||||
return FindOrCreateBoolConstant(false, is_irrelevant);
|
return FindOrCreateBoolConstant(false, is_irrelevant);
|
||||||
case spv::Op::OpTypeFloat: {
|
case SpvOpTypeFloat: {
|
||||||
auto width = type_instruction->GetSingleWordInOperand(0);
|
auto width = type_instruction->GetSingleWordInOperand(0);
|
||||||
auto num_words = (width + 32 - 1) / 32;
|
auto num_words = (width + 32 - 1) / 32;
|
||||||
return FindOrCreateFloatConstant(std::vector<uint32_t>(num_words, 0),
|
return FindOrCreateFloatConstant(std::vector<uint32_t>(num_words, 0),
|
||||||
width, is_irrelevant);
|
width, is_irrelevant);
|
||||||
}
|
}
|
||||||
case spv::Op::OpTypeInt: {
|
case SpvOpTypeInt: {
|
||||||
auto width = type_instruction->GetSingleWordInOperand(0);
|
auto width = type_instruction->GetSingleWordInOperand(0);
|
||||||
auto num_words = (width + 32 - 1) / 32;
|
auto num_words = (width + 32 - 1) / 32;
|
||||||
return FindOrCreateIntegerConstant(
|
return FindOrCreateIntegerConstant(
|
||||||
std::vector<uint32_t>(num_words, 0), width,
|
std::vector<uint32_t>(num_words, 0), width,
|
||||||
type_instruction->GetSingleWordInOperand(1), is_irrelevant);
|
type_instruction->GetSingleWordInOperand(1), is_irrelevant);
|
||||||
}
|
}
|
||||||
case spv::Op::OpTypeArray: {
|
case SpvOpTypeArray: {
|
||||||
auto component_type_id = type_instruction->GetSingleWordInOperand(0);
|
auto component_type_id = type_instruction->GetSingleWordInOperand(0);
|
||||||
auto num_components =
|
auto num_components =
|
||||||
fuzzerutil::GetArraySize(*type_instruction, GetIRContext());
|
fuzzerutil::GetArraySize(*type_instruction, GetIRContext());
|
||||||
@ -568,8 +566,8 @@ uint32_t FuzzerPass::FindOrCreateZeroConstant(
|
|||||||
FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
|
FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
|
||||||
scalar_or_composite_type_id, is_irrelevant);
|
scalar_or_composite_type_id, is_irrelevant);
|
||||||
}
|
}
|
||||||
case spv::Op::OpTypeMatrix:
|
case SpvOpTypeMatrix:
|
||||||
case spv::Op::OpTypeVector: {
|
case SpvOpTypeVector: {
|
||||||
auto component_type_id = type_instruction->GetSingleWordInOperand(0);
|
auto component_type_id = type_instruction->GetSingleWordInOperand(0);
|
||||||
auto num_components = type_instruction->GetSingleWordInOperand(1);
|
auto num_components = type_instruction->GetSingleWordInOperand(1);
|
||||||
return FindOrCreateCompositeConstant(
|
return FindOrCreateCompositeConstant(
|
||||||
@ -578,7 +576,7 @@ uint32_t FuzzerPass::FindOrCreateZeroConstant(
|
|||||||
FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
|
FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
|
||||||
scalar_or_composite_type_id, is_irrelevant);
|
scalar_or_composite_type_id, is_irrelevant);
|
||||||
}
|
}
|
||||||
case spv::Op::OpTypeStruct: {
|
case SpvOpTypeStruct: {
|
||||||
assert(!fuzzerutil::HasBlockOrBufferBlockDecoration(
|
assert(!fuzzerutil::HasBlockOrBufferBlockDecoration(
|
||||||
GetIRContext(), scalar_or_composite_type_id) &&
|
GetIRContext(), scalar_or_composite_type_id) &&
|
||||||
"We do not construct constants of struct types decorated with "
|
"We do not construct constants of struct types decorated with "
|
||||||
@ -648,7 +646,7 @@ opt::BasicBlock* FuzzerPass::GetOrCreateSimpleLoopPreheader(
|
|||||||
|
|
||||||
// |maybe_preheader| is a preheader if it branches unconditionally to
|
// |maybe_preheader| is a preheader if it branches unconditionally to
|
||||||
// the header. We also require it not to be a loop header.
|
// the header. We also require it not to be a loop header.
|
||||||
if (maybe_preheader->terminator()->opcode() == spv::Op::OpBranch &&
|
if (maybe_preheader->terminator()->opcode() == SpvOpBranch &&
|
||||||
!maybe_preheader->IsLoopHeader()) {
|
!maybe_preheader->IsLoopHeader()) {
|
||||||
return maybe_preheader;
|
return maybe_preheader;
|
||||||
}
|
}
|
||||||
@ -685,8 +683,8 @@ opt::BasicBlock* FuzzerPass::SplitBlockAfterOpPhiOrOpVariable(
|
|||||||
|
|
||||||
// Find the first non-OpPhi and non-OpVariable instruction.
|
// Find the first non-OpPhi and non-OpVariable instruction.
|
||||||
auto non_phi_or_var_inst = &*block->begin();
|
auto non_phi_or_var_inst = &*block->begin();
|
||||||
while (non_phi_or_var_inst->opcode() == spv::Op::OpPhi ||
|
while (non_phi_or_var_inst->opcode() == SpvOpPhi ||
|
||||||
non_phi_or_var_inst->opcode() == spv::Op::OpVariable) {
|
non_phi_or_var_inst->opcode() == SpvOpVariable) {
|
||||||
non_phi_or_var_inst = non_phi_or_var_inst->NextNode();
|
non_phi_or_var_inst = non_phi_or_var_inst->NextNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,7 +706,7 @@ uint32_t FuzzerPass::FindOrCreateLocalVariable(
|
|||||||
(void)pointer_type;
|
(void)pointer_type;
|
||||||
assert(pointer_type && pointer_type->AsPointer() &&
|
assert(pointer_type && pointer_type->AsPointer() &&
|
||||||
pointer_type->AsPointer()->storage_class() ==
|
pointer_type->AsPointer()->storage_class() ==
|
||||||
spv::StorageClass::Function &&
|
SpvStorageClassFunction &&
|
||||||
"The pointer_type_id must refer to a defined pointer type with "
|
"The pointer_type_id must refer to a defined pointer type with "
|
||||||
"storage class Function");
|
"storage class Function");
|
||||||
auto function = fuzzerutil::FindFunction(GetIRContext(), function_id);
|
auto function = fuzzerutil::FindFunction(GetIRContext(), function_id);
|
||||||
@ -717,7 +715,7 @@ uint32_t FuzzerPass::FindOrCreateLocalVariable(
|
|||||||
// First we try to find a suitable existing variable.
|
// First we try to find a suitable existing variable.
|
||||||
// All of the local variable declarations are located in the first block.
|
// All of the local variable declarations are located in the first block.
|
||||||
for (auto& instruction : *function->begin()) {
|
for (auto& instruction : *function->begin()) {
|
||||||
if (instruction.opcode() != spv::Op::OpVariable) {
|
if (instruction.opcode() != SpvOpVariable) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// The existing OpVariable must have type |pointer_type_id|.
|
// The existing OpVariable must have type |pointer_type_id|.
|
||||||
@ -751,16 +749,15 @@ uint32_t FuzzerPass::FindOrCreateGlobalVariable(
|
|||||||
(void)pointer_type;
|
(void)pointer_type;
|
||||||
assert(
|
assert(
|
||||||
pointer_type && pointer_type->AsPointer() &&
|
pointer_type && pointer_type->AsPointer() &&
|
||||||
(pointer_type->AsPointer()->storage_class() ==
|
(pointer_type->AsPointer()->storage_class() == SpvStorageClassPrivate ||
|
||||||
spv::StorageClass::Private ||
|
|
||||||
pointer_type->AsPointer()->storage_class() ==
|
pointer_type->AsPointer()->storage_class() ==
|
||||||
spv::StorageClass::Workgroup) &&
|
SpvStorageClassWorkgroup) &&
|
||||||
"The pointer_type_id must refer to a defined pointer type with storage "
|
"The pointer_type_id must refer to a defined pointer type with storage "
|
||||||
"class Private or Workgroup");
|
"class Private or Workgroup");
|
||||||
|
|
||||||
// First we try to find a suitable existing variable.
|
// First we try to find a suitable existing variable.
|
||||||
for (auto& instruction : GetIRContext()->module()->types_values()) {
|
for (auto& instruction : GetIRContext()->module()->types_values()) {
|
||||||
if (instruction.opcode() != spv::Op::OpVariable) {
|
if (instruction.opcode() != SpvOpVariable) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// The existing OpVariable must have type |pointer_type_id|.
|
// The existing OpVariable must have type |pointer_type_id|.
|
||||||
@ -784,13 +781,13 @@ uint32_t FuzzerPass::FindOrCreateGlobalVariable(
|
|||||||
uint32_t result_id = GetFuzzerContext()->GetFreshId();
|
uint32_t result_id = GetFuzzerContext()->GetFreshId();
|
||||||
|
|
||||||
// A variable with storage class Workgroup shouldn't have an initializer.
|
// A variable with storage class Workgroup shouldn't have an initializer.
|
||||||
if (storage_class == spv::StorageClass::Workgroup) {
|
if (storage_class == SpvStorageClassWorkgroup) {
|
||||||
ApplyTransformation(TransformationAddGlobalVariable(
|
ApplyTransformation(TransformationAddGlobalVariable(
|
||||||
result_id, pointer_type_id, spv::StorageClass::Workgroup, 0,
|
result_id, pointer_type_id, SpvStorageClassWorkgroup, 0,
|
||||||
pointee_value_is_irrelevant));
|
pointee_value_is_irrelevant));
|
||||||
} else {
|
} else {
|
||||||
ApplyTransformation(TransformationAddGlobalVariable(
|
ApplyTransformation(TransformationAddGlobalVariable(
|
||||||
result_id, pointer_type_id, spv::StorageClass::Private,
|
result_id, pointer_type_id, SpvStorageClassPrivate,
|
||||||
FindOrCreateZeroConstant(pointee_type_id, pointee_value_is_irrelevant),
|
FindOrCreateZeroConstant(pointee_type_id, pointee_value_is_irrelevant),
|
||||||
pointee_value_is_irrelevant));
|
pointee_value_is_irrelevant));
|
||||||
}
|
}
|
||||||
|
@ -159,14 +159,14 @@ class FuzzerPass {
|
|||||||
// already exist) and storage class |storage_class|. A transformation is
|
// already exist) and storage class |storage_class|. A transformation is
|
||||||
// applied to add the pointer if it does not already exist.
|
// applied to add the pointer if it does not already exist.
|
||||||
uint32_t FindOrCreatePointerType(uint32_t base_type_id,
|
uint32_t FindOrCreatePointerType(uint32_t base_type_id,
|
||||||
spv::StorageClass storage_class);
|
SpvStorageClass storage_class);
|
||||||
|
|
||||||
// Returns the id of an OpTypePointer instruction, with a integer base
|
// Returns the id of an OpTypePointer instruction, with a integer base
|
||||||
// type of width and signedness specified by |width| and |is_signed|,
|
// type of width and signedness specified by |width| and |is_signed|,
|
||||||
// respectively. If the pointer type or required integer base type do not
|
// respectively. If the pointer type or required integer base type do not
|
||||||
// exist, transformations are applied to add them.
|
// exist, transformations are applied to add them.
|
||||||
uint32_t FindOrCreatePointerToIntegerType(uint32_t width, bool is_signed,
|
uint32_t FindOrCreatePointerToIntegerType(uint32_t width, bool is_signed,
|
||||||
spv::StorageClass storage_class);
|
SpvStorageClass storage_class);
|
||||||
|
|
||||||
// Returns the id of an OpConstant instruction, with a integer type of
|
// Returns the id of an OpConstant instruction, with a integer type of
|
||||||
// width and signedness specified by |width| and |is_signed|, respectively,
|
// width and signedness specified by |width| and |is_signed|, respectively,
|
||||||
@ -239,7 +239,7 @@ class FuzzerPass {
|
|||||||
// storage class, and the sequence will have multiple elements if there are
|
// storage class, and the sequence will have multiple elements if there are
|
||||||
// repeated pointer declarations for the same basic type and storage class.
|
// repeated pointer declarations for the same basic type and storage class.
|
||||||
std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
|
std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
|
||||||
GetAvailableBasicTypesAndPointers(spv::StorageClass storage_class) const;
|
GetAvailableBasicTypesAndPointers(SpvStorageClass storage_class) const;
|
||||||
|
|
||||||
// Given a type id, |scalar_or_composite_type_id|, which must correspond to
|
// Given a type id, |scalar_or_composite_type_id|, which must correspond to
|
||||||
// some scalar or composite type, returns the result id of an instruction
|
// some scalar or composite type, returns the result id of an instruction
|
||||||
|
@ -34,16 +34,15 @@ void FuzzerPassAddAccessChains::Apply() {
|
|||||||
opt::BasicBlock::iterator inst_it,
|
opt::BasicBlock::iterator inst_it,
|
||||||
const protobufs::InstructionDescriptor& instruction_descriptor)
|
const protobufs::InstructionDescriptor& instruction_descriptor)
|
||||||
-> void {
|
-> void {
|
||||||
assert(
|
assert(inst_it->opcode() ==
|
||||||
inst_it->opcode() ==
|
instruction_descriptor.target_instruction_opcode() &&
|
||||||
spv::Op(instruction_descriptor.target_instruction_opcode()) &&
|
"The opcode of the instruction we might insert before must be "
|
||||||
"The opcode of the instruction we might insert before must be "
|
"the same as the opcode in the descriptor for the instruction");
|
||||||
"the same as the opcode in the descriptor for the instruction");
|
|
||||||
|
|
||||||
// Check whether it is legitimate to insert an access chain
|
// Check whether it is legitimate to insert an access chain
|
||||||
// instruction before this instruction.
|
// instruction before this instruction.
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAccessChain,
|
||||||
spv::Op::OpAccessChain, inst_it)) {
|
inst_it)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,8 +64,8 @@ void FuzzerPassAddAccessChains::Apply() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (instruction->opcode()) {
|
switch (instruction->opcode()) {
|
||||||
case spv::Op::OpConstantNull:
|
case SpvOpConstantNull:
|
||||||
case spv::Op::OpUndef:
|
case SpvOpUndef:
|
||||||
// Do not allow making an access chain from a null or
|
// Do not allow making an access chain from a null or
|
||||||
// undefined pointer. (We can eliminate these cases
|
// undefined pointer. (We can eliminate these cases
|
||||||
// before actually checking that the instruction is a
|
// before actually checking that the instruction is a
|
||||||
@ -79,7 +78,7 @@ void FuzzerPassAddAccessChains::Apply() {
|
|||||||
// make an access chain from it.
|
// make an access chain from it.
|
||||||
return context->get_def_use_mgr()
|
return context->get_def_use_mgr()
|
||||||
->GetDef(instruction->type_id())
|
->GetDef(instruction->type_id())
|
||||||
->opcode() == spv::Op::OpTypePointer;
|
->opcode() == SpvOpTypePointer;
|
||||||
});
|
});
|
||||||
|
|
||||||
// At this point, |relevant_instructions| contains all the pointers
|
// At this point, |relevant_instructions| contains all the pointers
|
||||||
@ -113,14 +112,14 @@ void FuzzerPassAddAccessChains::Apply() {
|
|||||||
}
|
}
|
||||||
uint32_t bound;
|
uint32_t bound;
|
||||||
switch (subobject_type->opcode()) {
|
switch (subobject_type->opcode()) {
|
||||||
case spv::Op::OpTypeArray:
|
case SpvOpTypeArray:
|
||||||
bound = fuzzerutil::GetArraySize(*subobject_type, GetIRContext());
|
bound = fuzzerutil::GetArraySize(*subobject_type, GetIRContext());
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpTypeMatrix:
|
case SpvOpTypeMatrix:
|
||||||
case spv::Op::OpTypeVector:
|
case SpvOpTypeVector:
|
||||||
bound = subobject_type->GetSingleWordInOperand(1);
|
bound = subobject_type->GetSingleWordInOperand(1);
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpTypeStruct:
|
case SpvOpTypeStruct:
|
||||||
bound = fuzzerutil::GetNumberOfStructMembers(*subobject_type);
|
bound = fuzzerutil::GetNumberOfStructMembers(*subobject_type);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -141,9 +140,9 @@ void FuzzerPassAddAccessChains::Apply() {
|
|||||||
GetFuzzerContext()->GetRandomIndexForAccessChain(bound);
|
GetFuzzerContext()->GetRandomIndexForAccessChain(bound);
|
||||||
|
|
||||||
switch (subobject_type->opcode()) {
|
switch (subobject_type->opcode()) {
|
||||||
case spv::Op::OpTypeArray:
|
case SpvOpTypeArray:
|
||||||
case spv::Op::OpTypeMatrix:
|
case SpvOpTypeMatrix:
|
||||||
case spv::Op::OpTypeVector: {
|
case SpvOpTypeVector: {
|
||||||
// The index will be clamped
|
// The index will be clamped
|
||||||
|
|
||||||
bool is_signed = GetFuzzerContext()->ChooseEven();
|
bool is_signed = GetFuzzerContext()->ChooseEven();
|
||||||
@ -165,7 +164,7 @@ void FuzzerPassAddAccessChains::Apply() {
|
|||||||
subobject_type_id = subobject_type->GetSingleWordInOperand(0);
|
subobject_type_id = subobject_type->GetSingleWordInOperand(0);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpTypeStruct:
|
case SpvOpTypeStruct:
|
||||||
index_ids.push_back(FindOrCreateIntegerConstant(
|
index_ids.push_back(FindOrCreateIntegerConstant(
|
||||||
{index_value}, 32, GetFuzzerContext()->ChooseEven(), false));
|
{index_value}, 32, GetFuzzerContext()->ChooseEven(), false));
|
||||||
subobject_type_id =
|
subobject_type_id =
|
||||||
@ -179,7 +178,7 @@ void FuzzerPassAddAccessChains::Apply() {
|
|||||||
// pointer suitable for the access chain's result type exists, so we
|
// pointer suitable for the access chain's result type exists, so we
|
||||||
// create one if it does not.
|
// create one if it does not.
|
||||||
FindOrCreatePointerType(subobject_type_id,
|
FindOrCreatePointerType(subobject_type_id,
|
||||||
static_cast<spv::StorageClass>(
|
static_cast<SpvStorageClass>(
|
||||||
pointer_type->GetSingleWordInOperand(0)));
|
pointer_type->GetSingleWordInOperand(0)));
|
||||||
// Apply the transformation to add an access chain.
|
// Apply the transformation to add an access chain.
|
||||||
ApplyTransformation(TransformationAccessChain(
|
ApplyTransformation(TransformationAccessChain(
|
||||||
|
@ -53,8 +53,8 @@ void FuzzerPassAddCompositeExtract::Apply() {
|
|||||||
opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
|
opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
|
||||||
opt::BasicBlock::iterator inst_it,
|
opt::BasicBlock::iterator inst_it,
|
||||||
const protobufs::InstructionDescriptor& instruction_descriptor) {
|
const protobufs::InstructionDescriptor& instruction_descriptor) {
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
|
||||||
spv::Op::OpCompositeExtract, inst_it)) {
|
inst_it)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,15 +97,15 @@ void FuzzerPassAddCompositeExtract::Apply() {
|
|||||||
assert(type_inst && "Composite instruction has invalid type id");
|
assert(type_inst && "Composite instruction has invalid type id");
|
||||||
|
|
||||||
switch (type_inst->opcode()) {
|
switch (type_inst->opcode()) {
|
||||||
case spv::Op::OpTypeArray:
|
case SpvOpTypeArray:
|
||||||
number_of_members =
|
number_of_members =
|
||||||
fuzzerutil::GetArraySize(*type_inst, GetIRContext());
|
fuzzerutil::GetArraySize(*type_inst, GetIRContext());
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpTypeVector:
|
case SpvOpTypeVector:
|
||||||
case spv::Op::OpTypeMatrix:
|
case SpvOpTypeMatrix:
|
||||||
number_of_members = type_inst->GetSingleWordInOperand(1);
|
number_of_members = type_inst->GetSingleWordInOperand(1);
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpTypeStruct:
|
case SpvOpTypeStruct:
|
||||||
number_of_members = type_inst->NumInOperands();
|
number_of_members = type_inst->NumInOperands();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -122,12 +122,12 @@ void FuzzerPassAddCompositeExtract::Apply() {
|
|||||||
number_of_members));
|
number_of_members));
|
||||||
|
|
||||||
switch (type_inst->opcode()) {
|
switch (type_inst->opcode()) {
|
||||||
case spv::Op::OpTypeArray:
|
case SpvOpTypeArray:
|
||||||
case spv::Op::OpTypeVector:
|
case SpvOpTypeVector:
|
||||||
case spv::Op::OpTypeMatrix:
|
case SpvOpTypeMatrix:
|
||||||
type_id = type_inst->GetSingleWordInOperand(0);
|
type_id = type_inst->GetSingleWordInOperand(0);
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpTypeStruct:
|
case SpvOpTypeStruct:
|
||||||
type_id = type_inst->GetSingleWordInOperand(indices.back());
|
type_id = type_inst->GetSingleWordInOperand(indices.back());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -36,11 +36,10 @@ void FuzzerPassAddCompositeInserts::Apply() {
|
|||||||
opt::BasicBlock::iterator instruction_iterator,
|
opt::BasicBlock::iterator instruction_iterator,
|
||||||
const protobufs::InstructionDescriptor& instruction_descriptor)
|
const protobufs::InstructionDescriptor& instruction_descriptor)
|
||||||
-> void {
|
-> void {
|
||||||
assert(
|
assert(instruction_iterator->opcode() ==
|
||||||
instruction_iterator->opcode() ==
|
instruction_descriptor.target_instruction_opcode() &&
|
||||||
spv::Op(instruction_descriptor.target_instruction_opcode()) &&
|
"The opcode of the instruction we might insert before must be "
|
||||||
"The opcode of the instruction we might insert before must be "
|
"the same as the opcode in the descriptor for the instruction");
|
||||||
"the same as the opcode in the descriptor for the instruction");
|
|
||||||
|
|
||||||
// Randomly decide whether to try adding an OpCompositeInsert
|
// Randomly decide whether to try adding an OpCompositeInsert
|
||||||
// instruction.
|
// instruction.
|
||||||
@ -52,7 +51,7 @@ void FuzzerPassAddCompositeInserts::Apply() {
|
|||||||
// It must be possible to insert an OpCompositeInsert instruction
|
// It must be possible to insert an OpCompositeInsert instruction
|
||||||
// before |instruction_iterator|.
|
// before |instruction_iterator|.
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
||||||
spv::Op::OpCompositeInsert, instruction_iterator)) {
|
SpvOpCompositeInsert, instruction_iterator)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,15 +114,15 @@ uint32_t FuzzerPassAddCompositeTypes::ChooseScalarOrCompositeType() {
|
|||||||
std::vector<uint32_t> candidates;
|
std::vector<uint32_t> candidates;
|
||||||
for (auto& inst : GetIRContext()->types_values()) {
|
for (auto& inst : GetIRContext()->types_values()) {
|
||||||
switch (inst.opcode()) {
|
switch (inst.opcode()) {
|
||||||
case spv::Op::OpTypeArray:
|
case SpvOpTypeArray:
|
||||||
case spv::Op::OpTypeBool:
|
case SpvOpTypeBool:
|
||||||
case spv::Op::OpTypeFloat:
|
case SpvOpTypeFloat:
|
||||||
case spv::Op::OpTypeInt:
|
case SpvOpTypeInt:
|
||||||
case spv::Op::OpTypeMatrix:
|
case SpvOpTypeMatrix:
|
||||||
case spv::Op::OpTypeVector:
|
case SpvOpTypeVector:
|
||||||
candidates.push_back(inst.result_id());
|
candidates.push_back(inst.result_id());
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpTypeStruct: {
|
case SpvOpTypeStruct: {
|
||||||
if (!fuzzerutil::MembersHaveBuiltInDecoration(GetIRContext(),
|
if (!fuzzerutil::MembersHaveBuiltInDecoration(GetIRContext(),
|
||||||
inst.result_id()) &&
|
inst.result_id()) &&
|
||||||
!fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),
|
!fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),
|
||||||
|
@ -36,7 +36,7 @@ void FuzzerPassAddCopyMemory::Apply() {
|
|||||||
opt::BasicBlock::iterator inst_it,
|
opt::BasicBlock::iterator inst_it,
|
||||||
const protobufs::InstructionDescriptor& instruction_descriptor) {
|
const protobufs::InstructionDescriptor& instruction_descriptor) {
|
||||||
// Check that we can insert an OpCopyMemory before this instruction.
|
// Check that we can insert an OpCopyMemory before this instruction.
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpCopyMemory,
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyMemory,
|
||||||
inst_it)) {
|
inst_it)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -61,8 +61,8 @@ void FuzzerPassAddCopyMemory::Apply() {
|
|||||||
|
|
||||||
// Decide whether to create global or local variable.
|
// Decide whether to create global or local variable.
|
||||||
auto storage_class = GetFuzzerContext()->ChooseEven()
|
auto storage_class = GetFuzzerContext()->ChooseEven()
|
||||||
? spv::StorageClass::Private
|
? SpvStorageClassPrivate
|
||||||
: spv::StorageClass::Function;
|
: SpvStorageClassFunction;
|
||||||
|
|
||||||
auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
|
auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
|
||||||
GetIRContext(), inst->type_id());
|
GetIRContext(), inst->type_id());
|
||||||
|
@ -29,14 +29,12 @@ bool IsBitWidthSupported(opt::IRContext* ir_context, uint32_t bit_width) {
|
|||||||
return true;
|
return true;
|
||||||
case 64:
|
case 64:
|
||||||
return ir_context->get_feature_mgr()->HasCapability(
|
return ir_context->get_feature_mgr()->HasCapability(
|
||||||
spv::Capability::Float64) &&
|
SpvCapabilityFloat64) &&
|
||||||
ir_context->get_feature_mgr()->HasCapability(
|
ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt64);
|
||||||
spv::Capability::Int64);
|
|
||||||
case 16:
|
case 16:
|
||||||
return ir_context->get_feature_mgr()->HasCapability(
|
return ir_context->get_feature_mgr()->HasCapability(
|
||||||
spv::Capability::Float16) &&
|
SpvCapabilityFloat16) &&
|
||||||
ir_context->get_feature_mgr()->HasCapability(
|
ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt16);
|
||||||
spv::Capability::Int16);
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -68,8 +66,7 @@ void FuzzerPassAddEquationInstructions::Apply() {
|
|||||||
// as an example opcode for this check, to be representative of *some*
|
// as an example opcode for this check, to be representative of *some*
|
||||||
// opcode that defines an equation, even though we may choose a
|
// opcode that defines an equation, even though we may choose a
|
||||||
// different opcode below.
|
// different opcode below.
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpIAdd,
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpIAdd, inst_it)) {
|
||||||
inst_it)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +78,7 @@ void FuzzerPassAddEquationInstructions::Apply() {
|
|||||||
[this](opt::IRContext* /*unused*/,
|
[this](opt::IRContext* /*unused*/,
|
||||||
opt::Instruction* instruction) -> bool {
|
opt::Instruction* instruction) -> bool {
|
||||||
return instruction->result_id() && instruction->type_id() &&
|
return instruction->result_id() && instruction->type_id() &&
|
||||||
instruction->opcode() != spv::Op::OpUndef &&
|
instruction->opcode() != SpvOpUndef &&
|
||||||
!GetTransformationContext()
|
!GetTransformationContext()
|
||||||
->GetFactManager()
|
->GetFactManager()
|
||||||
->IdIsIrrelevant(instruction->result_id());
|
->IdIsIrrelevant(instruction->result_id());
|
||||||
@ -89,16 +86,15 @@ void FuzzerPassAddEquationInstructions::Apply() {
|
|||||||
|
|
||||||
// Try the opcodes for which we know how to make ids at random until
|
// Try the opcodes for which we know how to make ids at random until
|
||||||
// something works.
|
// something works.
|
||||||
std::vector<spv::Op> candidate_opcodes = {
|
std::vector<SpvOp> candidate_opcodes = {
|
||||||
spv::Op::OpIAdd, spv::Op::OpISub, spv::Op::OpLogicalNot,
|
SpvOpIAdd, SpvOpISub, SpvOpLogicalNot, SpvOpSNegate,
|
||||||
spv::Op::OpSNegate, spv::Op::OpConvertUToF, spv::Op::OpConvertSToF,
|
SpvOpConvertUToF, SpvOpConvertSToF, SpvOpBitcast};
|
||||||
spv::Op::OpBitcast};
|
|
||||||
do {
|
do {
|
||||||
auto opcode =
|
auto opcode =
|
||||||
GetFuzzerContext()->RemoveAtRandomIndex(&candidate_opcodes);
|
GetFuzzerContext()->RemoveAtRandomIndex(&candidate_opcodes);
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case spv::Op::OpConvertSToF:
|
case SpvOpConvertSToF:
|
||||||
case spv::Op::OpConvertUToF: {
|
case SpvOpConvertUToF: {
|
||||||
std::vector<const opt::Instruction*> candidate_instructions;
|
std::vector<const opt::Instruction*> candidate_instructions;
|
||||||
for (const auto* inst :
|
for (const auto* inst :
|
||||||
GetIntegerInstructions(available_instructions)) {
|
GetIntegerInstructions(available_instructions)) {
|
||||||
@ -148,7 +144,7 @@ void FuzzerPassAddEquationInstructions::Apply() {
|
|||||||
{operand->result_id()}, instruction_descriptor));
|
{operand->result_id()}, instruction_descriptor));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case spv::Op::OpBitcast: {
|
case SpvOpBitcast: {
|
||||||
const auto candidate_instructions =
|
const auto candidate_instructions =
|
||||||
GetNumericalInstructions(available_instructions);
|
GetNumericalInstructions(available_instructions);
|
||||||
|
|
||||||
@ -201,8 +197,8 @@ void FuzzerPassAddEquationInstructions::Apply() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpIAdd:
|
case SpvOpIAdd:
|
||||||
case spv::Op::OpISub: {
|
case SpvOpISub: {
|
||||||
// Instructions of integer (scalar or vector) result type are
|
// Instructions of integer (scalar or vector) result type are
|
||||||
// suitable for these opcodes.
|
// suitable for these opcodes.
|
||||||
auto integer_instructions =
|
auto integer_instructions =
|
||||||
@ -255,7 +251,7 @@ void FuzzerPassAddEquationInstructions::Apply() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case spv::Op::OpLogicalNot: {
|
case SpvOpLogicalNot: {
|
||||||
// Choose any available instruction of boolean scalar/vector
|
// Choose any available instruction of boolean scalar/vector
|
||||||
// result type and equate its negation with a fresh id.
|
// result type and equate its negation with a fresh id.
|
||||||
auto boolean_instructions =
|
auto boolean_instructions =
|
||||||
@ -272,7 +268,7 @@ void FuzzerPassAddEquationInstructions::Apply() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case spv::Op::OpSNegate: {
|
case SpvOpSNegate: {
|
||||||
// Similar to OpLogicalNot, but for signed integer negation.
|
// Similar to OpLogicalNot, but for signed integer negation.
|
||||||
auto integer_instructions =
|
auto integer_instructions =
|
||||||
GetIntegerInstructions(available_instructions);
|
GetIntegerInstructions(available_instructions);
|
||||||
|
@ -39,8 +39,8 @@ void FuzzerPassAddFunctionCalls::Apply() {
|
|||||||
-> void {
|
-> void {
|
||||||
// Check whether it is legitimate to insert a function call before the
|
// Check whether it is legitimate to insert a function call before the
|
||||||
// instruction.
|
// instruction.
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpFunctionCall,
|
||||||
spv::Op::OpFunctionCall, inst_it)) {
|
inst_it)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,8 +112,8 @@ std::vector<uint32_t> FuzzerPassAddFunctionCalls::ChooseFunctionCallArguments(
|
|||||||
auto available_pointers = FindAvailableInstructions(
|
auto available_pointers = FindAvailableInstructions(
|
||||||
caller_function, caller_block, caller_inst_it,
|
caller_function, caller_block, caller_inst_it,
|
||||||
[this, caller_block](opt::IRContext* /*unused*/, opt::Instruction* inst) {
|
[this, caller_block](opt::IRContext* /*unused*/, opt::Instruction* inst) {
|
||||||
if (inst->opcode() != spv::Op::OpVariable ||
|
if (inst->opcode() != SpvOpVariable ||
|
||||||
inst->opcode() != spv::Op::OpFunctionParameter) {
|
inst->opcode() != SpvOpFunctionParameter) {
|
||||||
// Function parameters and variables are the only
|
// Function parameters and variables are the only
|
||||||
// kinds of pointer that can be used as actual
|
// kinds of pointer that can be used as actual
|
||||||
// parameters.
|
// parameters.
|
||||||
@ -172,15 +172,15 @@ std::vector<uint32_t> FuzzerPassAddFunctionCalls::ChooseFunctionCallArguments(
|
|||||||
auto storage_class = param_type->AsPointer()->storage_class();
|
auto storage_class = param_type->AsPointer()->storage_class();
|
||||||
auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
|
auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
|
||||||
GetIRContext(), param->type_id());
|
GetIRContext(), param->type_id());
|
||||||
if (storage_class == spv::StorageClass::Function) {
|
if (storage_class == SpvStorageClassFunction) {
|
||||||
// Add a new zero-initialized local variable to the current
|
// Add a new zero-initialized local variable to the current
|
||||||
// function, noting that its pointee value is irrelevant.
|
// function, noting that its pointee value is irrelevant.
|
||||||
ApplyTransformation(TransformationAddLocalVariable(
|
ApplyTransformation(TransformationAddLocalVariable(
|
||||||
fresh_variable_id, param->type_id(), caller_function->result_id(),
|
fresh_variable_id, param->type_id(), caller_function->result_id(),
|
||||||
FindOrCreateZeroConstant(pointee_type_id, false), true));
|
FindOrCreateZeroConstant(pointee_type_id, false), true));
|
||||||
} else {
|
} else {
|
||||||
assert((storage_class == spv::StorageClass::Private ||
|
assert((storage_class == SpvStorageClassPrivate ||
|
||||||
storage_class == spv::StorageClass::Workgroup) &&
|
storage_class == SpvStorageClassWorkgroup) &&
|
||||||
"Only Function, Private and Workgroup storage classes are "
|
"Only Function, Private and Workgroup storage classes are "
|
||||||
"supported at present.");
|
"supported at present.");
|
||||||
// Add a new global variable to the module, zero-initializing it if
|
// Add a new global variable to the module, zero-initializing it if
|
||||||
@ -188,7 +188,7 @@ std::vector<uint32_t> FuzzerPassAddFunctionCalls::ChooseFunctionCallArguments(
|
|||||||
// irrelevant.
|
// irrelevant.
|
||||||
ApplyTransformation(TransformationAddGlobalVariable(
|
ApplyTransformation(TransformationAddGlobalVariable(
|
||||||
fresh_variable_id, param->type_id(), storage_class,
|
fresh_variable_id, param->type_id(), storage_class,
|
||||||
storage_class == spv::StorageClass::Private
|
storage_class == SpvStorageClassPrivate
|
||||||
? FindOrCreateZeroConstant(pointee_type_id, false)
|
? FindOrCreateZeroConstant(pointee_type_id, false)
|
||||||
: 0,
|
: 0,
|
||||||
true));
|
true));
|
||||||
|
@ -29,17 +29,16 @@ FuzzerPassAddGlobalVariables::FuzzerPassAddGlobalVariables(
|
|||||||
transformations, ignore_inapplicable_transformations) {}
|
transformations, ignore_inapplicable_transformations) {}
|
||||||
|
|
||||||
void FuzzerPassAddGlobalVariables::Apply() {
|
void FuzzerPassAddGlobalVariables::Apply() {
|
||||||
spv::StorageClass variable_storage_class = spv::StorageClass::Private;
|
SpvStorageClass variable_storage_class = SpvStorageClassPrivate;
|
||||||
for (auto& entry_point : GetIRContext()->module()->entry_points()) {
|
for (auto& entry_point : GetIRContext()->module()->entry_points()) {
|
||||||
// If the execution model of some entry point is GLCompute,
|
// If the execution model of some entry point is GLCompute,
|
||||||
// then the variable storage class may be Workgroup.
|
// then the variable storage class may be Workgroup.
|
||||||
if (spv::ExecutionModel(entry_point.GetSingleWordInOperand(0)) ==
|
if (entry_point.GetSingleWordInOperand(0) == SpvExecutionModelGLCompute) {
|
||||||
spv::ExecutionModel::GLCompute) {
|
|
||||||
variable_storage_class =
|
variable_storage_class =
|
||||||
GetFuzzerContext()->ChoosePercentage(
|
GetFuzzerContext()->ChoosePercentage(
|
||||||
GetFuzzerContext()->GetChanceOfChoosingWorkgroupStorageClass())
|
GetFuzzerContext()->GetChanceOfChoosingWorkgroupStorageClass())
|
||||||
? spv::StorageClass::Workgroup
|
? SpvStorageClassWorkgroup
|
||||||
: spv::StorageClass::Private;
|
: SpvStorageClassPrivate;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,7 +87,7 @@ void FuzzerPassAddGlobalVariables::Apply() {
|
|||||||
ApplyTransformation(TransformationAddGlobalVariable(
|
ApplyTransformation(TransformationAddGlobalVariable(
|
||||||
GetFuzzerContext()->GetFreshId(), pointer_type_id,
|
GetFuzzerContext()->GetFreshId(), pointer_type_id,
|
||||||
variable_storage_class,
|
variable_storage_class,
|
||||||
variable_storage_class == spv::StorageClass::Private
|
variable_storage_class == SpvStorageClassPrivate
|
||||||
? FindOrCreateZeroConstant(basic_type, false)
|
? FindOrCreateZeroConstant(basic_type, false)
|
||||||
: 0,
|
: 0,
|
||||||
true));
|
true));
|
||||||
|
@ -34,11 +34,10 @@ void FuzzerPassAddLoads::Apply() {
|
|||||||
opt::BasicBlock::iterator inst_it,
|
opt::BasicBlock::iterator inst_it,
|
||||||
const protobufs::InstructionDescriptor& instruction_descriptor)
|
const protobufs::InstructionDescriptor& instruction_descriptor)
|
||||||
-> void {
|
-> void {
|
||||||
assert(
|
assert(inst_it->opcode() ==
|
||||||
inst_it->opcode() ==
|
instruction_descriptor.target_instruction_opcode() &&
|
||||||
spv::Op(instruction_descriptor.target_instruction_opcode()) &&
|
"The opcode of the instruction we might insert before must be "
|
||||||
"The opcode of the instruction we might insert before must be "
|
"the same as the opcode in the descriptor for the instruction");
|
||||||
"the same as the opcode in the descriptor for the instruction");
|
|
||||||
|
|
||||||
// Randomly decide whether to try inserting a load here.
|
// Randomly decide whether to try inserting a load here.
|
||||||
if (!GetFuzzerContext()->ChoosePercentage(
|
if (!GetFuzzerContext()->ChoosePercentage(
|
||||||
@ -48,11 +47,10 @@ void FuzzerPassAddLoads::Apply() {
|
|||||||
|
|
||||||
// Check whether it is legitimate to insert a load or atomic load before
|
// Check whether it is legitimate to insert a load or atomic load before
|
||||||
// this instruction.
|
// this instruction.
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, inst_it)) {
|
||||||
inst_it)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpAtomicLoad,
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAtomicLoad,
|
||||||
inst_it)) {
|
inst_it)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -66,8 +64,8 @@ void FuzzerPassAddLoads::Apply() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (instruction->opcode()) {
|
switch (instruction->opcode()) {
|
||||||
case spv::Op::OpConstantNull:
|
case SpvOpConstantNull:
|
||||||
case spv::Op::OpUndef:
|
case SpvOpUndef:
|
||||||
// Do not allow loading from a null or undefined pointer;
|
// Do not allow loading from a null or undefined pointer;
|
||||||
// this might be OK if the block is dead, but for now we
|
// this might be OK if the block is dead, but for now we
|
||||||
// conservatively avoid it.
|
// conservatively avoid it.
|
||||||
@ -77,7 +75,7 @@ void FuzzerPassAddLoads::Apply() {
|
|||||||
}
|
}
|
||||||
return context->get_def_use_mgr()
|
return context->get_def_use_mgr()
|
||||||
->GetDef(instruction->type_id())
|
->GetDef(instruction->type_id())
|
||||||
->opcode() == spv::Op::OpTypePointer;
|
->opcode() == SpvOpTypePointer;
|
||||||
});
|
});
|
||||||
|
|
||||||
// At this point, |relevant_instructions| contains all the pointers
|
// At this point, |relevant_instructions| contains all the pointers
|
||||||
@ -94,25 +92,25 @@ void FuzzerPassAddLoads::Apply() {
|
|||||||
uint32_t memory_scope_id = 0;
|
uint32_t memory_scope_id = 0;
|
||||||
uint32_t memory_semantics_id = 0;
|
uint32_t memory_semantics_id = 0;
|
||||||
|
|
||||||
auto storage_class = static_cast<spv::StorageClass>(
|
auto storage_class = static_cast<SpvStorageClass>(
|
||||||
GetIRContext()
|
GetIRContext()
|
||||||
->get_def_use_mgr()
|
->get_def_use_mgr()
|
||||||
->GetDef(chosen_instruction->type_id())
|
->GetDef(chosen_instruction->type_id())
|
||||||
->GetSingleWordInOperand(0));
|
->GetSingleWordInOperand(0));
|
||||||
|
|
||||||
switch (storage_class) {
|
switch (storage_class) {
|
||||||
case spv::StorageClass::StorageBuffer:
|
case SpvStorageClassStorageBuffer:
|
||||||
case spv::StorageClass::PhysicalStorageBuffer:
|
case SpvStorageClassPhysicalStorageBuffer:
|
||||||
case spv::StorageClass::Workgroup:
|
case SpvStorageClassWorkgroup:
|
||||||
case spv::StorageClass::CrossWorkgroup:
|
case SpvStorageClassCrossWorkgroup:
|
||||||
case spv::StorageClass::AtomicCounter:
|
case SpvStorageClassAtomicCounter:
|
||||||
case spv::StorageClass::Image:
|
case SpvStorageClassImage:
|
||||||
if (GetFuzzerContext()->ChoosePercentage(
|
if (GetFuzzerContext()->ChoosePercentage(
|
||||||
GetFuzzerContext()->GetChanceOfAddingAtomicLoad())) {
|
GetFuzzerContext()->GetChanceOfAddingAtomicLoad())) {
|
||||||
is_atomic_load = true;
|
is_atomic_load = true;
|
||||||
|
|
||||||
memory_scope_id = FindOrCreateConstant(
|
memory_scope_id = FindOrCreateConstant(
|
||||||
{uint32_t(spv::Scope::Invocation)},
|
{SpvScopeInvocation},
|
||||||
FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()),
|
FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()),
|
||||||
false);
|
false);
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ FuzzerPassAddLocalVariables::FuzzerPassAddLocalVariables(
|
|||||||
|
|
||||||
void FuzzerPassAddLocalVariables::Apply() {
|
void FuzzerPassAddLocalVariables::Apply() {
|
||||||
auto basic_type_ids_and_pointers =
|
auto basic_type_ids_and_pointers =
|
||||||
GetAvailableBasicTypesAndPointers(spv::StorageClass::Function);
|
GetAvailableBasicTypesAndPointers(SpvStorageClassFunction);
|
||||||
|
|
||||||
// These are the basic types that are available to this fuzzer pass.
|
// These are the basic types that are available to this fuzzer pass.
|
||||||
auto& basic_types = basic_type_ids_and_pointers.first;
|
auto& basic_types = basic_type_ids_and_pointers.first;
|
||||||
@ -64,7 +64,7 @@ void FuzzerPassAddLocalVariables::Apply() {
|
|||||||
// use it.
|
// use it.
|
||||||
pointer_type = GetFuzzerContext()->GetFreshId();
|
pointer_type = GetFuzzerContext()->GetFreshId();
|
||||||
ApplyTransformation(TransformationAddTypePointer(
|
ApplyTransformation(TransformationAddTypePointer(
|
||||||
pointer_type, spv::StorageClass::Function, basic_type));
|
pointer_type, SpvStorageClassFunction, basic_type));
|
||||||
available_pointers_to_basic_type.push_back(pointer_type);
|
available_pointers_to_basic_type.push_back(pointer_type);
|
||||||
} else {
|
} else {
|
||||||
// There is - grab one.
|
// There is - grab one.
|
||||||
|
@ -176,8 +176,8 @@ FuzzerPassAddOpPhiSynonyms::GetIdEquivalenceClasses() {
|
|||||||
// - OpFunction does not yield a value;
|
// - OpFunction does not yield a value;
|
||||||
// - OpUndef yields an undefined value at each use, so it should never be a
|
// - OpUndef yields an undefined value at each use, so it should never be a
|
||||||
// synonym of another id.
|
// synonym of another id.
|
||||||
if (pair.second->opcode() == spv::Op::OpFunction ||
|
if (pair.second->opcode() == SpvOpFunction ||
|
||||||
pair.second->opcode() == spv::Op::OpUndef) {
|
pair.second->opcode() == SpvOpUndef) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ void FuzzerPassAddParameters::Apply() {
|
|||||||
auto storage_class = fuzzerutil::GetStorageClassFromPointerType(
|
auto storage_class = fuzzerutil::GetStorageClassFromPointerType(
|
||||||
GetIRContext(), current_type_id);
|
GetIRContext(), current_type_id);
|
||||||
switch (storage_class) {
|
switch (storage_class) {
|
||||||
case spv::StorageClass::Function: {
|
case SpvStorageClassFunction: {
|
||||||
// In every caller find or create a local variable that has the
|
// In every caller find or create a local variable that has the
|
||||||
// selected type.
|
// selected type.
|
||||||
for (auto* instr :
|
for (auto* instr :
|
||||||
@ -91,8 +91,8 @@ void FuzzerPassAddParameters::Apply() {
|
|||||||
call_parameter_ids[instr->result_id()] = variable_id;
|
call_parameter_ids[instr->result_id()] = variable_id;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case spv::StorageClass::Private:
|
case SpvStorageClassPrivate:
|
||||||
case spv::StorageClass::Workgroup: {
|
case SpvStorageClassWorkgroup: {
|
||||||
// If there exists at least one caller, find or create a global
|
// If there exists at least one caller, find or create a global
|
||||||
// variable that has the selected type.
|
// variable that has the selected type.
|
||||||
std::vector<opt::Instruction*> callers =
|
std::vector<opt::Instruction*> callers =
|
||||||
|
@ -34,11 +34,10 @@ void FuzzerPassAddStores::Apply() {
|
|||||||
opt::BasicBlock::iterator inst_it,
|
opt::BasicBlock::iterator inst_it,
|
||||||
const protobufs::InstructionDescriptor& instruction_descriptor)
|
const protobufs::InstructionDescriptor& instruction_descriptor)
|
||||||
-> void {
|
-> void {
|
||||||
assert(
|
assert(inst_it->opcode() ==
|
||||||
inst_it->opcode() ==
|
instruction_descriptor.target_instruction_opcode() &&
|
||||||
spv::Op(instruction_descriptor.target_instruction_opcode()) &&
|
"The opcode of the instruction we might insert before must be "
|
||||||
"The opcode of the instruction we might insert before must be "
|
"the same as the opcode in the descriptor for the instruction");
|
||||||
"the same as the opcode in the descriptor for the instruction");
|
|
||||||
|
|
||||||
// Randomly decide whether to try inserting a store here.
|
// Randomly decide whether to try inserting a store here.
|
||||||
if (!GetFuzzerContext()->ChoosePercentage(
|
if (!GetFuzzerContext()->ChoosePercentage(
|
||||||
@ -48,12 +47,12 @@ void FuzzerPassAddStores::Apply() {
|
|||||||
|
|
||||||
// Check whether it is legitimate to insert a store before this
|
// Check whether it is legitimate to insert a store before this
|
||||||
// instruction.
|
// instruction.
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpStore,
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore,
|
||||||
inst_it)) {
|
inst_it)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAtomicStore,
|
||||||
spv::Op::OpAtomicStore, inst_it)) {
|
inst_it)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +67,7 @@ void FuzzerPassAddStores::Apply() {
|
|||||||
}
|
}
|
||||||
auto type_inst = context->get_def_use_mgr()->GetDef(
|
auto type_inst = context->get_def_use_mgr()->GetDef(
|
||||||
instruction->type_id());
|
instruction->type_id());
|
||||||
if (type_inst->opcode() != spv::Op::OpTypePointer) {
|
if (type_inst->opcode() != SpvOpTypePointer) {
|
||||||
// Not a pointer.
|
// Not a pointer.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -77,8 +76,8 @@ void FuzzerPassAddStores::Apply() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (instruction->opcode()) {
|
switch (instruction->opcode()) {
|
||||||
case spv::Op::OpConstantNull:
|
case SpvOpConstantNull:
|
||||||
case spv::Op::OpUndef:
|
case SpvOpUndef:
|
||||||
// Do not allow storing to a null or undefined pointer;
|
// Do not allow storing to a null or undefined pointer;
|
||||||
// this might be OK if the block is dead, but for now we
|
// this might be OK if the block is dead, but for now we
|
||||||
// conservatively avoid it.
|
// conservatively avoid it.
|
||||||
@ -127,24 +126,24 @@ void FuzzerPassAddStores::Apply() {
|
|||||||
uint32_t memory_semantics_id = 0;
|
uint32_t memory_semantics_id = 0;
|
||||||
|
|
||||||
auto storage_class =
|
auto storage_class =
|
||||||
static_cast<spv::StorageClass>(GetIRContext()
|
static_cast<SpvStorageClass>(GetIRContext()
|
||||||
->get_def_use_mgr()
|
->get_def_use_mgr()
|
||||||
->GetDef(pointer->type_id())
|
->GetDef(pointer->type_id())
|
||||||
->GetSingleWordInOperand(0));
|
->GetSingleWordInOperand(0));
|
||||||
|
|
||||||
switch (storage_class) {
|
switch (storage_class) {
|
||||||
case spv::StorageClass::StorageBuffer:
|
case SpvStorageClassStorageBuffer:
|
||||||
case spv::StorageClass::PhysicalStorageBuffer:
|
case SpvStorageClassPhysicalStorageBuffer:
|
||||||
case spv::StorageClass::Workgroup:
|
case SpvStorageClassWorkgroup:
|
||||||
case spv::StorageClass::CrossWorkgroup:
|
case SpvStorageClassCrossWorkgroup:
|
||||||
case spv::StorageClass::AtomicCounter:
|
case SpvStorageClassAtomicCounter:
|
||||||
case spv::StorageClass::Image:
|
case SpvStorageClassImage:
|
||||||
if (GetFuzzerContext()->ChoosePercentage(
|
if (GetFuzzerContext()->ChoosePercentage(
|
||||||
GetFuzzerContext()->GetChanceOfAddingAtomicStore())) {
|
GetFuzzerContext()->GetChanceOfAddingAtomicStore())) {
|
||||||
is_atomic_store = true;
|
is_atomic_store = true;
|
||||||
|
|
||||||
memory_scope_id = FindOrCreateConstant(
|
memory_scope_id = FindOrCreateConstant(
|
||||||
{uint32_t(spv::Scope::Invocation)},
|
{SpvScopeInvocation},
|
||||||
FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()),
|
FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()),
|
||||||
false);
|
false);
|
||||||
|
|
||||||
|
@ -44,8 +44,7 @@ void FuzzerPassAddSynonyms::Apply() {
|
|||||||
// Skip |inst_it| if we can't insert anything above it. OpIAdd is just
|
// Skip |inst_it| if we can't insert anything above it. OpIAdd is just
|
||||||
// a representative of some instruction that might be produced by the
|
// a representative of some instruction that might be produced by the
|
||||||
// transformation.
|
// transformation.
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpIAdd,
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpIAdd, inst_it)) {
|
||||||
inst_it)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,11 +35,10 @@ void FuzzerPassAddVectorShuffleInstructions::Apply() {
|
|||||||
opt::BasicBlock::iterator instruction_iterator,
|
opt::BasicBlock::iterator instruction_iterator,
|
||||||
const protobufs::InstructionDescriptor& instruction_descriptor)
|
const protobufs::InstructionDescriptor& instruction_descriptor)
|
||||||
-> void {
|
-> void {
|
||||||
assert(
|
assert(instruction_iterator->opcode() ==
|
||||||
instruction_iterator->opcode() ==
|
instruction_descriptor.target_instruction_opcode() &&
|
||||||
spv::Op(instruction_descriptor.target_instruction_opcode()) &&
|
"The opcode of the instruction we might insert before must be "
|
||||||
"The opcode of the instruction we might insert before must be "
|
"the same as the opcode in the descriptor for the instruction");
|
||||||
"the same as the opcode in the descriptor for the instruction");
|
|
||||||
|
|
||||||
// Randomly decide whether to try adding an OpVectorShuffle instruction.
|
// Randomly decide whether to try adding an OpVectorShuffle instruction.
|
||||||
if (!GetFuzzerContext()->ChoosePercentage(
|
if (!GetFuzzerContext()->ChoosePercentage(
|
||||||
@ -50,7 +49,7 @@ void FuzzerPassAddVectorShuffleInstructions::Apply() {
|
|||||||
// It must be valid to insert an OpVectorShuffle instruction
|
// It must be valid to insert an OpVectorShuffle instruction
|
||||||
// before |instruction_iterator|.
|
// before |instruction_iterator|.
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
||||||
spv::Op::OpVectorShuffle, instruction_iterator)) {
|
SpvOpVectorShuffle, instruction_iterator)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ void FuzzerPassAdjustBranchWeights::Apply() {
|
|||||||
// For all OpBranchConditional instructions,
|
// For all OpBranchConditional instructions,
|
||||||
// randomly applies the transformation.
|
// randomly applies the transformation.
|
||||||
GetIRContext()->module()->ForEachInst([this](opt::Instruction* instruction) {
|
GetIRContext()->module()->ForEachInst([this](opt::Instruction* instruction) {
|
||||||
if (instruction->opcode() == spv::Op::OpBranchConditional &&
|
if (instruction->opcode() == SpvOpBranchConditional &&
|
||||||
GetFuzzerContext()->ChoosePercentage(
|
GetFuzzerContext()->ChoosePercentage(
|
||||||
GetFuzzerContext()->GetChanceOfAdjustingBranchWeights())) {
|
GetFuzzerContext()->GetChanceOfAdjustingBranchWeights())) {
|
||||||
ApplyTransformation(TransformationAdjustBranchWeights(
|
ApplyTransformation(TransformationAdjustBranchWeights(
|
||||||
|
@ -40,21 +40,21 @@ void FuzzerPassAdjustFunctionControls::Apply() {
|
|||||||
// For the new mask, we first randomly select one of three basic masks:
|
// For the new mask, we first randomly select one of three basic masks:
|
||||||
// None, Inline or DontInline. These are always valid (and are mutually
|
// None, Inline or DontInline. These are always valid (and are mutually
|
||||||
// exclusive).
|
// exclusive).
|
||||||
std::vector<spv::FunctionControlMask> basic_function_control_masks = {
|
std::vector<uint32_t> basic_function_control_masks = {
|
||||||
spv::FunctionControlMask::MaskNone, spv::FunctionControlMask::Inline,
|
SpvFunctionControlMaskNone, SpvFunctionControlInlineMask,
|
||||||
spv::FunctionControlMask::DontInline};
|
SpvFunctionControlDontInlineMask};
|
||||||
uint32_t new_function_control_mask =
|
uint32_t new_function_control_mask =
|
||||||
uint32_t(basic_function_control_masks[GetFuzzerContext()->RandomIndex(
|
basic_function_control_masks[GetFuzzerContext()->RandomIndex(
|
||||||
basic_function_control_masks)]);
|
basic_function_control_masks)];
|
||||||
|
|
||||||
// We now consider the Pure and Const mask bits. If these are already
|
// We now consider the Pure and Const mask bits. If these are already
|
||||||
// set on the function then it's OK to keep them, but also interesting
|
// set on the function then it's OK to keep them, but also interesting
|
||||||
// to consider dropping them, so we decide randomly in each case.
|
// to consider dropping them, so we decide randomly in each case.
|
||||||
for (auto mask_bit :
|
for (auto mask_bit :
|
||||||
{spv::FunctionControlMask::Pure, spv::FunctionControlMask::Const}) {
|
{SpvFunctionControlPureMask, SpvFunctionControlConstMask}) {
|
||||||
if ((existing_function_control_mask & uint32_t(mask_bit)) &&
|
if ((existing_function_control_mask & mask_bit) &&
|
||||||
GetFuzzerContext()->ChooseEven()) {
|
GetFuzzerContext()->ChooseEven()) {
|
||||||
new_function_control_mask |= uint32_t(mask_bit);
|
new_function_control_mask |= mask_bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ void FuzzerPassAdjustLoopControls::Apply() {
|
|||||||
for (auto& block : function) {
|
for (auto& block : function) {
|
||||||
if (auto merge_inst = block.GetMergeInst()) {
|
if (auto merge_inst = block.GetMergeInst()) {
|
||||||
// Ignore the instruction if it is not a loop merge.
|
// Ignore the instruction if it is not a loop merge.
|
||||||
if (merge_inst->opcode() != spv::Op::OpLoopMerge) {
|
if (merge_inst->opcode() != SpvOpLoopMerge) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,10 +48,9 @@ void FuzzerPassAdjustLoopControls::Apply() {
|
|||||||
TransformationSetLoopControl::kLoopControlMaskInOperandIndex);
|
TransformationSetLoopControl::kLoopControlMaskInOperandIndex);
|
||||||
|
|
||||||
// First, set the new mask to one of None, Unroll or DontUnroll.
|
// First, set the new mask to one of None, Unroll or DontUnroll.
|
||||||
std::vector<uint32_t> basic_masks = {
|
std::vector<uint32_t> basic_masks = {SpvLoopControlMaskNone,
|
||||||
uint32_t(spv::LoopControlMask::MaskNone),
|
SpvLoopControlUnrollMask,
|
||||||
uint32_t(spv::LoopControlMask::Unroll),
|
SpvLoopControlDontUnrollMask};
|
||||||
uint32_t(spv::LoopControlMask::DontUnroll)};
|
|
||||||
uint32_t new_mask =
|
uint32_t new_mask =
|
||||||
basic_masks[GetFuzzerContext()->RandomIndex(basic_masks)];
|
basic_masks[GetFuzzerContext()->RandomIndex(basic_masks)];
|
||||||
|
|
||||||
@ -59,20 +58,19 @@ void FuzzerPassAdjustLoopControls::Apply() {
|
|||||||
// does, check which of these were present in the existing mask and
|
// does, check which of these were present in the existing mask and
|
||||||
// randomly decide whether to keep them. They are just hints, so
|
// randomly decide whether to keep them. They are just hints, so
|
||||||
// removing them should not change the semantics of the module.
|
// removing them should not change the semantics of the module.
|
||||||
for (auto mask_bit : {spv::LoopControlMask::DependencyInfinite,
|
for (auto mask_bit :
|
||||||
spv::LoopControlMask::DependencyLength,
|
{SpvLoopControlDependencyInfiniteMask,
|
||||||
spv::LoopControlMask::MinIterations,
|
SpvLoopControlDependencyLengthMask,
|
||||||
spv::LoopControlMask::MaxIterations,
|
SpvLoopControlMinIterationsMask, SpvLoopControlMaxIterationsMask,
|
||||||
spv::LoopControlMask::IterationMultiple}) {
|
SpvLoopControlIterationMultipleMask}) {
|
||||||
if ((existing_mask & uint32_t(mask_bit)) &&
|
if ((existing_mask & mask_bit) && GetFuzzerContext()->ChooseEven()) {
|
||||||
GetFuzzerContext()->ChooseEven()) {
|
|
||||||
// The mask bits we are considering are not available in all SPIR-V
|
// The mask bits we are considering are not available in all SPIR-V
|
||||||
// versions. However, we only include a mask bit if it was present
|
// versions. However, we only include a mask bit if it was present
|
||||||
// in the original loop control mask, and we work under the
|
// in the original loop control mask, and we work under the
|
||||||
// assumption that we are transforming a valid module, thus we don't
|
// assumption that we are transforming a valid module, thus we don't
|
||||||
// need to actually check whether the SPIR-V version being used
|
// need to actually check whether the SPIR-V version being used
|
||||||
// supports these loop control mask bits.
|
// supports these loop control mask bits.
|
||||||
new_mask |= uint32_t(mask_bit);
|
new_mask |= mask_bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,14 +81,14 @@ void FuzzerPassAdjustLoopControls::Apply() {
|
|||||||
|
|
||||||
// PeelCount and PartialCount are not compatible with DontUnroll, so
|
// PeelCount and PartialCount are not compatible with DontUnroll, so
|
||||||
// we check whether DontUnroll is set.
|
// we check whether DontUnroll is set.
|
||||||
if (!(new_mask & uint32_t(spv::LoopControlMask::DontUnroll))) {
|
if (!(new_mask & SpvLoopControlDontUnrollMask)) {
|
||||||
// If PeelCount is supported by this SPIR-V version, randomly choose
|
// If PeelCount is supported by this SPIR-V version, randomly choose
|
||||||
// whether to set it. If it was set in the original mask and is not
|
// whether to set it. If it was set in the original mask and is not
|
||||||
// selected for setting here, that amounts to dropping it.
|
// selected for setting here, that amounts to dropping it.
|
||||||
if (TransformationSetLoopControl::PeelCountIsSupported(
|
if (TransformationSetLoopControl::PeelCountIsSupported(
|
||||||
GetIRContext()) &&
|
GetIRContext()) &&
|
||||||
GetFuzzerContext()->ChooseEven()) {
|
GetFuzzerContext()->ChooseEven()) {
|
||||||
new_mask |= uint32_t(spv::LoopControlMask::PeelCount);
|
new_mask |= SpvLoopControlPeelCountMask;
|
||||||
// The peel count is chosen randomly - if PeelCount was already set
|
// The peel count is chosen randomly - if PeelCount was already set
|
||||||
// this will overwrite whatever peel count was previously used.
|
// this will overwrite whatever peel count was previously used.
|
||||||
peel_count = GetFuzzerContext()->GetRandomLoopControlPeelCount();
|
peel_count = GetFuzzerContext()->GetRandomLoopControlPeelCount();
|
||||||
@ -99,7 +97,7 @@ void FuzzerPassAdjustLoopControls::Apply() {
|
|||||||
if (TransformationSetLoopControl::PartialCountIsSupported(
|
if (TransformationSetLoopControl::PartialCountIsSupported(
|
||||||
GetIRContext()) &&
|
GetIRContext()) &&
|
||||||
GetFuzzerContext()->ChooseEven()) {
|
GetFuzzerContext()->ChooseEven()) {
|
||||||
new_mask |= uint32_t(spv::LoopControlMask::PartialCount);
|
new_mask |= SpvLoopControlPartialCountMask;
|
||||||
partial_count =
|
partial_count =
|
||||||
GetFuzzerContext()->GetRandomLoopControlPartialCount();
|
GetFuzzerContext()->GetRandomLoopControlPartialCount();
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,8 @@ void FuzzerPassAdjustMemoryOperandsMasks::Apply() {
|
|||||||
// From SPIR-V 1.4 onwards, OpCopyMemory and OpCopyMemorySized have a
|
// From SPIR-V 1.4 onwards, OpCopyMemory and OpCopyMemorySized have a
|
||||||
// second mask.
|
// second mask.
|
||||||
switch (inst_it->opcode()) {
|
switch (inst_it->opcode()) {
|
||||||
case spv::Op::OpCopyMemory:
|
case SpvOpCopyMemory:
|
||||||
case spv::Op::OpCopyMemorySized:
|
case SpvOpCopyMemorySized:
|
||||||
if (TransformationSetMemoryOperandsMask::
|
if (TransformationSetMemoryOperandsMask::
|
||||||
MultipleMemoryOperandMasksAreSupported(GetIRContext())) {
|
MultipleMemoryOperandMasksAreSupported(GetIRContext())) {
|
||||||
indices_of_available_masks_to_adjust.push_back(1);
|
indices_of_available_masks_to_adjust.push_back(1);
|
||||||
@ -75,26 +75,24 @@ void FuzzerPassAdjustMemoryOperandsMasks::Apply() {
|
|||||||
existing_mask_in_operand_index < inst_it->NumInOperands()
|
existing_mask_in_operand_index < inst_it->NumInOperands()
|
||||||
? inst_it->GetSingleWordInOperand(
|
? inst_it->GetSingleWordInOperand(
|
||||||
existing_mask_in_operand_index)
|
existing_mask_in_operand_index)
|
||||||
: static_cast<uint32_t>(spv::MemoryAccessMask::MaskNone);
|
: static_cast<uint32_t>(SpvMemoryAccessMaskNone);
|
||||||
|
|
||||||
// There are two things we can do to a mask:
|
// There are two things we can do to a mask:
|
||||||
// - add Volatile if not already present
|
// - add Volatile if not already present
|
||||||
// - toggle Nontemporal
|
// - toggle Nontemporal
|
||||||
// The following ensures that we do at least one of these
|
// The following ensures that we do at least one of these
|
||||||
bool add_volatile =
|
bool add_volatile = !(existing_mask & SpvMemoryAccessVolatileMask) &&
|
||||||
!(existing_mask & uint32_t(spv::MemoryAccessMask::Volatile)) &&
|
GetFuzzerContext()->ChooseEven();
|
||||||
GetFuzzerContext()->ChooseEven();
|
|
||||||
bool toggle_nontemporal =
|
bool toggle_nontemporal =
|
||||||
!add_volatile || GetFuzzerContext()->ChooseEven();
|
!add_volatile || GetFuzzerContext()->ChooseEven();
|
||||||
|
|
||||||
// These bitwise operations use '|' to add Volatile if desired, and
|
// These bitwise operations use '|' to add Volatile if desired, and
|
||||||
// '^' to toggle Nontemporal if desired.
|
// '^' to toggle Nontemporal if desired.
|
||||||
uint32_t new_mask =
|
uint32_t new_mask =
|
||||||
(existing_mask |
|
(existing_mask | (add_volatile ? SpvMemoryAccessVolatileMask
|
||||||
(add_volatile ? uint32_t(spv::MemoryAccessMask::Volatile)
|
: SpvMemoryAccessMaskNone)) ^
|
||||||
: uint32_t(spv::MemoryAccessMask::MaskNone))) ^
|
(toggle_nontemporal ? SpvMemoryAccessNontemporalMask
|
||||||
(toggle_nontemporal ? uint32_t(spv::MemoryAccessMask::Nontemporal)
|
: SpvMemoryAccessMaskNone);
|
||||||
: uint32_t(spv::MemoryAccessMask::MaskNone));
|
|
||||||
|
|
||||||
TransformationSetMemoryOperandsMask transformation(
|
TransformationSetMemoryOperandsMask transformation(
|
||||||
MakeInstructionDescriptor(block, inst_it), new_mask, mask_index);
|
MakeInstructionDescriptor(block, inst_it), new_mask, mask_index);
|
||||||
|
@ -34,7 +34,7 @@ void FuzzerPassAdjustSelectionControls::Apply() {
|
|||||||
for (auto& block : function) {
|
for (auto& block : function) {
|
||||||
if (auto merge_inst = block.GetMergeInst()) {
|
if (auto merge_inst = block.GetMergeInst()) {
|
||||||
// Ignore the instruction if it is not a selection merge.
|
// Ignore the instruction if it is not a selection merge.
|
||||||
if (merge_inst->opcode() != spv::Op::OpSelectionMerge) {
|
if (merge_inst->opcode() != SpvOpSelectionMerge) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,14 +48,13 @@ void FuzzerPassAdjustSelectionControls::Apply() {
|
|||||||
// The choices to change the selection control to are the set of valid
|
// The choices to change the selection control to are the set of valid
|
||||||
// controls, minus the current control.
|
// controls, minus the current control.
|
||||||
std::vector<uint32_t> choices;
|
std::vector<uint32_t> choices;
|
||||||
for (auto control : {spv::SelectionControlMask::MaskNone,
|
for (auto control :
|
||||||
spv::SelectionControlMask::Flatten,
|
{SpvSelectionControlMaskNone, SpvSelectionControlFlattenMask,
|
||||||
spv::SelectionControlMask::DontFlatten}) {
|
SpvSelectionControlDontFlattenMask}) {
|
||||||
if (control ==
|
if (control == merge_inst->GetSingleWordOperand(1)) {
|
||||||
spv::SelectionControlMask(merge_inst->GetSingleWordOperand(1))) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
choices.push_back(uint32_t(control));
|
choices.push_back(control);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the transformation and add it to the output transformation
|
// Apply the transformation and add it to the output transformation
|
||||||
|
@ -107,9 +107,9 @@ void FuzzerPassApplyIdSynonyms::Apply() {
|
|||||||
// which case we need to be able to add an extract instruction to get
|
// which case we need to be able to add an extract instruction to get
|
||||||
// that element out.
|
// that element out.
|
||||||
if (synonym_to_try->index_size() > 0 &&
|
if (synonym_to_try->index_size() > 0 &&
|
||||||
!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
|
||||||
spv::Op::OpCompositeExtract, use_inst) &&
|
use_inst) &&
|
||||||
use_inst->opcode() != spv::Op::OpPhi) {
|
use_inst->opcode() != SpvOpPhi) {
|
||||||
// We cannot insert an extract before this instruction, so this
|
// We cannot insert an extract before this instruction, so this
|
||||||
// synonym is no good.
|
// synonym is no good.
|
||||||
continue;
|
continue;
|
||||||
@ -132,7 +132,7 @@ void FuzzerPassApplyIdSynonyms::Apply() {
|
|||||||
id_with_which_to_replace_use = GetFuzzerContext()->GetFreshId();
|
id_with_which_to_replace_use = GetFuzzerContext()->GetFreshId();
|
||||||
opt::Instruction* instruction_to_insert_before = nullptr;
|
opt::Instruction* instruction_to_insert_before = nullptr;
|
||||||
|
|
||||||
if (use_inst->opcode() != spv::Op::OpPhi) {
|
if (use_inst->opcode() != SpvOpPhi) {
|
||||||
instruction_to_insert_before = use_inst;
|
instruction_to_insert_before = use_inst;
|
||||||
} else {
|
} else {
|
||||||
auto parent_block_id =
|
auto parent_block_id =
|
||||||
@ -182,7 +182,7 @@ void FuzzerPassApplyIdSynonyms::Apply() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FuzzerPassApplyIdSynonyms::DataDescriptorsHaveCompatibleTypes(
|
bool FuzzerPassApplyIdSynonyms::DataDescriptorsHaveCompatibleTypes(
|
||||||
spv::Op opcode, uint32_t use_in_operand_index,
|
SpvOp opcode, uint32_t use_in_operand_index,
|
||||||
const protobufs::DataDescriptor& dd1,
|
const protobufs::DataDescriptor& dd1,
|
||||||
const protobufs::DataDescriptor& dd2) {
|
const protobufs::DataDescriptor& dd2) {
|
||||||
auto base_object_type_id_1 =
|
auto base_object_type_id_1 =
|
||||||
|
@ -38,7 +38,7 @@ class FuzzerPassApplyIdSynonyms : public FuzzerPass {
|
|||||||
// with respect to the type. Concretely, returns true if |dd1| and |dd2| have
|
// with respect to the type. Concretely, returns true if |dd1| and |dd2| have
|
||||||
// the same type or both |dd1| and |dd2| are either a numerical or a vector
|
// the same type or both |dd1| and |dd2| are either a numerical or a vector
|
||||||
// type of integral components with possibly different signedness.
|
// type of integral components with possibly different signedness.
|
||||||
bool DataDescriptorsHaveCompatibleTypes(spv::Op opcode,
|
bool DataDescriptorsHaveCompatibleTypes(SpvOp opcode,
|
||||||
uint32_t use_in_operand_index,
|
uint32_t use_in_operand_index,
|
||||||
const protobufs::DataDescriptor& dd1,
|
const protobufs::DataDescriptor& dd1,
|
||||||
const protobufs::DataDescriptor& dd2);
|
const protobufs::DataDescriptor& dd2);
|
||||||
|
@ -81,7 +81,7 @@ void FuzzerPassConstructComposites::Apply() {
|
|||||||
// Check whether it is legitimate to insert a composite construction
|
// Check whether it is legitimate to insert a composite construction
|
||||||
// before the instruction.
|
// before the instruction.
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
||||||
spv::Op::OpCompositeConstruct, inst_it)) {
|
SpvOpCompositeConstruct, inst_it)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,19 +121,19 @@ void FuzzerPassConstructComposites::Apply() {
|
|||||||
auto composite_type_inst =
|
auto composite_type_inst =
|
||||||
GetIRContext()->get_def_use_mgr()->GetDef(chosen_composite_type);
|
GetIRContext()->get_def_use_mgr()->GetDef(chosen_composite_type);
|
||||||
switch (composite_type_inst->opcode()) {
|
switch (composite_type_inst->opcode()) {
|
||||||
case spv::Op::OpTypeArray:
|
case SpvOpTypeArray:
|
||||||
constructor_arguments = FindComponentsToConstructArray(
|
constructor_arguments = FindComponentsToConstructArray(
|
||||||
*composite_type_inst, type_id_to_available_instructions);
|
*composite_type_inst, type_id_to_available_instructions);
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpTypeMatrix:
|
case SpvOpTypeMatrix:
|
||||||
constructor_arguments = FindComponentsToConstructMatrix(
|
constructor_arguments = FindComponentsToConstructMatrix(
|
||||||
*composite_type_inst, type_id_to_available_instructions);
|
*composite_type_inst, type_id_to_available_instructions);
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpTypeStruct:
|
case SpvOpTypeStruct:
|
||||||
constructor_arguments = FindComponentsToConstructStruct(
|
constructor_arguments = FindComponentsToConstructStruct(
|
||||||
*composite_type_inst, type_id_to_available_instructions);
|
*composite_type_inst, type_id_to_available_instructions);
|
||||||
break;
|
break;
|
||||||
case spv::Op::OpTypeVector:
|
case SpvOpTypeVector:
|
||||||
constructor_arguments = FindComponentsToConstructVector(
|
constructor_arguments = FindComponentsToConstructVector(
|
||||||
*composite_type_inst, type_id_to_available_instructions);
|
*composite_type_inst, type_id_to_available_instructions);
|
||||||
break;
|
break;
|
||||||
@ -156,7 +156,7 @@ std::vector<uint32_t>
|
|||||||
FuzzerPassConstructComposites::FindComponentsToConstructArray(
|
FuzzerPassConstructComposites::FindComponentsToConstructArray(
|
||||||
const opt::Instruction& array_type_instruction,
|
const opt::Instruction& array_type_instruction,
|
||||||
const TypeIdToInstructions& type_id_to_available_instructions) {
|
const TypeIdToInstructions& type_id_to_available_instructions) {
|
||||||
assert(array_type_instruction.opcode() == spv::Op::OpTypeArray &&
|
assert(array_type_instruction.opcode() == SpvOpTypeArray &&
|
||||||
"Precondition: instruction must be an array type.");
|
"Precondition: instruction must be an array type.");
|
||||||
|
|
||||||
// Get the element type for the array.
|
// Get the element type for the array.
|
||||||
@ -191,7 +191,7 @@ std::vector<uint32_t>
|
|||||||
FuzzerPassConstructComposites::FindComponentsToConstructMatrix(
|
FuzzerPassConstructComposites::FindComponentsToConstructMatrix(
|
||||||
const opt::Instruction& matrix_type_instruction,
|
const opt::Instruction& matrix_type_instruction,
|
||||||
const TypeIdToInstructions& type_id_to_available_instructions) {
|
const TypeIdToInstructions& type_id_to_available_instructions) {
|
||||||
assert(matrix_type_instruction.opcode() == spv::Op::OpTypeMatrix &&
|
assert(matrix_type_instruction.opcode() == SpvOpTypeMatrix &&
|
||||||
"Precondition: instruction must be a matrix type.");
|
"Precondition: instruction must be a matrix type.");
|
||||||
|
|
||||||
// Get the element type for the matrix.
|
// Get the element type for the matrix.
|
||||||
@ -221,7 +221,7 @@ std::vector<uint32_t>
|
|||||||
FuzzerPassConstructComposites::FindComponentsToConstructStruct(
|
FuzzerPassConstructComposites::FindComponentsToConstructStruct(
|
||||||
const opt::Instruction& struct_type_instruction,
|
const opt::Instruction& struct_type_instruction,
|
||||||
const TypeIdToInstructions& type_id_to_available_instructions) {
|
const TypeIdToInstructions& type_id_to_available_instructions) {
|
||||||
assert(struct_type_instruction.opcode() == spv::Op::OpTypeStruct &&
|
assert(struct_type_instruction.opcode() == SpvOpTypeStruct &&
|
||||||
"Precondition: instruction must be a struct type.");
|
"Precondition: instruction must be a struct type.");
|
||||||
std::vector<uint32_t> result;
|
std::vector<uint32_t> result;
|
||||||
// Consider the type of each field of the struct.
|
// Consider the type of each field of the struct.
|
||||||
@ -251,7 +251,7 @@ std::vector<uint32_t>
|
|||||||
FuzzerPassConstructComposites::FindComponentsToConstructVector(
|
FuzzerPassConstructComposites::FindComponentsToConstructVector(
|
||||||
const opt::Instruction& vector_type_instruction,
|
const opt::Instruction& vector_type_instruction,
|
||||||
const TypeIdToInstructions& type_id_to_available_instructions) {
|
const TypeIdToInstructions& type_id_to_available_instructions) {
|
||||||
assert(vector_type_instruction.opcode() == spv::Op::OpTypeVector &&
|
assert(vector_type_instruction.opcode() == SpvOpTypeVector &&
|
||||||
"Precondition: instruction must be a vector type.");
|
"Precondition: instruction must be a vector type.");
|
||||||
|
|
||||||
// Get details of the type underlying the vector, and the width of the vector,
|
// Get details of the type underlying the vector, and the width of the vector,
|
||||||
|
@ -35,11 +35,10 @@ void FuzzerPassCopyObjects::Apply() {
|
|||||||
opt::BasicBlock::iterator inst_it,
|
opt::BasicBlock::iterator inst_it,
|
||||||
const protobufs::InstructionDescriptor& instruction_descriptor)
|
const protobufs::InstructionDescriptor& instruction_descriptor)
|
||||||
-> void {
|
-> void {
|
||||||
assert(
|
assert(inst_it->opcode() ==
|
||||||
inst_it->opcode() ==
|
instruction_descriptor.target_instruction_opcode() &&
|
||||||
spv::Op(instruction_descriptor.target_instruction_opcode()) &&
|
"The opcode of the instruction we might insert before must be "
|
||||||
"The opcode of the instruction we might insert before must be "
|
"the same as the opcode in the descriptor for the instruction");
|
||||||
"the same as the opcode in the descriptor for the instruction");
|
|
||||||
|
|
||||||
if (GetTransformationContext()->GetFactManager()->BlockIsDead(
|
if (GetTransformationContext()->GetFactManager()->BlockIsDead(
|
||||||
block->id())) {
|
block->id())) {
|
||||||
@ -49,7 +48,7 @@ void FuzzerPassCopyObjects::Apply() {
|
|||||||
|
|
||||||
// Check whether it is legitimate to insert a copy before this
|
// Check whether it is legitimate to insert a copy before this
|
||||||
// instruction.
|
// instruction.
|
||||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpCopyObject,
|
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyObject,
|
||||||
inst_it)) {
|
inst_it)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ void FuzzerPassDonateModules::DonateSingleModule(
|
|||||||
// module.
|
// module.
|
||||||
for (const auto& capability_inst : donor_ir_context->capabilities()) {
|
for (const auto& capability_inst : donor_ir_context->capabilities()) {
|
||||||
auto capability =
|
auto capability =
|
||||||
static_cast<spv::Capability>(capability_inst.GetSingleWordInOperand(0));
|
static_cast<SpvCapability>(capability_inst.GetSingleWordInOperand(0));
|
||||||
if (!GetIRContext()->get_feature_mgr()->HasCapability(capability)) {
|
if (!GetIRContext()->get_feature_mgr()->HasCapability(capability)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -122,27 +122,27 @@ void FuzzerPassDonateModules::DonateSingleModule(
|
|||||||
// kinds of decoration.
|
// kinds of decoration.
|
||||||
}
|
}
|
||||||
|
|
||||||
spv::StorageClass FuzzerPassDonateModules::AdaptStorageClass(
|
SpvStorageClass FuzzerPassDonateModules::AdaptStorageClass(
|
||||||
spv::StorageClass donor_storage_class) {
|
SpvStorageClass donor_storage_class) {
|
||||||
switch (donor_storage_class) {
|
switch (donor_storage_class) {
|
||||||
case spv::StorageClass::Function:
|
case SpvStorageClassFunction:
|
||||||
case spv::StorageClass::Private:
|
case SpvStorageClassPrivate:
|
||||||
case spv::StorageClass::Workgroup:
|
case SpvStorageClassWorkgroup:
|
||||||
// We leave these alone
|
// We leave these alone
|
||||||
return donor_storage_class;
|
return donor_storage_class;
|
||||||
case spv::StorageClass::Input:
|
case SpvStorageClassInput:
|
||||||
case spv::StorageClass::Output:
|
case SpvStorageClassOutput:
|
||||||
case spv::StorageClass::Uniform:
|
case SpvStorageClassUniform:
|
||||||
case spv::StorageClass::UniformConstant:
|
case SpvStorageClassUniformConstant:
|
||||||
case spv::StorageClass::PushConstant:
|
case SpvStorageClassPushConstant:
|
||||||
case spv::StorageClass::Image:
|
case SpvStorageClassImage:
|
||||||
case spv::StorageClass::StorageBuffer:
|
case SpvStorageClassStorageBuffer:
|
||||||
// We change these to Private
|
// We change these to Private
|
||||||
return spv::StorageClass::Private;
|
return SpvStorageClassPrivate;
|
||||||
default:
|
default:
|
||||||
// Handle other cases on demand.
|
// Handle other cases on demand.
|
||||||
assert(false && "Currently unsupported storage class.");
|
assert(false && "Currently unsupported storage class.");
|
||||||
return spv::StorageClass::Max;
|
return SpvStorageClassMax;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,14 +200,14 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
// that its component types will have been considered previously, and that
|
// that its component types will have been considered previously, and that
|
||||||
// |original_id_to_donated_id| will already contain an entry for them.
|
// |original_id_to_donated_id| will already contain an entry for them.
|
||||||
switch (type_or_value.opcode()) {
|
switch (type_or_value.opcode()) {
|
||||||
case spv::Op::OpTypeImage:
|
case SpvOpTypeImage:
|
||||||
case spv::Op::OpTypeSampledImage:
|
case SpvOpTypeSampledImage:
|
||||||
case spv::Op::OpTypeSampler:
|
case SpvOpTypeSampler:
|
||||||
// We do not donate types and variables that relate to images and
|
// We do not donate types and variables that relate to images and
|
||||||
// samplers, so we skip these types and subsequently skip anything that
|
// samplers, so we skip these types and subsequently skip anything that
|
||||||
// depends on them.
|
// depends on them.
|
||||||
return;
|
return;
|
||||||
case spv::Op::OpTypeVoid: {
|
case SpvOpTypeVoid: {
|
||||||
// Void has to exist already in order for us to have an entry point.
|
// Void has to exist already in order for us to have an entry point.
|
||||||
// Get the existing id of void.
|
// Get the existing id of void.
|
||||||
opt::analysis::Void void_type;
|
opt::analysis::Void void_type;
|
||||||
@ -216,7 +216,7 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
"The module being transformed will always have 'void' type "
|
"The module being transformed will always have 'void' type "
|
||||||
"declared.");
|
"declared.");
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpTypeBool: {
|
case SpvOpTypeBool: {
|
||||||
// Bool cannot be declared multiple times, so use its existing id if
|
// Bool cannot be declared multiple times, so use its existing id if
|
||||||
// present, or add a declaration of Bool with a fresh id if not.
|
// present, or add a declaration of Bool with a fresh id if not.
|
||||||
opt::analysis::Bool bool_type;
|
opt::analysis::Bool bool_type;
|
||||||
@ -228,7 +228,7 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
ApplyTransformation(TransformationAddTypeBoolean(new_result_id));
|
ApplyTransformation(TransformationAddTypeBoolean(new_result_id));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpTypeInt: {
|
case SpvOpTypeInt: {
|
||||||
// Int cannot be declared multiple times with the same width and
|
// Int cannot be declared multiple times with the same width and
|
||||||
// signedness, so check whether an existing identical Int type is
|
// signedness, so check whether an existing identical Int type is
|
||||||
// present and use its id if so. Otherwise add a declaration of the
|
// present and use its id if so. Otherwise add a declaration of the
|
||||||
@ -246,8 +246,8 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
TransformationAddTypeInt(new_result_id, width, is_signed));
|
TransformationAddTypeInt(new_result_id, width, is_signed));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpTypeFloat: {
|
case SpvOpTypeFloat: {
|
||||||
// Similar to spv::Op::OpTypeInt.
|
// Similar to SpvOpTypeInt.
|
||||||
const uint32_t width = type_or_value.GetSingleWordInOperand(0);
|
const uint32_t width = type_or_value.GetSingleWordInOperand(0);
|
||||||
opt::analysis::Float float_type(width);
|
opt::analysis::Float float_type(width);
|
||||||
auto float_type_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
|
auto float_type_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
|
||||||
@ -258,7 +258,7 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
ApplyTransformation(TransformationAddTypeFloat(new_result_id, width));
|
ApplyTransformation(TransformationAddTypeFloat(new_result_id, width));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpTypeVector: {
|
case SpvOpTypeVector: {
|
||||||
// It is not legal to have two Vector type declarations with identical
|
// It is not legal to have two Vector type declarations with identical
|
||||||
// element types and element counts, so check whether an existing
|
// element types and element counts, so check whether an existing
|
||||||
// identical Vector type is present and use its id if so. Otherwise add
|
// identical Vector type is present and use its id if so. Otherwise add
|
||||||
@ -282,8 +282,8 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
new_result_id, component_type_id, component_count));
|
new_result_id, component_type_id, component_count));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpTypeMatrix: {
|
case SpvOpTypeMatrix: {
|
||||||
// Similar to spv::Op::OpTypeVector.
|
// Similar to SpvOpTypeVector.
|
||||||
uint32_t column_type_id = original_id_to_donated_id->at(
|
uint32_t column_type_id = original_id_to_donated_id->at(
|
||||||
type_or_value.GetSingleWordInOperand(0));
|
type_or_value.GetSingleWordInOperand(0));
|
||||||
auto column_type =
|
auto column_type =
|
||||||
@ -302,7 +302,7 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpTypeArray: {
|
case SpvOpTypeArray: {
|
||||||
// It is OK to have multiple structurally identical array types, so
|
// It is OK to have multiple structurally identical array types, so
|
||||||
// we go ahead and add a remapped version of the type declared by the
|
// we go ahead and add a remapped version of the type declared by the
|
||||||
// donor.
|
// donor.
|
||||||
@ -318,7 +318,7 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
original_id_to_donated_id->at(
|
original_id_to_donated_id->at(
|
||||||
type_or_value.GetSingleWordInOperand(1))));
|
type_or_value.GetSingleWordInOperand(1))));
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpTypeRuntimeArray: {
|
case SpvOpTypeRuntimeArray: {
|
||||||
// A runtime array is allowed as the final member of an SSBO. During
|
// A runtime array is allowed as the final member of an SSBO. During
|
||||||
// donation we turn runtime arrays into fixed-size arrays. For dead
|
// donation we turn runtime arrays into fixed-size arrays. For dead
|
||||||
// code donations this is OK because the array is never indexed into at
|
// code donations this is OK because the array is never indexed into at
|
||||||
@ -341,8 +341,8 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
{GetFuzzerContext()->GetRandomSizeForNewArray()}, 32, false,
|
{GetFuzzerContext()->GetRandomSizeForNewArray()}, 32, false,
|
||||||
false)));
|
false)));
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpTypeStruct: {
|
case SpvOpTypeStruct: {
|
||||||
// Similar to spv::Op::OpTypeArray.
|
// Similar to SpvOpTypeArray.
|
||||||
std::vector<uint32_t> member_type_ids;
|
std::vector<uint32_t> member_type_ids;
|
||||||
for (uint32_t i = 0; i < type_or_value.NumInOperands(); i++) {
|
for (uint32_t i = 0; i < type_or_value.NumInOperands(); i++) {
|
||||||
auto component_type_id = type_or_value.GetSingleWordInOperand(i);
|
auto component_type_id = type_or_value.GetSingleWordInOperand(i);
|
||||||
@ -358,8 +358,8 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
ApplyTransformation(
|
ApplyTransformation(
|
||||||
TransformationAddTypeStruct(new_result_id, member_type_ids));
|
TransformationAddTypeStruct(new_result_id, member_type_ids));
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpTypePointer: {
|
case SpvOpTypePointer: {
|
||||||
// Similar to spv::Op::OpTypeArray.
|
// Similar to SpvOpTypeArray.
|
||||||
uint32_t pointee_type_id = type_or_value.GetSingleWordInOperand(1);
|
uint32_t pointee_type_id = type_or_value.GetSingleWordInOperand(1);
|
||||||
if (!original_id_to_donated_id->count(pointee_type_id)) {
|
if (!original_id_to_donated_id->count(pointee_type_id)) {
|
||||||
// We did not donate the pointee type for this pointer type, so we
|
// We did not donate the pointee type for this pointer type, so we
|
||||||
@ -369,11 +369,11 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
new_result_id = GetFuzzerContext()->GetFreshId();
|
new_result_id = GetFuzzerContext()->GetFreshId();
|
||||||
ApplyTransformation(TransformationAddTypePointer(
|
ApplyTransformation(TransformationAddTypePointer(
|
||||||
new_result_id,
|
new_result_id,
|
||||||
AdaptStorageClass(static_cast<spv::StorageClass>(
|
AdaptStorageClass(static_cast<SpvStorageClass>(
|
||||||
type_or_value.GetSingleWordInOperand(0))),
|
type_or_value.GetSingleWordInOperand(0))),
|
||||||
original_id_to_donated_id->at(pointee_type_id)));
|
original_id_to_donated_id->at(pointee_type_id)));
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpTypeFunction: {
|
case SpvOpTypeFunction: {
|
||||||
// It is not OK to have multiple function types that use identical ids
|
// It is not OK to have multiple function types that use identical ids
|
||||||
// for their return and parameter types. We thus go through all
|
// for their return and parameter types. We thus go through all
|
||||||
// existing function types to look for a match. We do not use the
|
// existing function types to look for a match. We do not use the
|
||||||
@ -425,11 +425,10 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
argument_type_ids));
|
argument_type_ids));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpSpecConstantOp: {
|
case SpvOpSpecConstantOp: {
|
||||||
new_result_id = GetFuzzerContext()->GetFreshId();
|
new_result_id = GetFuzzerContext()->GetFreshId();
|
||||||
auto type_id = original_id_to_donated_id->at(type_or_value.type_id());
|
auto type_id = original_id_to_donated_id->at(type_or_value.type_id());
|
||||||
auto opcode =
|
auto opcode = static_cast<SpvOp>(type_or_value.GetSingleWordInOperand(0));
|
||||||
static_cast<spv::Op>(type_or_value.GetSingleWordInOperand(0));
|
|
||||||
|
|
||||||
// Make sure we take into account |original_id_to_donated_id| when
|
// Make sure we take into account |original_id_to_donated_id| when
|
||||||
// computing operands for OpSpecConstantOp.
|
// computing operands for OpSpecConstantOp.
|
||||||
@ -448,20 +447,20 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
ApplyTransformation(TransformationAddSpecConstantOp(
|
ApplyTransformation(TransformationAddSpecConstantOp(
|
||||||
new_result_id, type_id, opcode, std::move(operands)));
|
new_result_id, type_id, opcode, std::move(operands)));
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpSpecConstantTrue:
|
case SpvOpSpecConstantTrue:
|
||||||
case spv::Op::OpSpecConstantFalse:
|
case SpvOpSpecConstantFalse:
|
||||||
case spv::Op::OpConstantTrue:
|
case SpvOpConstantTrue:
|
||||||
case spv::Op::OpConstantFalse: {
|
case SpvOpConstantFalse: {
|
||||||
// It is OK to have duplicate definitions of True and False, so add
|
// It is OK to have duplicate definitions of True and False, so add
|
||||||
// these to the module, using a remapped Bool type.
|
// these to the module, using a remapped Bool type.
|
||||||
new_result_id = GetFuzzerContext()->GetFreshId();
|
new_result_id = GetFuzzerContext()->GetFreshId();
|
||||||
auto value = type_or_value.opcode() == spv::Op::OpConstantTrue ||
|
auto value = type_or_value.opcode() == SpvOpConstantTrue ||
|
||||||
type_or_value.opcode() == spv::Op::OpSpecConstantTrue;
|
type_or_value.opcode() == SpvOpSpecConstantTrue;
|
||||||
ApplyTransformation(
|
ApplyTransformation(
|
||||||
TransformationAddConstantBoolean(new_result_id, value, false));
|
TransformationAddConstantBoolean(new_result_id, value, false));
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpSpecConstant:
|
case SpvOpSpecConstant:
|
||||||
case spv::Op::OpConstant: {
|
case SpvOpConstant: {
|
||||||
// It is OK to have duplicate constant definitions, so add this to the
|
// It is OK to have duplicate constant definitions, so add this to the
|
||||||
// module using a remapped result type.
|
// module using a remapped result type.
|
||||||
new_result_id = GetFuzzerContext()->GetFreshId();
|
new_result_id = GetFuzzerContext()->GetFreshId();
|
||||||
@ -473,8 +472,8 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
|
new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
|
||||||
data_words, false));
|
data_words, false));
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpSpecConstantComposite:
|
case SpvOpSpecConstantComposite:
|
||||||
case spv::Op::OpConstantComposite: {
|
case SpvOpConstantComposite: {
|
||||||
assert(original_id_to_donated_id->count(type_or_value.type_id()) &&
|
assert(original_id_to_donated_id->count(type_or_value.type_id()) &&
|
||||||
"Composite types for which it is possible to create a constant "
|
"Composite types for which it is possible to create a constant "
|
||||||
"should have been donated.");
|
"should have been donated.");
|
||||||
@ -496,7 +495,7 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
|
new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
|
||||||
constituent_ids, false));
|
constituent_ids, false));
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpConstantNull: {
|
case SpvOpConstantNull: {
|
||||||
if (!original_id_to_donated_id->count(type_or_value.type_id())) {
|
if (!original_id_to_donated_id->count(type_or_value.type_id())) {
|
||||||
// We did not donate the type associated with this null constant, so
|
// We did not donate the type associated with this null constant, so
|
||||||
// we cannot donate the null constant.
|
// we cannot donate the null constant.
|
||||||
@ -510,7 +509,7 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
new_result_id,
|
new_result_id,
|
||||||
original_id_to_donated_id->at(type_or_value.type_id())));
|
original_id_to_donated_id->at(type_or_value.type_id())));
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpVariable: {
|
case SpvOpVariable: {
|
||||||
if (!original_id_to_donated_id->count(type_or_value.type_id())) {
|
if (!original_id_to_donated_id->count(type_or_value.type_id())) {
|
||||||
// We did not donate the pointer type associated with this variable,
|
// We did not donate the pointer type associated with this variable,
|
||||||
// so we cannot donate the variable.
|
// so we cannot donate the variable.
|
||||||
@ -537,11 +536,11 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
uint32_t remapped_pointer_type =
|
uint32_t remapped_pointer_type =
|
||||||
original_id_to_donated_id->at(type_or_value.type_id());
|
original_id_to_donated_id->at(type_or_value.type_id());
|
||||||
uint32_t initializer_id;
|
uint32_t initializer_id;
|
||||||
spv::StorageClass storage_class =
|
SpvStorageClass storage_class =
|
||||||
static_cast<spv::StorageClass>(type_or_value.GetSingleWordInOperand(
|
static_cast<SpvStorageClass>(type_or_value.GetSingleWordInOperand(
|
||||||
0)) == spv::StorageClass::Workgroup
|
0)) == SpvStorageClassWorkgroup
|
||||||
? spv::StorageClass::Workgroup
|
? SpvStorageClassWorkgroup
|
||||||
: spv::StorageClass::Private;
|
: SpvStorageClassPrivate;
|
||||||
if (type_or_value.NumInOperands() == 1) {
|
if (type_or_value.NumInOperands() == 1) {
|
||||||
// The variable did not have an initializer. Initialize it to zero
|
// The variable did not have an initializer. Initialize it to zero
|
||||||
// if it has Private storage class (to limit problems associated with
|
// if it has Private storage class (to limit problems associated with
|
||||||
@ -552,7 +551,7 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
// could initialize Workgroup variables at the start of an entry
|
// could initialize Workgroup variables at the start of an entry
|
||||||
// point, and should do so if their uninitialized nature proves
|
// point, and should do so if their uninitialized nature proves
|
||||||
// problematic.
|
// problematic.
|
||||||
initializer_id = storage_class == spv::StorageClass::Workgroup
|
initializer_id = storage_class == SpvStorageClassWorkgroup
|
||||||
? 0
|
? 0
|
||||||
: FindOrCreateZeroConstant(
|
: FindOrCreateZeroConstant(
|
||||||
fuzzerutil::GetPointeeTypeIdFromPointerType(
|
fuzzerutil::GetPointeeTypeIdFromPointerType(
|
||||||
@ -567,7 +566,7 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
|
|||||||
TransformationAddGlobalVariable(new_result_id, remapped_pointer_type,
|
TransformationAddGlobalVariable(new_result_id, remapped_pointer_type,
|
||||||
storage_class, initializer_id, true));
|
storage_class, initializer_id, true));
|
||||||
} break;
|
} break;
|
||||||
case spv::Op::OpUndef: {
|
case SpvOpUndef: {
|
||||||
if (!original_id_to_donated_id->count(type_or_value.type_id())) {
|
if (!original_id_to_donated_id->count(type_or_value.type_id())) {
|
||||||
// We did not donate the type associated with this undef, so we cannot
|
// We did not donate the type associated with this undef, so we cannot
|
||||||
// donate the undef.
|
// donate the undef.
|
||||||
@ -639,7 +638,7 @@ void FuzzerPassDonateModules::HandleFunctions(
|
|||||||
[this, &donated_instructions, donor_ir_context,
|
[this, &donated_instructions, donor_ir_context,
|
||||||
&original_id_to_donated_id,
|
&original_id_to_donated_id,
|
||||||
&skipped_instructions](const opt::Instruction* instruction) {
|
&skipped_instructions](const opt::Instruction* instruction) {
|
||||||
if (instruction->opcode() == spv::Op::OpArrayLength) {
|
if (instruction->opcode() == SpvOpArrayLength) {
|
||||||
// We treat OpArrayLength specially.
|
// We treat OpArrayLength specially.
|
||||||
HandleOpArrayLength(*instruction, original_id_to_donated_id,
|
HandleOpArrayLength(*instruction, original_id_to_donated_id,
|
||||||
&donated_instructions);
|
&donated_instructions);
|
||||||
@ -683,70 +682,70 @@ bool FuzzerPassDonateModules::CanDonateInstruction(
|
|||||||
// Now consider instructions we specifically want to skip because we do not
|
// Now consider instructions we specifically want to skip because we do not
|
||||||
// yet support them.
|
// yet support them.
|
||||||
switch (instruction.opcode()) {
|
switch (instruction.opcode()) {
|
||||||
case spv::Op::OpAtomicLoad:
|
case SpvOpAtomicLoad:
|
||||||
case spv::Op::OpAtomicStore:
|
case SpvOpAtomicStore:
|
||||||
case spv::Op::OpAtomicExchange:
|
case SpvOpAtomicExchange:
|
||||||
case spv::Op::OpAtomicCompareExchange:
|
case SpvOpAtomicCompareExchange:
|
||||||
case spv::Op::OpAtomicCompareExchangeWeak:
|
case SpvOpAtomicCompareExchangeWeak:
|
||||||
case spv::Op::OpAtomicIIncrement:
|
case SpvOpAtomicIIncrement:
|
||||||
case spv::Op::OpAtomicIDecrement:
|
case SpvOpAtomicIDecrement:
|
||||||
case spv::Op::OpAtomicIAdd:
|
case SpvOpAtomicIAdd:
|
||||||
case spv::Op::OpAtomicISub:
|
case SpvOpAtomicISub:
|
||||||
case spv::Op::OpAtomicSMin:
|
case SpvOpAtomicSMin:
|
||||||
case spv::Op::OpAtomicUMin:
|
case SpvOpAtomicUMin:
|
||||||
case spv::Op::OpAtomicSMax:
|
case SpvOpAtomicSMax:
|
||||||
case spv::Op::OpAtomicUMax:
|
case SpvOpAtomicUMax:
|
||||||
case spv::Op::OpAtomicAnd:
|
case SpvOpAtomicAnd:
|
||||||
case spv::Op::OpAtomicOr:
|
case SpvOpAtomicOr:
|
||||||
case spv::Op::OpAtomicXor:
|
case SpvOpAtomicXor:
|
||||||
// We conservatively ignore all atomic instructions at present.
|
// We conservatively ignore all atomic instructions at present.
|
||||||
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3276): Consider
|
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3276): Consider
|
||||||
// being less conservative here.
|
// being less conservative here.
|
||||||
case spv::Op::OpImageSampleImplicitLod:
|
case SpvOpImageSampleImplicitLod:
|
||||||
case spv::Op::OpImageSampleExplicitLod:
|
case SpvOpImageSampleExplicitLod:
|
||||||
case spv::Op::OpImageSampleDrefImplicitLod:
|
case SpvOpImageSampleDrefImplicitLod:
|
||||||
case spv::Op::OpImageSampleDrefExplicitLod:
|
case SpvOpImageSampleDrefExplicitLod:
|
||||||
case spv::Op::OpImageSampleProjImplicitLod:
|
case SpvOpImageSampleProjImplicitLod:
|
||||||
case spv::Op::OpImageSampleProjExplicitLod:
|
case SpvOpImageSampleProjExplicitLod:
|
||||||
case spv::Op::OpImageSampleProjDrefImplicitLod:
|
case SpvOpImageSampleProjDrefImplicitLod:
|
||||||
case spv::Op::OpImageSampleProjDrefExplicitLod:
|
case SpvOpImageSampleProjDrefExplicitLod:
|
||||||
case spv::Op::OpImageFetch:
|
case SpvOpImageFetch:
|
||||||
case spv::Op::OpImageGather:
|
case SpvOpImageGather:
|
||||||
case spv::Op::OpImageDrefGather:
|
case SpvOpImageDrefGather:
|
||||||
case spv::Op::OpImageRead:
|
case SpvOpImageRead:
|
||||||
case spv::Op::OpImageWrite:
|
case SpvOpImageWrite:
|
||||||
case spv::Op::OpImageSparseSampleImplicitLod:
|
case SpvOpImageSparseSampleImplicitLod:
|
||||||
case spv::Op::OpImageSparseSampleExplicitLod:
|
case SpvOpImageSparseSampleExplicitLod:
|
||||||
case spv::Op::OpImageSparseSampleDrefImplicitLod:
|
case SpvOpImageSparseSampleDrefImplicitLod:
|
||||||
case spv::Op::OpImageSparseSampleDrefExplicitLod:
|
case SpvOpImageSparseSampleDrefExplicitLod:
|
||||||
case spv::Op::OpImageSparseSampleProjImplicitLod:
|
case SpvOpImageSparseSampleProjImplicitLod:
|
||||||
case spv::Op::OpImageSparseSampleProjExplicitLod:
|
case SpvOpImageSparseSampleProjExplicitLod:
|
||||||
case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
|
case SpvOpImageSparseSampleProjDrefImplicitLod:
|
||||||
case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
|
case SpvOpImageSparseSampleProjDrefExplicitLod:
|
||||||
case spv::Op::OpImageSparseFetch:
|
case SpvOpImageSparseFetch:
|
||||||
case spv::Op::OpImageSparseGather:
|
case SpvOpImageSparseGather:
|
||||||
case spv::Op::OpImageSparseDrefGather:
|
case SpvOpImageSparseDrefGather:
|
||||||
case spv::Op::OpImageSparseRead:
|
case SpvOpImageSparseRead:
|
||||||
case spv::Op::OpImageSampleFootprintNV:
|
case SpvOpImageSampleFootprintNV:
|
||||||
case spv::Op::OpImage:
|
case SpvOpImage:
|
||||||
case spv::Op::OpImageQueryFormat:
|
case SpvOpImageQueryFormat:
|
||||||
case spv::Op::OpImageQueryLevels:
|
case SpvOpImageQueryLevels:
|
||||||
case spv::Op::OpImageQueryLod:
|
case SpvOpImageQueryLod:
|
||||||
case spv::Op::OpImageQueryOrder:
|
case SpvOpImageQueryOrder:
|
||||||
case spv::Op::OpImageQuerySamples:
|
case SpvOpImageQuerySamples:
|
||||||
case spv::Op::OpImageQuerySize:
|
case SpvOpImageQuerySize:
|
||||||
case spv::Op::OpImageQuerySizeLod:
|
case SpvOpImageQuerySizeLod:
|
||||||
case spv::Op::OpSampledImage:
|
case SpvOpSampledImage:
|
||||||
// We ignore all instructions related to accessing images, since we do not
|
// We ignore all instructions related to accessing images, since we do not
|
||||||
// donate images.
|
// donate images.
|
||||||
return false;
|
return false;
|
||||||
case spv::Op::OpLoad:
|
case SpvOpLoad:
|
||||||
switch (donor_ir_context->get_def_use_mgr()
|
switch (donor_ir_context->get_def_use_mgr()
|
||||||
->GetDef(instruction.type_id())
|
->GetDef(instruction.type_id())
|
||||||
->opcode()) {
|
->opcode()) {
|
||||||
case spv::Op::OpTypeImage:
|
case SpvOpTypeImage:
|
||||||
case spv::Op::OpTypeSampledImage:
|
case SpvOpTypeSampledImage:
|
||||||
case spv::Op::OpTypeSampler:
|
case SpvOpTypeSampler:
|
||||||
// Again, we ignore instructions that relate to accessing images.
|
// Again, we ignore instructions that relate to accessing images.
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
@ -784,13 +783,13 @@ bool FuzzerPassDonateModules::CanDonateInstruction(
|
|||||||
bool FuzzerPassDonateModules::IsBasicType(
|
bool FuzzerPassDonateModules::IsBasicType(
|
||||||
const opt::Instruction& instruction) const {
|
const opt::Instruction& instruction) const {
|
||||||
switch (instruction.opcode()) {
|
switch (instruction.opcode()) {
|
||||||
case spv::Op::OpTypeArray:
|
case SpvOpTypeArray:
|
||||||
case spv::Op::OpTypeBool:
|
case SpvOpTypeBool:
|
||||||
case spv::Op::OpTypeFloat:
|
case SpvOpTypeFloat:
|
||||||
case spv::Op::OpTypeInt:
|
case SpvOpTypeInt:
|
||||||
case spv::Op::OpTypeMatrix:
|
case SpvOpTypeMatrix:
|
||||||
case spv::Op::OpTypeStruct:
|
case SpvOpTypeStruct:
|
||||||
case spv::Op::OpTypeVector:
|
case SpvOpTypeVector:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -801,7 +800,7 @@ void FuzzerPassDonateModules::HandleOpArrayLength(
|
|||||||
const opt::Instruction& instruction,
|
const opt::Instruction& instruction,
|
||||||
std::map<uint32_t, uint32_t>* original_id_to_donated_id,
|
std::map<uint32_t, uint32_t>* original_id_to_donated_id,
|
||||||
std::vector<protobufs::Instruction>* donated_instructions) const {
|
std::vector<protobufs::Instruction>* donated_instructions) const {
|
||||||
assert(instruction.opcode() == spv::Op::OpArrayLength &&
|
assert(instruction.opcode() == SpvOpArrayLength &&
|
||||||
"Precondition: instruction must be OpArrayLength.");
|
"Precondition: instruction must be OpArrayLength.");
|
||||||
uint32_t donated_variable_id =
|
uint32_t donated_variable_id =
|
||||||
original_id_to_donated_id->at(instruction.GetSingleWordInOperand(0));
|
original_id_to_donated_id->at(instruction.GetSingleWordInOperand(0));
|
||||||
@ -810,12 +809,12 @@ void FuzzerPassDonateModules::HandleOpArrayLength(
|
|||||||
auto pointer_to_struct_instruction =
|
auto pointer_to_struct_instruction =
|
||||||
GetIRContext()->get_def_use_mgr()->GetDef(
|
GetIRContext()->get_def_use_mgr()->GetDef(
|
||||||
donated_variable_instruction->type_id());
|
donated_variable_instruction->type_id());
|
||||||
assert(pointer_to_struct_instruction->opcode() == spv::Op::OpTypePointer &&
|
assert(pointer_to_struct_instruction->opcode() == SpvOpTypePointer &&
|
||||||
"Type of variable must be pointer.");
|
"Type of variable must be pointer.");
|
||||||
auto donated_struct_type_instruction =
|
auto donated_struct_type_instruction =
|
||||||
GetIRContext()->get_def_use_mgr()->GetDef(
|
GetIRContext()->get_def_use_mgr()->GetDef(
|
||||||
pointer_to_struct_instruction->GetSingleWordInOperand(1));
|
pointer_to_struct_instruction->GetSingleWordInOperand(1));
|
||||||
assert(donated_struct_type_instruction->opcode() == spv::Op::OpTypeStruct &&
|
assert(donated_struct_type_instruction->opcode() == SpvOpTypeStruct &&
|
||||||
"Pointee type of pointer used by OpArrayLength must be struct.");
|
"Pointee type of pointer used by OpArrayLength must be struct.");
|
||||||
assert(donated_struct_type_instruction->NumInOperands() ==
|
assert(donated_struct_type_instruction->NumInOperands() ==
|
||||||
instruction.GetSingleWordInOperand(1) + 1 &&
|
instruction.GetSingleWordInOperand(1) + 1 &&
|
||||||
@ -826,7 +825,7 @@ void FuzzerPassDonateModules::HandleOpArrayLength(
|
|||||||
donated_struct_type_instruction->NumInOperands() - 1);
|
donated_struct_type_instruction->NumInOperands() - 1);
|
||||||
auto fixed_size_array_type_instruction =
|
auto fixed_size_array_type_instruction =
|
||||||
GetIRContext()->get_def_use_mgr()->GetDef(fixed_size_array_type_id);
|
GetIRContext()->get_def_use_mgr()->GetDef(fixed_size_array_type_id);
|
||||||
assert(fixed_size_array_type_instruction->opcode() == spv::Op::OpTypeArray &&
|
assert(fixed_size_array_type_instruction->opcode() == SpvOpTypeArray &&
|
||||||
"The donated array type must be fixed-size.");
|
"The donated array type must be fixed-size.");
|
||||||
auto array_size_id =
|
auto array_size_id =
|
||||||
fixed_size_array_type_instruction->GetSingleWordInOperand(1);
|
fixed_size_array_type_instruction->GetSingleWordInOperand(1);
|
||||||
@ -838,8 +837,7 @@ void FuzzerPassDonateModules::HandleOpArrayLength(
|
|||||||
}
|
}
|
||||||
|
|
||||||
donated_instructions->push_back(MakeInstructionMessage(
|
donated_instructions->push_back(MakeInstructionMessage(
|
||||||
spv::Op::OpCopyObject,
|
SpvOpCopyObject, original_id_to_donated_id->at(instruction.type_id()),
|
||||||
original_id_to_donated_id->at(instruction.type_id()),
|
|
||||||
original_id_to_donated_id->at(instruction.result_id()),
|
original_id_to_donated_id->at(instruction.result_id()),
|
||||||
opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {array_size_id}}})));
|
opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {array_size_id}}})));
|
||||||
}
|
}
|
||||||
@ -894,7 +892,7 @@ void FuzzerPassDonateModules::HandleDifficultInstruction(
|
|||||||
// more interesting value later.
|
// more interesting value later.
|
||||||
auto zero_constant = FindOrCreateZeroConstant(remapped_type_id, true);
|
auto zero_constant = FindOrCreateZeroConstant(remapped_type_id, true);
|
||||||
donated_instructions->push_back(MakeInstructionMessage(
|
donated_instructions->push_back(MakeInstructionMessage(
|
||||||
spv::Op::OpCopyObject, remapped_type_id,
|
SpvOpCopyObject, remapped_type_id,
|
||||||
original_id_to_donated_id->at(instruction.result_id()),
|
original_id_to_donated_id->at(instruction.result_id()),
|
||||||
opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {zero_constant}}})));
|
opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {zero_constant}}})));
|
||||||
}
|
}
|
||||||
@ -928,8 +926,8 @@ void FuzzerPassDonateModules::PrepareInstructionForDonation(
|
|||||||
(void)(donor_ir_context);
|
(void)(donor_ir_context);
|
||||||
assert((donor_ir_context->get_def_use_mgr()
|
assert((donor_ir_context->get_def_use_mgr()
|
||||||
->GetDef(operand_id)
|
->GetDef(operand_id)
|
||||||
->opcode() == spv::Op::OpLabel ||
|
->opcode() == SpvOpLabel ||
|
||||||
instruction.opcode() == spv::Op::OpPhi) &&
|
instruction.opcode() == SpvOpPhi) &&
|
||||||
"Unsupported forward reference.");
|
"Unsupported forward reference.");
|
||||||
original_id_to_donated_id->insert(
|
original_id_to_donated_id->insert(
|
||||||
{operand_id, GetFuzzerContext()->GetFreshId()});
|
{operand_id, GetFuzzerContext()->GetFreshId()});
|
||||||
@ -944,7 +942,7 @@ void FuzzerPassDonateModules::PrepareInstructionForDonation(
|
|||||||
input_operands.push_back({in_operand.type, operand_data});
|
input_operands.push_back({in_operand.type, operand_data});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instruction.opcode() == spv::Op::OpVariable &&
|
if (instruction.opcode() == SpvOpVariable &&
|
||||||
instruction.NumInOperands() == 1) {
|
instruction.NumInOperands() == 1) {
|
||||||
// This is an uninitialized local variable. Initialize it to zero.
|
// This is an uninitialized local variable. Initialize it to zero.
|
||||||
input_operands.push_back(
|
input_operands.push_back(
|
||||||
@ -1019,7 +1017,7 @@ bool FuzzerPassDonateModules::CreateLoopLimiterInfo(
|
|||||||
|
|
||||||
// Adjust OpPhi instructions in the |merge_block|.
|
// Adjust OpPhi instructions in the |merge_block|.
|
||||||
for (const auto& inst : *merge_block) {
|
for (const auto& inst : *merge_block) {
|
||||||
if (inst.opcode() != spv::Op::OpPhi) {
|
if (inst.opcode() != SpvOpPhi) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1072,8 +1070,7 @@ bool FuzzerPassDonateModules::MaybeAddLivesafeFunction(
|
|||||||
// live-safe. Add them if not already present.
|
// live-safe. Add them if not already present.
|
||||||
FindOrCreateBoolType(); // Needed for comparisons
|
FindOrCreateBoolType(); // Needed for comparisons
|
||||||
FindOrCreatePointerToIntegerType(
|
FindOrCreatePointerToIntegerType(
|
||||||
32, false,
|
32, false, SpvStorageClassFunction); // Needed for adding loop limiters
|
||||||
spv::StorageClass::Function); // Needed for adding loop limiters
|
|
||||||
FindOrCreateIntegerConstant({0}, 32, false,
|
FindOrCreateIntegerConstant({0}, 32, false,
|
||||||
false); // Needed for initializing loop limiters
|
false); // Needed for initializing loop limiters
|
||||||
FindOrCreateIntegerConstant({1}, 32, false,
|
FindOrCreateIntegerConstant({1}, 32, false,
|
||||||
@ -1110,8 +1107,8 @@ bool FuzzerPassDonateModules::MaybeAddLivesafeFunction(
|
|||||||
for (auto& block : function_to_donate) {
|
for (auto& block : function_to_donate) {
|
||||||
for (auto& inst : block) {
|
for (auto& inst : block) {
|
||||||
switch (inst.opcode()) {
|
switch (inst.opcode()) {
|
||||||
case spv::Op::OpAccessChain:
|
case SpvOpAccessChain:
|
||||||
case spv::Op::OpInBoundsAccessChain: {
|
case SpvOpInBoundsAccessChain: {
|
||||||
protobufs::AccessChainClampingInfo clamping_info;
|
protobufs::AccessChainClampingInfo clamping_info;
|
||||||
clamping_info.set_access_chain_id(
|
clamping_info.set_access_chain_id(
|
||||||
original_id_to_donated_id.at(inst.result_id()));
|
original_id_to_donated_id.at(inst.result_id()));
|
||||||
@ -1121,8 +1118,7 @@ bool FuzzerPassDonateModules::MaybeAddLivesafeFunction(
|
|||||||
assert(base_object && "The base object must exist.");
|
assert(base_object && "The base object must exist.");
|
||||||
auto pointer_type = donor_ir_context->get_def_use_mgr()->GetDef(
|
auto pointer_type = donor_ir_context->get_def_use_mgr()->GetDef(
|
||||||
base_object->type_id());
|
base_object->type_id());
|
||||||
assert(pointer_type &&
|
assert(pointer_type && pointer_type->opcode() == SpvOpTypePointer &&
|
||||||
pointer_type->opcode() == spv::Op::OpTypePointer &&
|
|
||||||
"The base object must have pointer type.");
|
"The base object must have pointer type.");
|
||||||
|
|
||||||
auto should_be_composite_type =
|
auto should_be_composite_type =
|
||||||
@ -1142,8 +1138,7 @@ bool FuzzerPassDonateModules::MaybeAddLivesafeFunction(
|
|||||||
|
|
||||||
// Get the bound for the component being indexed into.
|
// Get the bound for the component being indexed into.
|
||||||
uint32_t bound;
|
uint32_t bound;
|
||||||
if (should_be_composite_type->opcode() ==
|
if (should_be_composite_type->opcode() == SpvOpTypeRuntimeArray) {
|
||||||
spv::Op::OpTypeRuntimeArray) {
|
|
||||||
// The donor is indexing into a runtime array. We do not
|
// The donor is indexing into a runtime array. We do not
|
||||||
// donate runtime arrays. Instead, we donate a corresponding
|
// donate runtime arrays. Instead, we donate a corresponding
|
||||||
// fixed-size array for every runtime array. We should thus
|
// fixed-size array for every runtime array. We should thus
|
||||||
@ -1153,7 +1148,7 @@ bool FuzzerPassDonateModules::MaybeAddLivesafeFunction(
|
|||||||
GetIRContext()->get_def_use_mgr()->GetDef(
|
GetIRContext()->get_def_use_mgr()->GetDef(
|
||||||
original_id_to_donated_id.at(
|
original_id_to_donated_id.at(
|
||||||
should_be_composite_type->result_id()));
|
should_be_composite_type->result_id()));
|
||||||
assert(fixed_size_array_type->opcode() == spv::Op::OpTypeArray &&
|
assert(fixed_size_array_type->opcode() == SpvOpTypeArray &&
|
||||||
"A runtime array type in the donor should have been "
|
"A runtime array type in the donor should have been "
|
||||||
"replaced by a fixed-sized array in the recipient.");
|
"replaced by a fixed-sized array in the recipient.");
|
||||||
// The size of this fixed-size array is a suitable bound.
|
// The size of this fixed-size array is a suitable bound.
|
||||||
@ -1168,12 +1163,12 @@ bool FuzzerPassDonateModules::MaybeAddLivesafeFunction(
|
|||||||
donor_ir_context->get_def_use_mgr()->GetDef(index_id);
|
donor_ir_context->get_def_use_mgr()->GetDef(index_id);
|
||||||
auto index_type_inst = donor_ir_context->get_def_use_mgr()->GetDef(
|
auto index_type_inst = donor_ir_context->get_def_use_mgr()->GetDef(
|
||||||
index_inst->type_id());
|
index_inst->type_id());
|
||||||
assert(index_type_inst->opcode() == spv::Op::OpTypeInt);
|
assert(index_type_inst->opcode() == SpvOpTypeInt);
|
||||||
opt::analysis::Integer* index_int_type =
|
opt::analysis::Integer* index_int_type =
|
||||||
donor_ir_context->get_type_mgr()
|
donor_ir_context->get_type_mgr()
|
||||||
->GetType(index_type_inst->result_id())
|
->GetType(index_type_inst->result_id())
|
||||||
->AsInteger();
|
->AsInteger();
|
||||||
if (index_inst->opcode() != spv::Op::OpConstant) {
|
if (index_inst->opcode() != SpvOpConstant) {
|
||||||
// We will have to clamp this index, so we need a constant
|
// We will have to clamp this index, so we need a constant
|
||||||
// whose value is one less than the bound, to compare
|
// whose value is one less than the bound, to compare
|
||||||
// against and to use as the clamped value.
|
// against and to use as the clamped value.
|
||||||
@ -1199,7 +1194,7 @@ bool FuzzerPassDonateModules::MaybeAddLivesafeFunction(
|
|||||||
uint32_t kill_unreachable_return_value_id = 0;
|
uint32_t kill_unreachable_return_value_id = 0;
|
||||||
auto function_return_type_inst =
|
auto function_return_type_inst =
|
||||||
donor_ir_context->get_def_use_mgr()->GetDef(function_to_donate.type_id());
|
donor_ir_context->get_def_use_mgr()->GetDef(function_to_donate.type_id());
|
||||||
if (function_return_type_inst->opcode() != spv::Op::OpTypeVoid &&
|
if (function_return_type_inst->opcode() != SpvOpTypeVoid &&
|
||||||
fuzzerutil::FunctionContainsOpKillOrUnreachable(function_to_donate)) {
|
fuzzerutil::FunctionContainsOpKillOrUnreachable(function_to_donate)) {
|
||||||
kill_unreachable_return_value_id = FindOrCreateZeroConstant(
|
kill_unreachable_return_value_id = FindOrCreateZeroConstant(
|
||||||
original_id_to_donated_id.at(function_return_type_inst->result_id()),
|
original_id_to_donated_id.at(function_return_type_inst->result_id()),
|
||||||
|
@ -45,8 +45,7 @@ class FuzzerPassDonateModules : public FuzzerPass {
|
|||||||
private:
|
private:
|
||||||
// Adapts a storage class coming from a donor module so that it will work
|
// Adapts a storage class coming from a donor module so that it will work
|
||||||
// in a recipient module, e.g. by changing Uniform to Private.
|
// in a recipient module, e.g. by changing Uniform to Private.
|
||||||
static spv::StorageClass AdaptStorageClass(
|
static SpvStorageClass AdaptStorageClass(SpvStorageClass donor_storage_class);
|
||||||
spv::StorageClass donor_storage_class);
|
|
||||||
|
|
||||||
// Identifies all external instruction set imports in |donor_ir_context| and
|
// Identifies all external instruction set imports in |donor_ir_context| and
|
||||||
// populates |original_id_to_donated_id| with a mapping from the donor's id
|
// populates |original_id_to_donated_id| with a mapping from the donor's id
|
||||||
|
@ -40,8 +40,8 @@ void FuzzerPassExpandVectorReductions::Apply() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// |instruction| must be OpAny or OpAll.
|
// |instruction| must be OpAny or OpAll.
|
||||||
if (instruction.opcode() != spv::Op::OpAny &&
|
if (instruction.opcode() != SpvOpAny &&
|
||||||
instruction.opcode() != spv::Op::OpAll) {
|
instruction.opcode() != SpvOpAll) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,8 +48,8 @@ void FuzzerPassFlattenConditionalBranches::Apply() {
|
|||||||
// Only consider this block if it is the header of a conditional, with a
|
// Only consider this block if it is the header of a conditional, with a
|
||||||
// non-irrelevant condition.
|
// non-irrelevant condition.
|
||||||
if (block.GetMergeInst() &&
|
if (block.GetMergeInst() &&
|
||||||
block.GetMergeInst()->opcode() == spv::Op::OpSelectionMerge &&
|
block.GetMergeInst()->opcode() == SpvOpSelectionMerge &&
|
||||||
block.terminator()->opcode() == spv::Op::OpBranchConditional &&
|
block.terminator()->opcode() == SpvOpBranchConditional &&
|
||||||
!GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
|
!GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
|
||||||
block.terminator()->GetSingleWordInOperand(0))) {
|
block.terminator()->GetSingleWordInOperand(0))) {
|
||||||
selection_headers.emplace_back(&block);
|
selection_headers.emplace_back(&block);
|
||||||
@ -94,11 +94,11 @@ void FuzzerPassFlattenConditionalBranches::Apply() {
|
|||||||
->get_def_use_mgr()
|
->get_def_use_mgr()
|
||||||
->GetDef(phi_instruction->type_id())
|
->GetDef(phi_instruction->type_id())
|
||||||
->opcode()) {
|
->opcode()) {
|
||||||
case spv::Op::OpTypeBool:
|
case SpvOpTypeBool:
|
||||||
case spv::Op::OpTypeInt:
|
case SpvOpTypeInt:
|
||||||
case spv::Op::OpTypeFloat:
|
case SpvOpTypeFloat:
|
||||||
case spv::Op::OpTypePointer:
|
case SpvOpTypePointer:
|
||||||
case spv::Op::OpTypeVector:
|
case SpvOpTypeVector:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -143,7 +143,7 @@ void FuzzerPassFlattenConditionalBranches::Apply() {
|
|||||||
GetIRContext()->get_def_use_mgr()->GetDef(
|
GetIRContext()->get_def_use_mgr()->GetDef(
|
||||||
phi_instruction->type_id());
|
phi_instruction->type_id());
|
||||||
switch (type_instruction->opcode()) {
|
switch (type_instruction->opcode()) {
|
||||||
case spv::Op::OpTypeVector: {
|
case SpvOpTypeVector: {
|
||||||
uint32_t dimension =
|
uint32_t dimension =
|
||||||
type_instruction->GetSingleWordInOperand(1);
|
type_instruction->GetSingleWordInOperand(1);
|
||||||
switch (dimension) {
|
switch (dimension) {
|
||||||
|
@ -64,7 +64,7 @@ void FuzzerPassInlineFunctions::Apply() {
|
|||||||
auto* function_call_block =
|
auto* function_call_block =
|
||||||
GetIRContext()->get_instr_block(function_call_instruction);
|
GetIRContext()->get_instr_block(function_call_instruction);
|
||||||
if ((function_call_instruction != &*--function_call_block->tail() ||
|
if ((function_call_instruction != &*--function_call_block->tail() ||
|
||||||
function_call_block->terminator()->opcode() != spv::Op::OpBranch) &&
|
function_call_block->terminator()->opcode() != SpvOpBranch) &&
|
||||||
!MaybeApplyTransformation(TransformationSplitBlock(
|
!MaybeApplyTransformation(TransformationSplitBlock(
|
||||||
MakeInstructionDescriptor(GetIRContext(),
|
MakeInstructionDescriptor(GetIRContext(),
|
||||||
function_call_instruction->NextNode()),
|
function_call_instruction->NextNode()),
|
||||||
|
@ -47,20 +47,18 @@ void FuzzerPassMakeVectorOperationsDynamic::Apply() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure |instruction| has only one indexing operand.
|
// Make sure |instruction| has only one indexing operand.
|
||||||
assert(
|
assert(instruction.NumInOperands() ==
|
||||||
instruction.NumInOperands() ==
|
(instruction.opcode() == SpvOpCompositeExtract ? 2 : 3) &&
|
||||||
(instruction.opcode() == spv::Op::OpCompositeExtract ? 2 : 3) &&
|
"FuzzerPassMakeVectorOperationsDynamic: the composite "
|
||||||
"FuzzerPassMakeVectorOperationsDynamic: the composite "
|
"instruction must have "
|
||||||
"instruction must have "
|
"only one indexing operand.");
|
||||||
"only one indexing operand.");
|
|
||||||
|
|
||||||
// Applies the make vector operation dynamic transformation.
|
// Applies the make vector operation dynamic transformation.
|
||||||
ApplyTransformation(TransformationMakeVectorOperationDynamic(
|
ApplyTransformation(TransformationMakeVectorOperationDynamic(
|
||||||
instruction.result_id(),
|
instruction.result_id(),
|
||||||
FindOrCreateIntegerConstant(
|
FindOrCreateIntegerConstant(
|
||||||
{instruction.GetSingleWordInOperand(
|
{instruction.GetSingleWordInOperand(
|
||||||
instruction.opcode() == spv::Op::OpCompositeExtract ? 1
|
instruction.opcode() == SpvOpCompositeExtract ? 1 : 2)},
|
||||||
: 2)},
|
|
||||||
32, GetFuzzerContext()->ChooseEven(), false)));
|
32, GetFuzzerContext()->ChooseEven(), false)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user