Switch SPIRV-Tools to use spirv.hpp11 internally (#4981)

Fixes #4960

* Switches to using enum classes with an underlying type to avoid
  undefined behaviour
This commit is contained in:
alan-baker 2022-11-04 17:27:10 -04:00 committed by GitHub
parent c8e1588cfa
commit d35a78db57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
523 changed files with 16054 additions and 14867 deletions

View File

@ -220,7 +220,8 @@ $(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
@ -294,7 +295,8 @@ $(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.

View File

@ -137,7 +137,7 @@ cc_library(
copts = COMMON_COPTS, copts = COMMON_COPTS,
includes = ["source"], includes = ["source"],
deps = [ deps = [
"@spirv_headers//:spirv_c_headers", "@spirv_headers//:spirv_cpp11_headers",
], ],
) )
@ -162,7 +162,7 @@ cc_library(
deps = [ deps = [
":generated_headers", ":generated_headers",
":spirv_tools_headers", ":spirv_tools_headers",
"@spirv_headers//:spirv_c_headers", "@spirv_headers//:spirv_cpp11_headers",
"@spirv_headers//:spirv_common_headers", "@spirv_headers//:spirv_common_headers",
], ],
) )

View File

@ -69,6 +69,8 @@ template("spvtools_core_tables") {
rebase_path(cldebuginfo100_insts_file, root_build_dir), rebase_path(cldebuginfo100_insts_file, root_build_dir),
"--operand-kinds-output", "--operand-kinds-output",
rebase_path(operand_kinds_file, root_build_dir), rebase_path(operand_kinds_file, root_build_dir),
"--output-language",
"c++"
] ]
} }
} }
@ -101,6 +103,8 @@ template("spvtools_core_enums") {
rebase_path(extension_enum_file, root_build_dir), rebase_path(extension_enum_file, root_build_dir),
"--enum-string-mapping-output", "--enum-string-mapping-output",
rebase_path(extension_map_file, root_build_dir), rebase_path(extension_map_file, root_build_dir),
"--output-language",
"c++"
] ]
inputs = [ inputs = [
core_json_file, core_json_file,
@ -142,6 +146,8 @@ template("spvtools_glsl_tables") {
rebase_path(glsl_json_file, root_build_dir), rebase_path(glsl_json_file, root_build_dir),
"--glsl-insts-output", "--glsl-insts-output",
rebase_path(glsl_insts_file, root_build_dir), rebase_path(glsl_insts_file, root_build_dir),
"--output-language",
"c++"
] ]
inputs = [ inputs = [
core_json_file, core_json_file,

View File

@ -200,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") if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
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 "")

2
DEPS
View File

@ -6,7 +6,7 @@ vars = {
'effcee_revision': '35912e1b7778ec2ddcff7e7188177761539e59e0', 'effcee_revision': '35912e1b7778ec2ddcff7e7188177761539e59e0',
'googletest_revision': 'd9bb8412d60b993365abb53f00b6dad9b2c01b62', 'googletest_revision': 'd9bb8412d60b993365abb53f00b6dad9b2c01b62',
're2_revision': 'd2836d1b1c34c4e330a85a1006201db474bf2c8a', 're2_revision': 'd2836d1b1c34c4e330a85a1006201db474bf2c8a',
'spirv_headers_revision': '85a1ed200d50660786c1a88d9166e871123cce39', 'spirv_headers_revision': '47f2465ee3e78ec5ec38f00b2c405d9475797228',
} }
deps = { deps = {

View File

@ -66,7 +66,8 @@ def generate_core_tables(version = None):
"--extinst-debuginfo-grammar=$(location {1}) " + "--extinst-debuginfo-grammar=$(location {1}) " +
"--extinst-cldebuginfo100-grammar=$(location {2}) " + "--extinst-cldebuginfo100-grammar=$(location {2}) " +
"--core-insts-output=$(location {3}) " + "--core-insts-output=$(location {3}) " +
"--operand-kinds-output=$(location {4})" "--operand-kinds-output=$(location {4}) " +
"--output-language=c++"
).format(*fmtargs), ).format(*fmtargs),
cmd_bat = ( cmd_bat = (
"$(location :generate_grammar_tables) " + "$(location :generate_grammar_tables) " +
@ -74,7 +75,8 @@ def generate_core_tables(version = None):
"--extinst-debuginfo-grammar=$(location {1}) " + "--extinst-debuginfo-grammar=$(location {1}) " +
"--extinst-cldebuginfo100-grammar=$(location {2}) " + "--extinst-cldebuginfo100-grammar=$(location {2}) " +
"--core-insts-output=$(location {3}) " + "--core-insts-output=$(location {3}) " +
"--operand-kinds-output=$(location {4})" "--operand-kinds-output=$(location {4}) " +
"--output-language=c++"
).format(*fmtargs), ).format(*fmtargs),
exec_tools = [":generate_grammar_tables"], exec_tools = [":generate_grammar_tables"],
visibility = ["//visibility:private"], visibility = ["//visibility:private"],
@ -103,7 +105,8 @@ def generate_enum_string_mapping(version = None):
"--extinst-debuginfo-grammar=$(location {1}) " + "--extinst-debuginfo-grammar=$(location {1}) " +
"--extinst-cldebuginfo100-grammar=$(location {2}) " + "--extinst-cldebuginfo100-grammar=$(location {2}) " +
"--extension-enum-output=$(location {3}) " + "--extension-enum-output=$(location {3}) " +
"--enum-string-mapping-output=$(location {4})" "--enum-string-mapping-output=$(location {4}) " +
"--output-language=c++"
).format(*fmtargs), ).format(*fmtargs),
cmd_bat = ( cmd_bat = (
"$(location :generate_grammar_tables) " + "$(location :generate_grammar_tables) " +
@ -111,7 +114,8 @@ def generate_enum_string_mapping(version = None):
"--extinst-debuginfo-grammar=$(location {1}) " + "--extinst-debuginfo-grammar=$(location {1}) " +
"--extinst-cldebuginfo100-grammar=$(location {2}) " + "--extinst-cldebuginfo100-grammar=$(location {2}) " +
"--extension-enum-output=$(location {3}) " + "--extension-enum-output=$(location {3}) " +
"--enum-string-mapping-output=$(location {4})" "--enum-string-mapping-output=$(location {4}) " +
"--output-language=c++"
).format(*fmtargs), ).format(*fmtargs),
exec_tools = [":generate_grammar_tables"], exec_tools = [":generate_grammar_tables"],
visibility = ["//visibility:private"], visibility = ["//visibility:private"],
@ -158,12 +162,14 @@ def generate_glsl_tables(version = None):
cmd = ( cmd = (
"$(location :generate_grammar_tables) " + "$(location :generate_grammar_tables) " +
"--extinst-glsl-grammar=$(location {0}) " + "--extinst-glsl-grammar=$(location {0}) " +
"--glsl-insts-output=$(location {1})" "--glsl-insts-output=$(location {1}) " +
"--output-language=c++"
).format(*fmtargs), ).format(*fmtargs),
cmd_bat = ( cmd_bat = (
"$(location :generate_grammar_tables) " + "$(location :generate_grammar_tables) " +
"--extinst-glsl-grammar=$(location {0}) " + "--extinst-glsl-grammar=$(location {0}) " +
"--glsl-insts-output=$(location {1})" "--glsl-insts-output=$(location {1}) " +
"--output-language=c++"
).format(*fmtargs), ).format(*fmtargs),
exec_tools = [":generate_grammar_tables"], exec_tools = [":generate_grammar_tables"],
visibility = ["//visibility:private"], visibility = ["//visibility:private"],

View File

@ -37,6 +37,7 @@ macro(spvtools_core_tables CONFIG_VERSION)
--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}
@ -58,6 +59,7 @@ macro(spvtools_enum_string_mapping CONFIG_VERSION)
--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}
@ -92,6 +94,7 @@ macro(spvtools_glsl_tables CONFIG_VERSION)
COMMAND ${PYTHON_EXECUTABLE} ${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})

View File

@ -78,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 {
SpvOp opcode; spv::Op 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 SpvOpIAdd // The name does not have the usual "Op" prefix. For example opcode
// is associated with the name "IAdd". // spv::Op::IAdd is associated with the name "IAdd".
// //
// clang-format off // clang-format off
#define CASE(NAME) { SpvOp##NAME, #NAME } #define CASE(NAME) { spv::Op::Op##NAME, #NAME }
const SpecConstantOpcodeEntry kOpSpecConstantOpcodes[] = { const SpecConstantOpcodeEntry kOpSpecConstantOpcodes[] = {
// Conversion // Conversion
CASE(SConvert), CASE(SConvert),
@ -173,7 +173,7 @@ bool AssemblyGrammar::isValid() const {
} }
CapabilitySet AssemblyGrammar::filterCapsAgainstTargetEnv( CapabilitySet AssemblyGrammar::filterCapsAgainstTargetEnv(
const SpvCapability* cap_array, uint32_t count) const { const spv::Capability* cap_array, uint32_t count) const {
CapabilitySet cap_set; CapabilitySet cap_set;
for (uint32_t i = 0; i < count; ++i) { for (uint32_t i = 0; i < count; ++i) {
spv_operand_desc cap_desc = {}; spv_operand_desc cap_desc = {};
@ -194,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(SpvOp opcode, spv_result_t AssemblyGrammar::lookupOpcode(spv::Op 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);
} }
@ -214,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,
SpvOp* opcode) const { spv::Op* 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,
@ -226,7 +226,7 @@ spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(const char* name,
return SPV_SUCCESS; return SPV_SUCCESS;
} }
spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(SpvOp opcode) const { spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(spv::Op 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,

View File

@ -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 SpvCapability* cap_array, CapabilitySet filterCapsAgainstTargetEnv(const spv::Capability* 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(SpvOp opcode, spv_opcode_desc* desc) const; spv_result_t lookupOpcode(spv::Op 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,11 +82,12 @@ 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, SpvOp* opcode) const; spv_result_t lookupSpecConstantOpcode(const char* name,
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(SpvOp opcode) const; spv_result_t lookupSpecConstantOpcode(spv::Op opcode) const;
// Parses a mask expression string for the given operand type. // Parses a mask expression string for the given operand type.
// //

View File

@ -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, SpvOp opcode, spv_result_t exhaustedInputDiagnostic(size_t inst_offset, spv::Op 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<SpvOp>(inst.opcode), &opcode_desc)) if (grammar_.lookupOpcode(static_cast<spv::Op>(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 SpvOp opcode = static_cast<SpvOp>(inst->opcode); const spv::Op opcode = static_cast<spv::Op>(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 == SpvOpExtInst && parsed_operand.offset == 3) { if (opcode == spv::Op::OpExtInst && 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(SpvOpExtInst == opcode); assert(spv::Op::OpExtInst == 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(SpvOpSpecConstantOp == opcode); assert(spv::Op::OpSpecConstantOp == opcode);
if (word > static_cast<uint32_t>(SpvOp::SpvOpMax) || if (word > static_cast<uint32_t>(spv::Op::Max) ||
grammar_.lookupSpecConstantOpcode(SpvOp(word))) { grammar_.lookupSpecConstantOpcode(spv::Op(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(SpvOp(word), &opcode_entry)) { if (grammar_.lookupOpcode(spv::Op(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";
} }
@ -549,7 +549,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
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 == SpvOpSwitch) { if (opcode == spv::Op::OpSwitch) {
// 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);
@ -575,7 +575,8 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
<< " is not a scalar integer"; << " is not a scalar integer";
} }
} else { } else {
assert(opcode == SpvOpConstant || opcode == SpvOpSpecConstant); assert(opcode == spv::Op::OpConstant ||
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);
@ -607,7 +608,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 (SpvOpExtInstImport == opcode) { if (spv::Op::OpExtInstImport == 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.
@ -789,14 +790,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 SpvOp opcode = static_cast<SpvOp>(inst->opcode); const spv::Op opcode = static_cast<spv::Op>(inst->opcode);
if (spvOpcodeGeneratesType(opcode)) { if (spvOpcodeGeneratesType(opcode)) {
NumberType info = {SPV_NUMBER_NONE, 0}; NumberType info = {SPV_NUMBER_NONE, 0};
if (SpvOpTypeInt == opcode) { if (spv::Op::OpTypeInt == 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 (SpvOpTypeFloat == opcode) { } else if (spv::Op::OpTypeFloat == 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);
} }

View File

@ -44,8 +44,8 @@ using IdGroup = std::vector<uint32_t>;
// different implementations produce identical results. // different implementations produce identical results.
using IdGroupMapByName = std::map<std::string, IdGroup>; using IdGroupMapByName = std::map<std::string, IdGroup>;
using IdGroupMapByTypeId = std::map<uint32_t, IdGroup>; using IdGroupMapByTypeId = std::map<uint32_t, IdGroup>;
using IdGroupMapByOp = std::map<SpvOp, IdGroup>; using IdGroupMapByOp = std::map<spv::Op, IdGroup>;
using IdGroupMapByStorageClass = std::map<SpvStorageClass, IdGroup>; using IdGroupMapByStorageClass = std::map<spv::StorageClass, IdGroup>;
// A set of potential id mappings that haven't been resolved yet. Any id in src // A set of potential id mappings that haven't been resolved yet. Any id in src
// may map in any id in dst. Note that ids are added in the same order as they // may map in any id in dst. Note that ids are added in the same order as they
@ -301,10 +301,10 @@ class Differ {
// Get various properties from an id. These Helper functions are passed to // Get various properties from an id. These Helper functions are passed to
// `GroupIds` and `GroupIdsAndMatch` below (as the `get_group` argument). // `GroupIds` and `GroupIdsAndMatch` below (as the `get_group` argument).
uint32_t GroupIdsHelperGetTypeId(const IdInstructions& id_to, uint32_t id); uint32_t GroupIdsHelperGetTypeId(const IdInstructions& id_to, uint32_t id);
SpvStorageClass GroupIdsHelperGetTypePointerStorageClass( spv::StorageClass GroupIdsHelperGetTypePointerStorageClass(
const IdInstructions& id_to, uint32_t id); const IdInstructions& id_to, uint32_t id);
SpvOp GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to, spv::Op GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
uint32_t id); uint32_t id);
// Given a list of ids, groups them based on some value. The `get_group` // Given a list of ids, groups them based on some value. The `get_group`
// function extracts a piece of information corresponding to each id, and the // function extracts a piece of information corresponding to each id, and the
@ -414,8 +414,8 @@ class Differ {
// Helper functions to retrieve information pertaining to an id // Helper functions to retrieve information pertaining to an id
const opt::Instruction* GetInst(const IdInstructions& id_to, uint32_t id); const opt::Instruction* GetInst(const IdInstructions& id_to, uint32_t id);
uint32_t GetConstantUint(const IdInstructions& id_to, uint32_t constant_id); uint32_t GetConstantUint(const IdInstructions& id_to, uint32_t constant_id);
SpvExecutionModel GetExecutionModel(const opt::Module* module, spv::ExecutionModel GetExecutionModel(const opt::Module* module,
uint32_t entry_point_id); uint32_t entry_point_id);
bool HasName(const IdInstructions& id_to, uint32_t id); bool HasName(const IdInstructions& id_to, uint32_t id);
// Get the OpName associated with an id // Get the OpName associated with an id
std::string GetName(const IdInstructions& id_to, uint32_t id, bool* has_name); std::string GetName(const IdInstructions& id_to, uint32_t id, bool* has_name);
@ -424,20 +424,21 @@ class Differ {
// string, and this improves diff between SPIR-V from those tools and others. // string, and this improves diff between SPIR-V from those tools and others.
std::string GetSanitizedName(const IdInstructions& id_to, uint32_t id); std::string GetSanitizedName(const IdInstructions& id_to, uint32_t id);
uint32_t GetVarTypeId(const IdInstructions& id_to, uint32_t var_id, uint32_t GetVarTypeId(const IdInstructions& id_to, uint32_t var_id,
SpvStorageClass* storage_class); spv::StorageClass* storage_class);
bool GetDecorationValue(const IdInstructions& id_to, uint32_t id, bool GetDecorationValue(const IdInstructions& id_to, uint32_t id,
SpvDecoration decoration, uint32_t* decoration_value); spv::Decoration decoration,
uint32_t* decoration_value);
const opt::Instruction* GetForwardPointerInst(const IdInstructions& id_to, const opt::Instruction* GetForwardPointerInst(const IdInstructions& id_to,
uint32_t id); uint32_t id);
bool IsIntType(const IdInstructions& id_to, uint32_t type_id); bool IsIntType(const IdInstructions& id_to, uint32_t type_id);
bool IsFloatType(const IdInstructions& id_to, uint32_t type_id); bool IsFloatType(const IdInstructions& id_to, uint32_t type_id);
bool IsConstantUint(const IdInstructions& id_to, uint32_t id); bool IsConstantUint(const IdInstructions& id_to, uint32_t id);
bool IsVariable(const IdInstructions& id_to, uint32_t pointer_id); bool IsVariable(const IdInstructions& id_to, uint32_t pointer_id);
bool IsOp(const IdInstructions& id_to, uint32_t id, SpvOp opcode); bool IsOp(const IdInstructions& id_to, uint32_t id, spv::Op opcode);
bool IsPerVertexType(const IdInstructions& id_to, uint32_t type_id); bool IsPerVertexType(const IdInstructions& id_to, uint32_t type_id);
bool IsPerVertexVariable(const IdInstructions& id_to, uint32_t type_id); bool IsPerVertexVariable(const IdInstructions& id_to, uint32_t type_id);
SpvStorageClass GetPerVertexStorageClass(const opt::Module* module, spv::StorageClass GetPerVertexStorageClass(const opt::Module* module,
uint32_t type_id); uint32_t type_id);
spv_ext_inst_type_t GetExtInstType(const IdInstructions& id_to, spv_ext_inst_type_t GetExtInstType(const IdInstructions& id_to,
uint32_t set_id); uint32_t set_id);
spv_number_kind_t GetNumberKind(const IdInstructions& id_to, spv_number_kind_t GetNumberKind(const IdInstructions& id_to,
@ -561,19 +562,19 @@ void IdInstructions::MapIdsToInfos(
uint32_t id_operand = 0; uint32_t id_operand = 0;
switch (inst.opcode()) { switch (inst.opcode()) {
case SpvOpName: case spv::Op::OpName:
info_map = &name_map_; info_map = &name_map_;
break; break;
case SpvOpMemberName: case spv::Op::OpMemberName:
info_map = &name_map_; info_map = &name_map_;
break; break;
case SpvOpDecorate: case spv::Op::OpDecorate:
info_map = &decoration_map_; info_map = &decoration_map_;
break; break;
case SpvOpMemberDecorate: case spv::Op::OpMemberDecorate:
info_map = &decoration_map_; info_map = &decoration_map_;
break; break;
case SpvOpTypeForwardPointer: { case spv::Op::OpTypeForwardPointer: {
uint32_t id = inst.GetSingleWordOperand(0); uint32_t id = inst.GetSingleWordOperand(0);
assert(id != 0); assert(id != 0);
@ -731,10 +732,10 @@ int Differ::ComparePreambleInstructions(const opt::Instruction* a,
// Instead of comparing OpExecutionMode entry point ids as ids, compare them // Instead of comparing OpExecutionMode entry point ids as ids, compare them
// through their corresponding execution model. This simplifies traversing // through their corresponding execution model. This simplifies traversing
// the sorted list of instructions between src and dst modules. // the sorted list of instructions between src and dst modules.
if (a->opcode() == SpvOpExecutionMode) { if (a->opcode() == spv::Op::OpExecutionMode) {
const SpvExecutionModel src_model = const spv::ExecutionModel src_model =
GetExecutionModel(src_inst_module, a->GetSingleWordOperand(0)); GetExecutionModel(src_inst_module, a->GetSingleWordOperand(0));
const SpvExecutionModel dst_model = const spv::ExecutionModel dst_model =
GetExecutionModel(dst_inst_module, b->GetSingleWordOperand(0)); GetExecutionModel(dst_inst_module, b->GetSingleWordOperand(0));
if (src_model < dst_model) { if (src_model < dst_model) {
@ -818,17 +819,17 @@ uint32_t Differ::GroupIdsHelperGetTypeId(const IdInstructions& id_to,
return GetInst(id_to, id)->type_id(); return GetInst(id_to, id)->type_id();
} }
SpvStorageClass Differ::GroupIdsHelperGetTypePointerStorageClass( spv::StorageClass Differ::GroupIdsHelperGetTypePointerStorageClass(
const IdInstructions& id_to, uint32_t id) { const IdInstructions& id_to, uint32_t id) {
const opt::Instruction* inst = GetInst(id_to, id); const opt::Instruction* inst = GetInst(id_to, id);
assert(inst && inst->opcode() == SpvOpTypePointer); assert(inst && inst->opcode() == spv::Op::OpTypePointer);
return SpvStorageClass(inst->GetSingleWordInOperand(0)); return spv::StorageClass(inst->GetSingleWordInOperand(0));
} }
SpvOp Differ::GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to, spv::Op Differ::GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
uint32_t id) { uint32_t id) {
const opt::Instruction* inst = GetInst(id_to, id); const opt::Instruction* inst = GetInst(id_to, id);
assert(inst && inst->opcode() == SpvOpTypePointer); assert(inst && inst->opcode() == spv::Op::OpTypePointer);
const uint32_t type_id = inst->GetSingleWordInOperand(1); const uint32_t type_id = inst->GetSingleWordInOperand(1);
const opt::Instruction* type_inst = GetInst(id_to, type_id); const opt::Instruction* type_inst = GetInst(id_to, type_id);
@ -1020,7 +1021,7 @@ bool Differ::DoInstructionsMatchFuzzy(const opt::Instruction* src_inst,
} }
// For external instructions, make sure the set and opcode of the external // For external instructions, make sure the set and opcode of the external
// instruction matches too. // instruction matches too.
if (src_inst->opcode() == SpvOpExtInst) { if (src_inst->opcode() == spv::Op::OpExtInst) {
if (!DoOperandsMatch(src_inst, dst_inst, 0, 2)) { if (!DoOperandsMatch(src_inst, dst_inst, 0, 2)) {
return false; return false;
} }
@ -1064,26 +1065,26 @@ bool Differ::DoDebugAndAnnotationInstructionsMatch(
} }
switch (src_inst->opcode()) { switch (src_inst->opcode()) {
case SpvOpString: case spv::Op::OpString:
case SpvOpSourceExtension: case spv::Op::OpSourceExtension:
case SpvOpModuleProcessed: case spv::Op::OpModuleProcessed:
return DoesOperandMatch(src_inst->GetOperand(0), dst_inst->GetOperand(0)); return DoesOperandMatch(src_inst->GetOperand(0), dst_inst->GetOperand(0));
case SpvOpSource: case spv::Op::OpSource:
return DoOperandsMatch(src_inst, dst_inst, 0, 2); return DoOperandsMatch(src_inst, dst_inst, 0, 2);
case SpvOpSourceContinued: case spv::Op::OpSourceContinued:
return true; return true;
case SpvOpName: case spv::Op::OpName:
return DoOperandsMatch(src_inst, dst_inst, 0, 1); return DoOperandsMatch(src_inst, dst_inst, 0, 1);
case SpvOpMemberName: case spv::Op::OpMemberName:
return DoOperandsMatch(src_inst, dst_inst, 0, 2); return DoOperandsMatch(src_inst, dst_inst, 0, 2);
case SpvOpDecorate: case spv::Op::OpDecorate:
return DoOperandsMatch(src_inst, dst_inst, 0, 2); return DoOperandsMatch(src_inst, dst_inst, 0, 2);
case SpvOpMemberDecorate: case spv::Op::OpMemberDecorate:
return DoOperandsMatch(src_inst, dst_inst, 0, 3); return DoOperandsMatch(src_inst, dst_inst, 0, 3);
case SpvOpExtInst: case spv::Op::OpExtInst:
case SpvOpDecorationGroup: case spv::Op::OpDecorationGroup:
case SpvOpGroupDecorate: case spv::Op::OpGroupDecorate:
case SpvOpGroupMemberDecorate: case spv::Op::OpGroupMemberDecorate:
return false; return false;
default: default:
return false; return false;
@ -1095,9 +1096,9 @@ bool Differ::AreVariablesMatchable(uint32_t src_id, uint32_t dst_id,
// Variables must match by their built-in decorations. // Variables must match by their built-in decorations.
uint32_t src_built_in_decoration = 0, dst_built_in_decoration = 0; uint32_t src_built_in_decoration = 0, dst_built_in_decoration = 0;
const bool src_is_built_in = GetDecorationValue( const bool src_is_built_in = GetDecorationValue(
src_id_to_, src_id, SpvDecorationBuiltIn, &src_built_in_decoration); src_id_to_, src_id, spv::Decoration::BuiltIn, &src_built_in_decoration);
const bool dst_is_built_in = GetDecorationValue( const bool dst_is_built_in = GetDecorationValue(
dst_id_to_, dst_id, SpvDecorationBuiltIn, &dst_built_in_decoration); dst_id_to_, dst_id, spv::Decoration::BuiltIn, &dst_built_in_decoration);
if (src_is_built_in != dst_is_built_in) { if (src_is_built_in != dst_is_built_in) {
return false; return false;
@ -1107,7 +1108,7 @@ bool Differ::AreVariablesMatchable(uint32_t src_id, uint32_t dst_id,
} }
// Check their types and storage classes. // Check their types and storage classes.
SpvStorageClass src_storage_class, dst_storage_class; spv::StorageClass src_storage_class, dst_storage_class;
const uint32_t src_type_id = const uint32_t src_type_id =
GetVarTypeId(src_id_to_, src_id, &src_storage_class); GetVarTypeId(src_id_to_, src_id, &src_storage_class);
const uint32_t dst_type_id = const uint32_t dst_type_id =
@ -1127,12 +1128,14 @@ bool Differ::AreVariablesMatchable(uint32_t src_id, uint32_t dst_id,
// Allow one of the two to be Private while the other is Input or // Allow one of the two to be Private while the other is Input or
// Output, this allows matching in/out variables that have been turned // Output, this allows matching in/out variables that have been turned
// global as part of linking two stages (as done in ANGLE). // global as part of linking two stages (as done in ANGLE).
const bool src_is_io = src_storage_class == SpvStorageClassInput || const bool src_is_io = src_storage_class == spv::StorageClass::Input ||
src_storage_class == SpvStorageClassOutput; src_storage_class == spv::StorageClass::Output;
const bool dst_is_io = dst_storage_class == SpvStorageClassInput || const bool dst_is_io = dst_storage_class == spv::StorageClass::Input ||
dst_storage_class == SpvStorageClassOutput; dst_storage_class == spv::StorageClass::Output;
const bool src_is_private = src_storage_class == SpvStorageClassPrivate; const bool src_is_private =
const bool dst_is_private = dst_storage_class == SpvStorageClassPrivate; src_storage_class == spv::StorageClass::Private;
const bool dst_is_private =
dst_storage_class == spv::StorageClass::Private;
if (!((src_is_io && dst_is_private) || (src_is_private && dst_is_io))) { if (!((src_is_io && dst_is_private) || (src_is_private && dst_is_io))) {
return false; return false;
@ -1277,16 +1280,16 @@ bool Differ::MatchOpSpecConstant(const opt::Instruction* src_inst,
// Otherwise, match them by SpecId. // Otherwise, match them by SpecId.
uint32_t src_spec_id, dst_spec_id; uint32_t src_spec_id, dst_spec_id;
if (GetDecorationValue(src_id_to_, src_id, SpvDecorationSpecId, if (GetDecorationValue(src_id_to_, src_id, spv::Decoration::SpecId,
&src_spec_id) && &src_spec_id) &&
GetDecorationValue(dst_id_to_, dst_id, SpvDecorationSpecId, GetDecorationValue(dst_id_to_, dst_id, spv::Decoration::SpecId,
&dst_spec_id)) { &dst_spec_id)) {
return src_spec_id == dst_spec_id; return src_spec_id == dst_spec_id;
} }
// There is no SpecId decoration, while not practical, still valid. // There is no SpecId decoration, while not practical, still valid.
// SpecConstantOp don't have SpecId and can be matched by operands // SpecConstantOp don't have SpecId and can be matched by operands
if (src_inst->opcode() == SpvOpSpecConstantOp) { if (src_inst->opcode() == spv::Op::OpSpecConstantOp) {
if (src_inst->NumInOperandWords() == dst_inst->NumInOperandWords()) { if (src_inst->NumInOperandWords() == dst_inst->NumInOperandWords()) {
return DoOperandsMatch(src_inst, dst_inst, 0, return DoOperandsMatch(src_inst, dst_inst, 0,
src_inst->NumInOperandWords()); src_inst->NumInOperandWords());
@ -1327,13 +1330,13 @@ bool Differ::MatchOpVariable(const opt::Instruction* src_inst,
// built-in decorations. // built-in decorations.
uint32_t src_built_in_decoration; uint32_t src_built_in_decoration;
const bool src_is_built_in = GetDecorationValue( const bool src_is_built_in = GetDecorationValue(
src_id_to_, src_id, SpvDecorationBuiltIn, &src_built_in_decoration); src_id_to_, src_id, spv::Decoration::BuiltIn, &src_built_in_decoration);
if (src_is_built_in && AreVariablesMatchable(src_id, dst_id, flexibility)) { if (src_is_built_in && AreVariablesMatchable(src_id, dst_id, flexibility)) {
return true; return true;
} }
SpvStorageClass src_storage_class, dst_storage_class; spv::StorageClass src_storage_class, dst_storage_class;
GetVarTypeId(src_id_to_, src_id, &src_storage_class); GetVarTypeId(src_id_to_, src_id, &src_storage_class);
GetVarTypeId(dst_id_to_, dst_id, &dst_storage_class); GetVarTypeId(dst_id_to_, dst_id, &dst_storage_class);
@ -1348,13 +1351,13 @@ bool Differ::MatchOpVariable(const opt::Instruction* src_inst,
uint32_t src_binding = 0, dst_binding = 0; uint32_t src_binding = 0, dst_binding = 0;
const bool src_has_set = GetDecorationValue( const bool src_has_set = GetDecorationValue(
src_id_to_, src_id, SpvDecorationDescriptorSet, &src_set); src_id_to_, src_id, spv::Decoration::DescriptorSet, &src_set);
const bool dst_has_set = GetDecorationValue( const bool dst_has_set = GetDecorationValue(
dst_id_to_, dst_id, SpvDecorationDescriptorSet, &dst_set); dst_id_to_, dst_id, spv::Decoration::DescriptorSet, &dst_set);
const bool src_has_binding = const bool src_has_binding = GetDecorationValue(
GetDecorationValue(src_id_to_, src_id, SpvDecorationBinding, &src_set); src_id_to_, src_id, spv::Decoration::Binding, &src_set);
const bool dst_has_binding = const bool dst_has_binding = GetDecorationValue(
GetDecorationValue(dst_id_to_, dst_id, SpvDecorationBinding, &dst_set); dst_id_to_, dst_id, spv::Decoration::Binding, &dst_set);
if (src_has_set && dst_has_set && src_has_binding && dst_has_binding) { if (src_has_set && dst_has_set && src_has_binding && dst_has_binding) {
return src_set == dst_set && src_binding == dst_binding; return src_set == dst_set && src_binding == dst_binding;
@ -1367,9 +1370,9 @@ bool Differ::MatchOpVariable(const opt::Instruction* src_inst,
uint32_t src_location, dst_location; uint32_t src_location, dst_location;
const bool src_has_location = GetDecorationValue( const bool src_has_location = GetDecorationValue(
src_id_to_, src_id, SpvDecorationLocation, &src_location); src_id_to_, src_id, spv::Decoration::Location, &src_location);
const bool dst_has_location = GetDecorationValue( const bool dst_has_location = GetDecorationValue(
dst_id_to_, dst_id, SpvDecorationLocation, &dst_location); dst_id_to_, dst_id, spv::Decoration::Location, &dst_location);
if (src_has_location && dst_has_location) { if (src_has_location && dst_has_location) {
return src_location == dst_location; return src_location == dst_location;
@ -1384,25 +1387,25 @@ bool Differ::MatchPerVertexType(uint32_t src_type_id, uint32_t dst_type_id) {
// For gl_PerVertex, find the type pointer of this type (array) and make sure // For gl_PerVertex, find the type pointer of this type (array) and make sure
// the storage classes of src and dst match; geometry and tessellation shaders // the storage classes of src and dst match; geometry and tessellation shaders
// have two instances of gl_PerVertex. // have two instances of gl_PerVertex.
SpvStorageClass src_storage_class = spv::StorageClass src_storage_class =
GetPerVertexStorageClass(src_, src_type_id); GetPerVertexStorageClass(src_, src_type_id);
SpvStorageClass dst_storage_class = spv::StorageClass dst_storage_class =
GetPerVertexStorageClass(dst_, dst_type_id); GetPerVertexStorageClass(dst_, dst_type_id);
assert(src_storage_class == SpvStorageClassInput || assert(src_storage_class == spv::StorageClass::Input ||
src_storage_class == SpvStorageClassOutput); src_storage_class == spv::StorageClass::Output);
assert(dst_storage_class == SpvStorageClassInput || assert(dst_storage_class == spv::StorageClass::Input ||
dst_storage_class == SpvStorageClassOutput); dst_storage_class == spv::StorageClass::Output);
return src_storage_class == dst_storage_class; return src_storage_class == dst_storage_class;
} }
bool Differ::MatchPerVertexVariable(const opt::Instruction* src_inst, bool Differ::MatchPerVertexVariable(const opt::Instruction* src_inst,
const opt::Instruction* dst_inst) { const opt::Instruction* dst_inst) {
SpvStorageClass src_storage_class = spv::StorageClass src_storage_class =
SpvStorageClass(src_inst->GetSingleWordInOperand(0)); spv::StorageClass(src_inst->GetSingleWordInOperand(0));
SpvStorageClass dst_storage_class = spv::StorageClass dst_storage_class =
SpvStorageClass(dst_inst->GetSingleWordInOperand(0)); spv::StorageClass(dst_inst->GetSingleWordInOperand(0));
return src_storage_class == dst_storage_class; return src_storage_class == dst_storage_class;
} }
@ -1479,7 +1482,7 @@ InstructionList Differ::GetFunctionHeader(const opt::Function& function) {
InstructionList body; InstructionList body;
function.WhileEachInst( function.WhileEachInst(
[&body](const opt::Instruction* inst) { [&body](const opt::Instruction* inst) {
if (inst->opcode() == SpvOpLabel) { if (inst->opcode() == spv::Op::OpLabel) {
return false; return false;
} }
body.push_back(inst); body.push_back(inst);
@ -1694,12 +1697,12 @@ void Differ::MatchVariablesUsedByMatchedInstructions(
default: default:
// TODO: match functions based on OpFunctionCall? // TODO: match functions based on OpFunctionCall?
break; break;
case SpvOpAccessChain: case spv::Op::OpAccessChain:
case SpvOpInBoundsAccessChain: case spv::Op::OpInBoundsAccessChain:
case SpvOpPtrAccessChain: case spv::Op::OpPtrAccessChain:
case SpvOpInBoundsPtrAccessChain: case spv::Op::OpInBoundsPtrAccessChain:
case SpvOpLoad: case spv::Op::OpLoad:
case SpvOpStore: case spv::Op::OpStore:
const uint32_t src_pointer_id = src_inst->GetSingleWordInOperand(0); const uint32_t src_pointer_id = src_inst->GetSingleWordInOperand(0);
const uint32_t dst_pointer_id = dst_inst->GetSingleWordInOperand(0); const uint32_t dst_pointer_id = dst_inst->GetSingleWordInOperand(0);
if (IsVariable(src_id_to_, src_pointer_id) && if (IsVariable(src_id_to_, src_pointer_id) &&
@ -1727,23 +1730,24 @@ const opt::Instruction* Differ::GetInst(const IdInstructions& id_to,
uint32_t Differ::GetConstantUint(const IdInstructions& id_to, uint32_t Differ::GetConstantUint(const IdInstructions& id_to,
uint32_t constant_id) { uint32_t constant_id) {
const opt::Instruction* constant_inst = GetInst(id_to, constant_id); const opt::Instruction* constant_inst = GetInst(id_to, constant_id);
assert(constant_inst->opcode() == SpvOpConstant); assert(constant_inst->opcode() == spv::Op::OpConstant);
assert(GetInst(id_to, constant_inst->type_id())->opcode() == SpvOpTypeInt); assert(GetInst(id_to, constant_inst->type_id())->opcode() ==
spv::Op::OpTypeInt);
return constant_inst->GetSingleWordInOperand(0); return constant_inst->GetSingleWordInOperand(0);
} }
SpvExecutionModel Differ::GetExecutionModel(const opt::Module* module, spv::ExecutionModel Differ::GetExecutionModel(const opt::Module* module,
uint32_t entry_point_id) { uint32_t entry_point_id) {
for (const opt::Instruction& inst : module->entry_points()) { for (const opt::Instruction& inst : module->entry_points()) {
assert(inst.opcode() == SpvOpEntryPoint); assert(inst.opcode() == spv::Op::OpEntryPoint);
if (inst.GetSingleWordOperand(1) == entry_point_id) { if (inst.GetSingleWordOperand(1) == entry_point_id) {
return SpvExecutionModel(inst.GetSingleWordOperand(0)); return spv::ExecutionModel(inst.GetSingleWordOperand(0));
} }
} }
assert(false && "Unreachable"); assert(false && "Unreachable");
return SpvExecutionModel(0xFFF); return spv::ExecutionModel(0xFFF);
} }
bool Differ::HasName(const IdInstructions& id_to, uint32_t id) { bool Differ::HasName(const IdInstructions& id_to, uint32_t id) {
@ -1751,7 +1755,7 @@ bool Differ::HasName(const IdInstructions& id_to, uint32_t id) {
assert(id < id_to.name_map_.size()); assert(id < id_to.name_map_.size());
for (const opt::Instruction* inst : id_to.name_map_[id]) { for (const opt::Instruction* inst : id_to.name_map_[id]) {
if (inst->opcode() == SpvOpName) { if (inst->opcode() == spv::Op::OpName) {
return true; return true;
} }
} }
@ -1765,7 +1769,7 @@ std::string Differ::GetName(const IdInstructions& id_to, uint32_t id,
assert(id < id_to.name_map_.size()); assert(id < id_to.name_map_.size());
for (const opt::Instruction* inst : id_to.name_map_[id]) { for (const opt::Instruction* inst : id_to.name_map_[id]) {
if (inst->opcode() == SpvOpName) { if (inst->opcode() == spv::Op::OpName) {
*has_name = true; *has_name = true;
return inst->GetOperand(1).AsString(); return inst->GetOperand(1).AsString();
} }
@ -1788,11 +1792,11 @@ std::string Differ::GetSanitizedName(const IdInstructions& id_to, uint32_t id) {
} }
uint32_t Differ::GetVarTypeId(const IdInstructions& id_to, uint32_t var_id, uint32_t Differ::GetVarTypeId(const IdInstructions& id_to, uint32_t var_id,
SpvStorageClass* storage_class) { spv::StorageClass* storage_class) {
const opt::Instruction* var_inst = GetInst(id_to, var_id); const opt::Instruction* var_inst = GetInst(id_to, var_id);
assert(var_inst->opcode() == SpvOpVariable); assert(var_inst->opcode() == spv::Op::OpVariable);
*storage_class = SpvStorageClass(var_inst->GetSingleWordInOperand(0)); *storage_class = spv::StorageClass(var_inst->GetSingleWordInOperand(0));
// Get the type pointer from the variable. // Get the type pointer from the variable.
const uint32_t type_pointer_id = var_inst->type_id(); const uint32_t type_pointer_id = var_inst->type_id();
@ -1803,15 +1807,15 @@ uint32_t Differ::GetVarTypeId(const IdInstructions& id_to, uint32_t var_id,
} }
bool Differ::GetDecorationValue(const IdInstructions& id_to, uint32_t id, bool Differ::GetDecorationValue(const IdInstructions& id_to, uint32_t id,
SpvDecoration decoration, spv::Decoration decoration,
uint32_t* decoration_value) { uint32_t* decoration_value) {
assert(id != 0); assert(id != 0);
assert(id < id_to.decoration_map_.size()); assert(id < id_to.decoration_map_.size());
for (const opt::Instruction* inst : id_to.decoration_map_[id]) { for (const opt::Instruction* inst : id_to.decoration_map_[id]) {
if (inst->opcode() == SpvOpDecorate && if (inst->opcode() == spv::Op::OpDecorate &&
inst->GetSingleWordOperand(0) == id && inst->GetSingleWordOperand(0) == id &&
inst->GetSingleWordOperand(1) == decoration) { spv::Decoration(inst->GetSingleWordOperand(1)) == decoration) {
*decoration_value = inst->GetSingleWordOperand(2); *decoration_value = inst->GetSingleWordOperand(2);
return true; return true;
} }
@ -1828,28 +1832,28 @@ const opt::Instruction* Differ::GetForwardPointerInst(
} }
bool Differ::IsIntType(const IdInstructions& id_to, uint32_t type_id) { bool Differ::IsIntType(const IdInstructions& id_to, uint32_t type_id) {
return IsOp(id_to, type_id, SpvOpTypeInt); return IsOp(id_to, type_id, spv::Op::OpTypeInt);
} }
bool Differ::IsFloatType(const IdInstructions& id_to, uint32_t type_id) { bool Differ::IsFloatType(const IdInstructions& id_to, uint32_t type_id) {
return IsOp(id_to, type_id, SpvOpTypeFloat); return IsOp(id_to, type_id, spv::Op::OpTypeFloat);
} }
bool Differ::IsConstantUint(const IdInstructions& id_to, uint32_t id) { bool Differ::IsConstantUint(const IdInstructions& id_to, uint32_t id) {
const opt::Instruction* constant_inst = GetInst(id_to, id); const opt::Instruction* constant_inst = GetInst(id_to, id);
if (constant_inst->opcode() != SpvOpConstant) { if (constant_inst->opcode() != spv::Op::OpConstant) {
return false; return false;
} }
const opt::Instruction* type_inst = GetInst(id_to, constant_inst->type_id()); const opt::Instruction* type_inst = GetInst(id_to, constant_inst->type_id());
return type_inst->opcode() == SpvOpTypeInt; return type_inst->opcode() == spv::Op::OpTypeInt;
} }
bool Differ::IsVariable(const IdInstructions& id_to, uint32_t pointer_id) { bool Differ::IsVariable(const IdInstructions& id_to, uint32_t pointer_id) {
return IsOp(id_to, pointer_id, SpvOpVariable); return IsOp(id_to, pointer_id, spv::Op::OpVariable);
} }
bool Differ::IsOp(const IdInstructions& id_to, uint32_t id, SpvOp op) { bool Differ::IsOp(const IdInstructions& id_to, uint32_t id, spv::Op op) {
return GetInst(id_to, id)->opcode() == op; return GetInst(id_to, id)->opcode() == op;
} }
@ -1858,17 +1862,18 @@ bool Differ::IsPerVertexType(const IdInstructions& id_to, uint32_t type_id) {
assert(type_id < id_to.decoration_map_.size()); assert(type_id < id_to.decoration_map_.size());
for (const opt::Instruction* inst : id_to.decoration_map_[type_id]) { for (const opt::Instruction* inst : id_to.decoration_map_[type_id]) {
if (inst->opcode() == SpvOpMemberDecorate && if (inst->opcode() == spv::Op::OpMemberDecorate &&
inst->GetSingleWordOperand(0) == type_id && inst->GetSingleWordOperand(0) == type_id &&
inst->GetSingleWordOperand(2) == SpvDecorationBuiltIn) { spv::Decoration(inst->GetSingleWordOperand(2)) ==
SpvBuiltIn built_in = SpvBuiltIn(inst->GetSingleWordOperand(3)); spv::Decoration::BuiltIn) {
spv::BuiltIn built_in = spv::BuiltIn(inst->GetSingleWordOperand(3));
// Only gl_PerVertex can have, and it can only have, the following // Only gl_PerVertex can have, and it can only have, the following
// built-in decorations. // built-in decorations.
return built_in == SpvBuiltInPosition || return built_in == spv::BuiltIn::Position ||
built_in == SpvBuiltInPointSize || built_in == spv::BuiltIn::PointSize ||
built_in == SpvBuiltInClipDistance || built_in == spv::BuiltIn::ClipDistance ||
built_in == SpvBuiltInCullDistance; built_in == spv::BuiltIn::CullDistance;
} }
} }
@ -1877,12 +1882,12 @@ bool Differ::IsPerVertexType(const IdInstructions& id_to, uint32_t type_id) {
bool Differ::IsPerVertexVariable(const IdInstructions& id_to, uint32_t var_id) { bool Differ::IsPerVertexVariable(const IdInstructions& id_to, uint32_t var_id) {
// Get the type from the type pointer. // Get the type from the type pointer.
SpvStorageClass storage_class; spv::StorageClass storage_class;
uint32_t type_id = GetVarTypeId(id_to, var_id, &storage_class); uint32_t type_id = GetVarTypeId(id_to, var_id, &storage_class);
const opt::Instruction* type_inst = GetInst(id_to, type_id); const opt::Instruction* type_inst = GetInst(id_to, type_id);
// If array, get the element type. // If array, get the element type.
if (type_inst->opcode() == SpvOpTypeArray) { if (type_inst->opcode() == spv::Op::OpTypeArray) {
type_id = type_inst->GetSingleWordInOperand(0); type_id = type_inst->GetSingleWordInOperand(0);
} }
@ -1890,21 +1895,21 @@ bool Differ::IsPerVertexVariable(const IdInstructions& id_to, uint32_t var_id) {
return IsPerVertexType(id_to, type_id); return IsPerVertexType(id_to, type_id);
} }
SpvStorageClass Differ::GetPerVertexStorageClass(const opt::Module* module, spv::StorageClass Differ::GetPerVertexStorageClass(const opt::Module* module,
uint32_t type_id) { uint32_t type_id) {
for (const opt::Instruction& inst : module->types_values()) { for (const opt::Instruction& inst : module->types_values()) {
switch (inst.opcode()) { switch (inst.opcode()) {
case SpvOpTypeArray: case spv::Op::OpTypeArray:
// The gl_PerVertex instance could be an array, look for a variable of // The gl_PerVertex instance could be an array, look for a variable of
// the array type instead. // the array type instead.
if (inst.GetSingleWordInOperand(0) == type_id) { if (inst.GetSingleWordInOperand(0) == type_id) {
type_id = inst.result_id(); type_id = inst.result_id();
} }
break; break;
case SpvOpTypePointer: case spv::Op::OpTypePointer:
// Find the storage class of the pointer to this type. // Find the storage class of the pointer to this type.
if (inst.GetSingleWordInOperand(1) == type_id) { if (inst.GetSingleWordInOperand(1) == type_id) {
return SpvStorageClass(inst.GetSingleWordInOperand(0)); return spv::StorageClass(inst.GetSingleWordInOperand(0));
} }
break; break;
default: default:
@ -1915,7 +1920,7 @@ SpvStorageClass Differ::GetPerVertexStorageClass(const opt::Module* module,
// gl_PerVertex is declared, but is unused. Return either of Input or Output // gl_PerVertex is declared, but is unused. Return either of Input or Output
// classes just so it matches one in the other module. This should be highly // classes just so it matches one in the other module. This should be highly
// unlikely, perhaps except for ancient GS-used-to-emulate-CS scenarios. // unlikely, perhaps except for ancient GS-used-to-emulate-CS scenarios.
return SpvStorageClassOutput; return spv::StorageClass::Output;
} }
spv_ext_inst_type_t Differ::GetExtInstType(const IdInstructions& id_to, spv_ext_inst_type_t Differ::GetExtInstType(const IdInstructions& id_to,
@ -1941,9 +1946,9 @@ spv_number_kind_t Differ::GetNumberKind(const IdInstructions& id_to,
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:
switch (inst.opcode()) { switch (inst.opcode()) {
case SpvOpSwitch: case spv::Op::OpSwitch:
case SpvOpConstant: case spv::Op::OpConstant:
case SpvOpSpecConstant: case spv::Op::OpSpecConstant:
// Same kind of number as the selector (OpSwitch) or the type // Same kind of number as the selector (OpSwitch) or the type
// (Op*Constant). // (Op*Constant).
return GetTypeNumberKind(id_to, inst.GetSingleWordOperand(0), return GetTypeNumberKind(id_to, inst.GetSingleWordOperand(0),
@ -1969,12 +1974,12 @@ spv_number_kind_t Differ::GetTypeNumberKind(const IdInstructions& id_to,
} }
switch (type_inst->opcode()) { switch (type_inst->opcode()) {
case SpvOpTypeInt: case spv::Op::OpTypeInt:
*number_bit_width = type_inst->GetSingleWordOperand(1); *number_bit_width = type_inst->GetSingleWordOperand(1);
return type_inst->GetSingleWordOperand(2) == 0 ? SPV_NUMBER_UNSIGNED_INT return type_inst->GetSingleWordOperand(2) == 0 ? SPV_NUMBER_UNSIGNED_INT
: SPV_NUMBER_SIGNED_INT; : SPV_NUMBER_SIGNED_INT;
break; break;
case SpvOpTypeFloat: case spv::Op::OpTypeFloat:
*number_bit_width = type_inst->GetSingleWordOperand(1); *number_bit_width = type_inst->GetSingleWordOperand(1);
return SPV_NUMBER_FLOATING; return SPV_NUMBER_FLOATING;
default: default:
@ -2092,7 +2097,7 @@ void Differ::MatchTypeForwardPointers() {
return inst.GetSingleWordOperand(0); return inst.GetSingleWordOperand(0);
}; };
auto accept_type_forward_pointer_ops = [](const opt::Instruction& inst) { auto accept_type_forward_pointer_ops = [](const opt::Instruction& inst) {
return inst.opcode() == SpvOpTypeForwardPointer; return inst.opcode() == spv::Op::OpTypeForwardPointer;
}; };
PoolPotentialIds(src_->types_values(), potential_id_map.src_ids, true, PoolPotentialIds(src_->types_values(), potential_id_map.src_ids, true,
@ -2116,17 +2121,17 @@ void Differ::MatchTypeForwardPointers() {
// - If leftover is unique, match // - If leftover is unique, match
// Group forwarded pointers by storage class first and loop over them. // Group forwarded pointers by storage class first and loop over them.
GroupIdsAndMatch<SpvStorageClass>( GroupIdsAndMatch<spv::StorageClass>(
potential_id_map.src_ids, potential_id_map.dst_ids, SpvStorageClassMax, potential_id_map.src_ids, potential_id_map.dst_ids,
&Differ::GroupIdsHelperGetTypePointerStorageClass, spv::StorageClass::Max, &Differ::GroupIdsHelperGetTypePointerStorageClass,
[this](const IdGroup& src_group_by_storage_class, [this](const IdGroup& src_group_by_storage_class,
const IdGroup& dst_group_by_storage_class) { const IdGroup& dst_group_by_storage_class) {
// Group them further by the type they are pointing to and loop over // Group them further by the type they are pointing to and loop over
// them. // them.
GroupIdsAndMatch<SpvOp>( GroupIdsAndMatch<spv::Op>(
src_group_by_storage_class, dst_group_by_storage_class, SpvOpMax, src_group_by_storage_class, dst_group_by_storage_class,
&Differ::GroupIdsHelperGetTypePointerTypeOp, spv::Op::Max, &Differ::GroupIdsHelperGetTypePointerTypeOp,
[this](const IdGroup& src_group_by_type_op, [this](const IdGroup& src_group_by_type_op,
const IdGroup& dst_group_by_type_op) { const IdGroup& dst_group_by_type_op) {
@ -2182,8 +2187,8 @@ void Differ::MatchTypeIds() {
MatchIds(potential_id_map, [this, flexibility]( MatchIds(potential_id_map, [this, flexibility](
const opt::Instruction* src_inst, const opt::Instruction* src_inst,
const opt::Instruction* dst_inst) { const opt::Instruction* dst_inst) {
const SpvOp src_op = src_inst->opcode(); const spv::Op src_op = src_inst->opcode();
const SpvOp dst_op = dst_inst->opcode(); const spv::Op dst_op = dst_inst->opcode();
// Don't match if the opcode is not the same. // Don't match if the opcode is not the same.
if (src_op != dst_op) { if (src_op != dst_op) {
@ -2191,26 +2196,26 @@ void Differ::MatchTypeIds() {
} }
switch (src_op) { switch (src_op) {
case SpvOpTypeVoid: case spv::Op::OpTypeVoid:
case SpvOpTypeBool: case spv::Op::OpTypeBool:
case SpvOpTypeSampler: case spv::Op::OpTypeSampler:
// void, bool and sampler are unique, match them. // void, bool and sampler are unique, match them.
return true; return true;
case SpvOpTypeInt: case spv::Op::OpTypeInt:
case SpvOpTypeFloat: case spv::Op::OpTypeFloat:
case SpvOpTypeVector: case spv::Op::OpTypeVector:
case SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
case SpvOpTypeSampledImage: case spv::Op::OpTypeSampledImage:
case SpvOpTypeRuntimeArray: case spv::Op::OpTypeRuntimeArray:
case SpvOpTypePointer: case spv::Op::OpTypePointer:
// Match these instructions when all operands match. // Match these instructions when all operands match.
assert(src_inst->NumInOperandWords() == assert(src_inst->NumInOperandWords() ==
dst_inst->NumInOperandWords()); dst_inst->NumInOperandWords());
return DoOperandsMatch(src_inst, dst_inst, 0, return DoOperandsMatch(src_inst, dst_inst, 0,
src_inst->NumInOperandWords()); src_inst->NumInOperandWords());
case SpvOpTypeFunction: case spv::Op::OpTypeFunction:
case SpvOpTypeImage: case spv::Op::OpTypeImage:
// Match function types only if they have the same number of operands, // Match function types only if they have the same number of operands,
// and they all match. // and they all match.
// Match image types similarly, expecting the optional final parameter // Match image types similarly, expecting the optional final parameter
@ -2221,7 +2226,7 @@ void Differ::MatchTypeIds() {
return DoOperandsMatch(src_inst, dst_inst, 0, return DoOperandsMatch(src_inst, dst_inst, 0,
src_inst->NumInOperandWords()); src_inst->NumInOperandWords());
case SpvOpTypeArray: case spv::Op::OpTypeArray:
// Match arrays only if the element type and length match. The length // Match arrays only if the element type and length match. The length
// is an id of a constant, so the actual constant it's defining is // is an id of a constant, so the actual constant it's defining is
// compared instead. // compared instead.
@ -2238,7 +2243,7 @@ void Differ::MatchTypeIds() {
// example if a spec contant is used). // example if a spec contant is used).
return DoOperandsMatch(src_inst, dst_inst, 1, 1); return DoOperandsMatch(src_inst, dst_inst, 1, 1);
case SpvOpTypeStruct: case spv::Op::OpTypeStruct:
return MatchOpTypeStruct(src_inst, dst_inst, flexibility); return MatchOpTypeStruct(src_inst, dst_inst, flexibility);
default: default:
@ -2270,8 +2275,8 @@ void Differ::MatchConstants() {
MatchIds(potential_id_map, [this, flexibility]( MatchIds(potential_id_map, [this, flexibility](
const opt::Instruction* src_inst, const opt::Instruction* src_inst,
const opt::Instruction* dst_inst) { const opt::Instruction* dst_inst) {
const SpvOp src_op = src_inst->opcode(); const spv::Op src_op = src_inst->opcode();
const SpvOp dst_op = dst_inst->opcode(); const spv::Op dst_op = dst_inst->opcode();
// Don't match if the opcode is not the same. // Don't match if the opcode is not the same.
if (src_op != dst_op) { if (src_op != dst_op) {
@ -2279,14 +2284,14 @@ void Differ::MatchConstants() {
} }
switch (src_op) { switch (src_op) {
case SpvOpConstantTrue: case spv::Op::OpConstantTrue:
case SpvOpConstantFalse: case spv::Op::OpConstantFalse:
// true and false are unique, match them. // true and false are unique, match them.
return true; return true;
case SpvOpConstant: case spv::Op::OpConstant:
return MatchOpConstant(src_inst, dst_inst, flexibility); return MatchOpConstant(src_inst, dst_inst, flexibility);
case SpvOpConstantComposite: case spv::Op::OpConstantComposite:
case SpvOpSpecConstantComposite: case spv::Op::OpSpecConstantComposite:
// Composite constants must match in type and value. // Composite constants must match in type and value.
// //
// TODO: match OpConstantNull with OpConstantComposite with all zeros // TODO: match OpConstantNull with OpConstantComposite with all zeros
@ -2299,7 +2304,7 @@ void Differ::MatchConstants() {
dst_inst->GetOperand(0)) && dst_inst->GetOperand(0)) &&
DoOperandsMatch(src_inst, dst_inst, 0, DoOperandsMatch(src_inst, dst_inst, 0,
src_inst->NumInOperandWords()); src_inst->NumInOperandWords());
case SpvOpConstantSampler: case spv::Op::OpConstantSampler:
// Match sampler constants exactly. // Match sampler constants exactly.
// TODO: Allow flexibility in parameters to better diff shaders where // TODO: Allow flexibility in parameters to better diff shaders where
// the sampler param has changed. // the sampler param has changed.
@ -2307,15 +2312,15 @@ void Differ::MatchConstants() {
dst_inst->NumInOperandWords()); dst_inst->NumInOperandWords());
return DoOperandsMatch(src_inst, dst_inst, 0, return DoOperandsMatch(src_inst, dst_inst, 0,
src_inst->NumInOperandWords()); src_inst->NumInOperandWords());
case SpvOpConstantNull: case spv::Op::OpConstantNull:
// Match null constants as long as the type matches. // Match null constants as long as the type matches.
return DoesOperandMatch(src_inst->GetOperand(0), return DoesOperandMatch(src_inst->GetOperand(0),
dst_inst->GetOperand(0)); dst_inst->GetOperand(0));
case SpvOpSpecConstantTrue: case spv::Op::OpSpecConstantTrue:
case SpvOpSpecConstantFalse: case spv::Op::OpSpecConstantFalse:
case SpvOpSpecConstant: case spv::Op::OpSpecConstant:
case SpvOpSpecConstantOp: case spv::Op::OpSpecConstantOp:
// Match spec constants by name if available, then by the SpecId // Match spec constants by name if available, then by the SpecId
// decoration. // decoration.
return MatchOpSpecConstant(src_inst, dst_inst); return MatchOpSpecConstant(src_inst, dst_inst);
@ -2334,7 +2339,7 @@ void Differ::MatchVariableIds() {
return inst.result_id(); return inst.result_id();
}; };
auto accept_type_ops = [](const opt::Instruction& inst) { auto accept_type_ops = [](const opt::Instruction& inst) {
return inst.opcode() == SpvOpVariable; return inst.opcode() == spv::Op::OpVariable;
}; };
PoolPotentialIds(src_->types_values(), potential_id_map.src_ids, true, PoolPotentialIds(src_->types_values(), potential_id_map.src_ids, true,
@ -2350,8 +2355,8 @@ void Differ::MatchVariableIds() {
MatchIds(potential_id_map, MatchIds(potential_id_map,
[this, flexibility](const opt::Instruction* src_inst, [this, flexibility](const opt::Instruction* src_inst,
const opt::Instruction* dst_inst) { const opt::Instruction* dst_inst) {
assert(src_inst->opcode() == SpvOpVariable); assert(src_inst->opcode() == spv::Op::OpVariable);
assert(dst_inst->opcode() == SpvOpVariable); assert(dst_inst->opcode() == spv::Op::OpVariable);
return MatchOpVariable(src_inst, dst_inst, flexibility); return MatchOpVariable(src_inst, dst_inst, flexibility);
}); });
@ -2597,7 +2602,7 @@ void Differ::ToParsedInstruction(
parsed_inst->num_words = static_cast<uint16_t>(inst_binary.size()); parsed_inst->num_words = static_cast<uint16_t>(inst_binary.size());
parsed_inst->opcode = static_cast<uint16_t>(inst.opcode()); parsed_inst->opcode = static_cast<uint16_t>(inst.opcode());
parsed_inst->ext_inst_type = parsed_inst->ext_inst_type =
inst.opcode() == SpvOpExtInst inst.opcode() == spv::Op::OpExtInst
? GetExtInstType(id_to, original_inst.GetSingleWordInOperand(0)) ? GetExtInstType(id_to, original_inst.GetSingleWordInOperand(0))
: SPV_EXT_INST_TYPE_NONE; : SPV_EXT_INST_TYPE_NONE;
parsed_inst->type_id = parsed_inst->type_id =

View File

@ -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<SpvOp>(inst.opcode); auto opcode = static_cast<spv::Op>(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 == SpvOpName) { if (comment_ && opcode == spv::Op::OpName) {
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<SpvOp>(inst.opcode); auto opcode = static_cast<spv::Op>(inst.opcode);
if (comment_ && opcode == SpvOpFunction) { if (comment_ && opcode == spv::Op::OpFunction) {
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,7 +351,7 @@ 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(SpvOp(word), &opcode_desc)) if (grammar_.lookupOpcode(spv::Op(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;

View File

@ -200,8 +200,8 @@ class EnumSet {
std::unique_ptr<OverflowSetType> overflow_ = {}; std::unique_ptr<OverflowSetType> overflow_ = {};
}; };
// A set of SpvCapability, optimized for small capability values. // A set of spv::Capability, optimized for small capability values.
using CapabilitySet = EnumSet<SpvCapability>; using CapabilitySet = EnumSet<spv::Capability>;
} // namespace spvtools } // namespace spvtools

View File

@ -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(SpvCapability capability); const char* CapabilityToString(spv::Capability capability);
} // namespace spvtools } // namespace spvtools

View File

@ -24,7 +24,9 @@
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 != SpvOpExtension) return "ERROR_not_op_extension"; if (inst->opcode != static_cast<uint16_t>(spv::Op::OpExtension)) {
return "ERROR_not_op_extension";
}
assert(inst->num_operands == 1); assert(inst->num_operands == 1);

View File

@ -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() != SpvOpVariable) { if (type_or_value.opcode() != spv::Op::OpVariable) {
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() != SpvOpVariable) { if (type_or_value.opcode() != spv::Op::OpVariable) {
continue; continue;
} }
if (replay_result.transformation_context->GetFactManager() if (replay_result.transformation_context->GetFactManager()

View File

@ -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() != SpvOpFunctionCall) { if (instruction.opcode() != spv::Op::OpFunctionCall) {
continue; continue;
} }
// Get the id of the function being called. // Get the id of the function being called.

View File

@ -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() == SpvOpConstant); assert(constant_instruction.opcode() == spv::Op::OpConstant);
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() == SpvOpConstant && assert(constant_inst->opcode() == spv::Op::OpConstant &&
"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,8 +175,9 @@ bool ConstantUniformFacts::MaybeAddFact(
return false; return false;
} }
assert(SpvOpVariable == uniform_variable->opcode()); assert(spv::Op::OpVariable == uniform_variable->opcode());
assert(SpvStorageClassUniform == uniform_variable->GetSingleWordInOperand(0)); assert(spv::StorageClass::Uniform ==
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());
@ -184,7 +185,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() !=
SpvStorageClassUniform) { spv::StorageClass::Uniform) {
return false; return false;
} }
auto should_be_uniform_pointer_instruction = auto should_be_uniform_pointer_instruction =

View File

@ -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(operation.opcode); hash.push_back(uint32_t(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,7 +104,8 @@ bool DataSynonymAndIdEquationFacts::MaybeAddFact(
} }
// Now add the fact. // Now add the fact.
AddEquationFactRecursive(lhs_dd, static_cast<SpvOp>(fact.opcode()), rhs_dds); AddEquationFactRecursive(lhs_dd, static_cast<spv::Op>(fact.opcode()),
rhs_dds);
return true; return true;
} }
@ -119,7 +120,7 @@ DataSynonymAndIdEquationFacts::GetEquations(
} }
void DataSynonymAndIdEquationFacts::AddEquationFactRecursive( void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
const protobufs::DataDescriptor& lhs_dd, SpvOp opcode, const protobufs::DataDescriptor& lhs_dd, spv::Op 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.");
@ -155,21 +156,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 SpvOpConvertSToF: case spv::Op::OpConvertSToF:
case SpvOpConvertUToF: case spv::Op::OpConvertUToF:
ComputeConversionDataSynonymFacts(*rhs_dds[0]); ComputeConversionDataSynonymFacts(*rhs_dds[0]);
break; break;
case SpvOpBitcast: { case spv::Op::OpBitcast: {
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 SpvOpIAdd: { case spv::Op::OpIAdd: {
// 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 == SpvOpISub) { if (equation.opcode == spv::Op::OpISub) {
// 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"
@ -179,7 +180,7 @@ void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
} }
} }
for (const auto& equation : GetEquations(rhs_dds[1])) { for (const auto& equation : GetEquations(rhs_dds[1])) {
if (equation.opcode == SpvOpISub) { if (equation.opcode == spv::Op::OpISub) {
// 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)"
@ -190,10 +191,10 @@ void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
} }
break; break;
} }
case SpvOpISub: { case spv::Op::OpISub: {
// 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 == SpvOpIAdd) { if (equation.opcode == spv::Op::OpIAdd) {
// 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"
@ -207,34 +208,34 @@ void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
} }
} }
if (equation.opcode == SpvOpISub) { if (equation.opcode == spv::Op::OpISub) {
// 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, SpvOpSNegate, AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
{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 == SpvOpIAdd) { if (equation.opcode == spv::Op::OpIAdd) {
// 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, SpvOpSNegate, AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
{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, SpvOpSNegate, AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
{equation.operands[0]}); {equation.operands[0]});
} }
} }
if (equation.opcode == SpvOpISub) { if (equation.opcode == spv::Op::OpISub) {
// 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)"
@ -245,8 +246,8 @@ void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
} }
break; break;
} }
case SpvOpLogicalNot: case spv::Op::OpLogicalNot:
case SpvOpSNegate: { case spv::Op::OpSNegate: {
// 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) {
@ -321,9 +322,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 == SpvOpConvertSToF) { if (equation.opcode == spv::Op::OpConvertSToF) {
convert_s_to_f_lhs.push_back(*dd_it); convert_s_to_f_lhs.push_back(*dd_it);
} else if (equation.opcode == SpvOpConvertUToF) { } else if (equation.opcode == spv::Op::OpConvertUToF) {
convert_u_to_f_lhs.push_back(*dd_it); convert_u_to_f_lhs.push_back(*dd_it);
} }
} }
@ -808,9 +809,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() ==
SpvOpTypeVoid || spv::Op::OpTypeVoid ||
ir_context_->get_def_use_mgr()->GetDef(end_type_id_2)->opcode() == ir_context_->get_def_use_mgr()->GetDef(end_type_id_2)->opcode() ==
SpvOpTypeVoid) { spv::Op::OpTypeVoid) {
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.

View File

@ -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 {
SpvOp opcode; spv::Op 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, SpvOp opcode, const protobufs::DataDescriptor& lhs_dd, spv::Op 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.

View File

@ -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 << " " << static_cast<SpvOp>(fact.opcode()); stream << " " << 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, SpvOp opcode, void FactManager::AddFactIdEquation(uint32_t lhs_id, spv::Op 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(opcode); fact.set_opcode(uint32_t(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);
} }

View File

@ -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, SpvOp opcode, void AddFactIdEquation(uint32_t lhs_id, spv::Op 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

View File

@ -36,8 +36,9 @@ 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() == SpvOpCapability); assert(capability.opcode() == spv::Op::OpCapability);
if (capability.GetSingleWordInOperand(0) == SpvCapabilityShader) { if (spv::Capability(capability.GetSingleWordInOperand(0)) ==
spv::Capability::Shader) {
found_capability_shader = true; found_capability_shader = true;
break; break;
} }
@ -51,7 +52,8 @@ 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 (entry_point.GetSingleWordInOperand(0) == SpvExecutionModelFragment) { if (spv::ExecutionModel(entry_point.GetSingleWordInOperand(0)) ==
spv::ExecutionModel::Fragment) {
fragment_entry_point = &entry_point; fragment_entry_point = &entry_point;
break; break;
} }
@ -81,8 +83,9 @@ 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() == SpvOpVariable && if (inst.opcode() == spv::Op::OpVariable &&
inst.GetSingleWordInOperand(0) == SpvStorageClassOutput) { spv::StorageClass(inst.GetSingleWordInOperand(0)) ==
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; "
@ -144,10 +147,11 @@ 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(constant_id, MakeIdUseDescriptor(
MakeInstructionDescriptor(greater_than_instruction, constant_id,
SpvOpFOrdGreaterThan, 0), MakeInstructionDescriptor(greater_than_instruction,
in_operand_index), spv::Op::OpFOrdGreaterThan, 0),
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());
} }
@ -204,20 +208,21 @@ 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>(ir_context.get(), SpvOpLabel, 0, auto label = MakeUnique<opt::Instruction>(
new_exit_block_id, ir_context.get(), spv::Op::OpLabel, 0, 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(MakeUnique<opt::Instruction>( new_exit_block->AddInstruction(
ir_context.get(), SpvOpReturn, 0, 0, opt::Instruction::OperandList())); MakeUnique<opt::Instruction>(ir_context.get(), spv::Op::OpReturn, 0, 0,
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>(ir_context.get(), SpvOpLabel, 0, auto label = MakeUnique<opt::Instruction>(
ir_context->TakeNextId(), ir_context.get(), spv::Op::OpLabel, 0, 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
@ -229,7 +234,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(), SpvOpCompositeConstruct, vec4_id, ir_context.get(), spv::Op::OpCompositeConstruct, 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));
@ -241,7 +246,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(), SpvOpStore, 0, 0, op_store_operands)); ir_context.get(), spv::Op::OpStore, 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
@ -313,7 +318,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(), SpvOpFOrdGreaterThan, ir_context.get(), spv::Op::OpFOrdGreaterThan,
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));
@ -344,9 +349,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( new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
MakeUnique<opt::Instruction>(ir_context.get(), SpvOpBranchConditional, ir_context.get(), spv::Op::OpBranchConditional, 0, 0,
0, 0, op_branch_conditional_operands)); 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());

View File

@ -131,14 +131,15 @@ 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, SpvOp, uint32_t>> base_opcode_skip_triples; std::vector<std::tuple<uint32_t, spv::Op, uint32_t>>
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<SpvOp, uint32_t> skip_count; std::map<spv::Op, 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
@ -151,7 +152,7 @@ void FuzzerPass::ForEachInstructionWithInstructionDescriptor(
base = inst_it->result_id(); base = inst_it->result_id();
skip_count.clear(); skip_count.clear();
} }
const SpvOp opcode = inst_it->opcode(); const spv::Op 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,
@ -330,7 +331,7 @@ uint32_t FuzzerPass::FindOrCreateStructType(
} }
uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id, uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id,
SpvStorageClass storage_class) { spv::StorageClass 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(
@ -345,7 +346,7 @@ uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id,
} }
uint32_t FuzzerPass::FindOrCreatePointerToIntegerType( uint32_t FuzzerPass::FindOrCreatePointerToIntegerType(
uint32_t width, bool is_signed, SpvStorageClass storage_class) { uint32_t width, bool is_signed, spv::StorageClass storage_class) {
return FindOrCreatePointerType(FindOrCreateIntegerType(width, is_signed), return FindOrCreatePointerType(FindOrCreateIntegerType(width, is_signed),
storage_class); storage_class);
} }
@ -432,7 +433,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() == SpvOpUndef && inst.type_id() == type_id) { if (inst.opcode() == spv::Op::OpUndef && inst.type_id() == type_id) {
return inst.result_id(); return inst.result_id();
} }
} }
@ -464,7 +465,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(
SpvStorageClass storage_class) const { spv::StorageClass 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;
@ -480,23 +481,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 SpvOpTypeBool: case spv::Op::OpTypeBool:
case SpvOpTypeFloat: case spv::Op::OpTypeFloat:
case SpvOpTypeInt: case spv::Op::OpTypeInt:
case SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
case SpvOpTypeVector: case spv::Op::OpTypeVector:
// 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 SpvOpTypeArray: case spv::Op::OpTypeArray:
// 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 SpvOpTypeStruct: { case spv::Op::OpTypeStruct: {
// 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(),
@ -515,11 +516,12 @@ FuzzerPass::GetAvailableBasicTypesAndPointers(
} }
break; break;
} }
case SpvOpTypePointer: { case spv::Op::OpTypePointer: {
// 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 (inst.GetSingleWordInOperand(0) == storage_class && if (spv::StorageClass(inst.GetSingleWordInOperand(0)) ==
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
@ -541,22 +543,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 SpvOpTypeBool: case spv::Op::OpTypeBool:
return FindOrCreateBoolConstant(false, is_irrelevant); return FindOrCreateBoolConstant(false, is_irrelevant);
case SpvOpTypeFloat: { case spv::Op::OpTypeFloat: {
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 SpvOpTypeInt: { case spv::Op::OpTypeInt: {
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 SpvOpTypeArray: { case spv::Op::OpTypeArray: {
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());
@ -566,8 +568,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 SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
case SpvOpTypeVector: { case spv::Op::OpTypeVector: {
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(
@ -576,7 +578,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 SpvOpTypeStruct: { case spv::Op::OpTypeStruct: {
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 "
@ -646,7 +648,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() == SpvOpBranch && if (maybe_preheader->terminator()->opcode() == spv::Op::OpBranch &&
!maybe_preheader->IsLoopHeader()) { !maybe_preheader->IsLoopHeader()) {
return maybe_preheader; return maybe_preheader;
} }
@ -683,8 +685,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() == SpvOpPhi || while (non_phi_or_var_inst->opcode() == spv::Op::OpPhi ||
non_phi_or_var_inst->opcode() == SpvOpVariable) { non_phi_or_var_inst->opcode() == spv::Op::OpVariable) {
non_phi_or_var_inst = non_phi_or_var_inst->NextNode(); non_phi_or_var_inst = non_phi_or_var_inst->NextNode();
} }
@ -706,7 +708,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() ==
SpvStorageClassFunction && spv::StorageClass::Function &&
"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);
@ -715,7 +717,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() != SpvOpVariable) { if (instruction.opcode() != spv::Op::OpVariable) {
continue; continue;
} }
// The existing OpVariable must have type |pointer_type_id|. // The existing OpVariable must have type |pointer_type_id|.
@ -749,15 +751,16 @@ 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() == SpvStorageClassPrivate || (pointer_type->AsPointer()->storage_class() ==
spv::StorageClass::Private ||
pointer_type->AsPointer()->storage_class() == pointer_type->AsPointer()->storage_class() ==
SpvStorageClassWorkgroup) && spv::StorageClass::Workgroup) &&
"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() != SpvOpVariable) { if (instruction.opcode() != spv::Op::OpVariable) {
continue; continue;
} }
// The existing OpVariable must have type |pointer_type_id|. // The existing OpVariable must have type |pointer_type_id|.
@ -781,13 +784,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 == SpvStorageClassWorkgroup) { if (storage_class == spv::StorageClass::Workgroup) {
ApplyTransformation(TransformationAddGlobalVariable( ApplyTransformation(TransformationAddGlobalVariable(
result_id, pointer_type_id, SpvStorageClassWorkgroup, 0, result_id, pointer_type_id, spv::StorageClass::Workgroup, 0,
pointee_value_is_irrelevant)); pointee_value_is_irrelevant));
} else { } else {
ApplyTransformation(TransformationAddGlobalVariable( ApplyTransformation(TransformationAddGlobalVariable(
result_id, pointer_type_id, SpvStorageClassPrivate, result_id, pointer_type_id, spv::StorageClass::Private,
FindOrCreateZeroConstant(pointee_type_id, pointee_value_is_irrelevant), FindOrCreateZeroConstant(pointee_type_id, pointee_value_is_irrelevant),
pointee_value_is_irrelevant)); pointee_value_is_irrelevant));
} }

View File

@ -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,
SpvStorageClass storage_class); spv::StorageClass 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,
SpvStorageClass storage_class); spv::StorageClass 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(SpvStorageClass storage_class) const; GetAvailableBasicTypesAndPointers(spv::StorageClass 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

View File

@ -34,15 +34,16 @@ 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(inst_it->opcode() == assert(
instruction_descriptor.target_instruction_opcode() && inst_it->opcode() ==
"The opcode of the instruction we might insert before must be " spv::Op(instruction_descriptor.target_instruction_opcode()) &&
"the same as the opcode in the descriptor for the instruction"); "The opcode of the instruction we might insert before must be "
"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(SpvOpAccessChain, if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
inst_it)) { spv::Op::OpAccessChain, inst_it)) {
return; return;
} }
@ -64,8 +65,8 @@ void FuzzerPassAddAccessChains::Apply() {
return false; return false;
} }
switch (instruction->opcode()) { switch (instruction->opcode()) {
case SpvOpConstantNull: case spv::Op::OpConstantNull:
case SpvOpUndef: case spv::Op::OpUndef:
// 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
@ -78,7 +79,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() == SpvOpTypePointer; ->opcode() == spv::Op::OpTypePointer;
}); });
// At this point, |relevant_instructions| contains all the pointers // At this point, |relevant_instructions| contains all the pointers
@ -112,14 +113,14 @@ void FuzzerPassAddAccessChains::Apply() {
} }
uint32_t bound; uint32_t bound;
switch (subobject_type->opcode()) { switch (subobject_type->opcode()) {
case SpvOpTypeArray: case spv::Op::OpTypeArray:
bound = fuzzerutil::GetArraySize(*subobject_type, GetIRContext()); bound = fuzzerutil::GetArraySize(*subobject_type, GetIRContext());
break; break;
case SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
case SpvOpTypeVector: case spv::Op::OpTypeVector:
bound = subobject_type->GetSingleWordInOperand(1); bound = subobject_type->GetSingleWordInOperand(1);
break; break;
case SpvOpTypeStruct: case spv::Op::OpTypeStruct:
bound = fuzzerutil::GetNumberOfStructMembers(*subobject_type); bound = fuzzerutil::GetNumberOfStructMembers(*subobject_type);
break; break;
default: default:
@ -140,9 +141,9 @@ void FuzzerPassAddAccessChains::Apply() {
GetFuzzerContext()->GetRandomIndexForAccessChain(bound); GetFuzzerContext()->GetRandomIndexForAccessChain(bound);
switch (subobject_type->opcode()) { switch (subobject_type->opcode()) {
case SpvOpTypeArray: case spv::Op::OpTypeArray:
case SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
case SpvOpTypeVector: { case spv::Op::OpTypeVector: {
// The index will be clamped // The index will be clamped
bool is_signed = GetFuzzerContext()->ChooseEven(); bool is_signed = GetFuzzerContext()->ChooseEven();
@ -164,7 +165,7 @@ void FuzzerPassAddAccessChains::Apply() {
subobject_type_id = subobject_type->GetSingleWordInOperand(0); subobject_type_id = subobject_type->GetSingleWordInOperand(0);
} break; } break;
case SpvOpTypeStruct: case spv::Op::OpTypeStruct:
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 =
@ -178,7 +179,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<SpvStorageClass>( static_cast<spv::StorageClass>(
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(

View File

@ -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(SpvOpCompositeExtract, if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
inst_it)) { spv::Op::OpCompositeExtract, 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 SpvOpTypeArray: case spv::Op::OpTypeArray:
number_of_members = number_of_members =
fuzzerutil::GetArraySize(*type_inst, GetIRContext()); fuzzerutil::GetArraySize(*type_inst, GetIRContext());
break; break;
case SpvOpTypeVector: case spv::Op::OpTypeVector:
case SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
number_of_members = type_inst->GetSingleWordInOperand(1); number_of_members = type_inst->GetSingleWordInOperand(1);
break; break;
case SpvOpTypeStruct: case spv::Op::OpTypeStruct:
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 SpvOpTypeArray: case spv::Op::OpTypeArray:
case SpvOpTypeVector: case spv::Op::OpTypeVector:
case SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
type_id = type_inst->GetSingleWordInOperand(0); type_id = type_inst->GetSingleWordInOperand(0);
break; break;
case SpvOpTypeStruct: case spv::Op::OpTypeStruct:
type_id = type_inst->GetSingleWordInOperand(indices.back()); type_id = type_inst->GetSingleWordInOperand(indices.back());
break; break;
default: default:

View File

@ -36,10 +36,11 @@ 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(instruction_iterator->opcode() == assert(
instruction_descriptor.target_instruction_opcode() && instruction_iterator->opcode() ==
"The opcode of the instruction we might insert before must be " spv::Op(instruction_descriptor.target_instruction_opcode()) &&
"the same as the opcode in the descriptor for the instruction"); "The opcode of the instruction we might insert before must be "
"the same as the opcode in the descriptor for the instruction");
// Randomly decide whether to try adding an OpCompositeInsert // Randomly decide whether to try adding an OpCompositeInsert
// instruction. // instruction.
@ -51,7 +52,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(
SpvOpCompositeInsert, instruction_iterator)) { spv::Op::OpCompositeInsert, instruction_iterator)) {
return; return;
} }

View File

@ -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 SpvOpTypeArray: case spv::Op::OpTypeArray:
case SpvOpTypeBool: case spv::Op::OpTypeBool:
case SpvOpTypeFloat: case spv::Op::OpTypeFloat:
case SpvOpTypeInt: case spv::Op::OpTypeInt:
case SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
case SpvOpTypeVector: case spv::Op::OpTypeVector:
candidates.push_back(inst.result_id()); candidates.push_back(inst.result_id());
break; break;
case SpvOpTypeStruct: { case spv::Op::OpTypeStruct: {
if (!fuzzerutil::MembersHaveBuiltInDecoration(GetIRContext(), if (!fuzzerutil::MembersHaveBuiltInDecoration(GetIRContext(),
inst.result_id()) && inst.result_id()) &&
!fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(), !fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),

View File

@ -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(SpvOpCopyMemory, if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpCopyMemory,
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()
? SpvStorageClassPrivate ? spv::StorageClass::Private
: SpvStorageClassFunction; : spv::StorageClass::Function;
auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType( auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
GetIRContext(), inst->type_id()); GetIRContext(), inst->type_id());

View File

@ -29,12 +29,14 @@ 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(
SpvCapabilityFloat64) && spv::Capability::Float64) &&
ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt64); ir_context->get_feature_mgr()->HasCapability(
spv::Capability::Int64);
case 16: case 16:
return ir_context->get_feature_mgr()->HasCapability( return ir_context->get_feature_mgr()->HasCapability(
SpvCapabilityFloat16) && spv::Capability::Float16) &&
ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt16); ir_context->get_feature_mgr()->HasCapability(
spv::Capability::Int16);
default: default:
return false; return false;
} }
@ -66,7 +68,8 @@ 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(SpvOpIAdd, inst_it)) { if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpIAdd,
inst_it)) {
return; return;
} }
@ -78,7 +81,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() != SpvOpUndef && instruction->opcode() != spv::Op::OpUndef &&
!GetTransformationContext() !GetTransformationContext()
->GetFactManager() ->GetFactManager()
->IdIsIrrelevant(instruction->result_id()); ->IdIsIrrelevant(instruction->result_id());
@ -86,15 +89,16 @@ 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<SpvOp> candidate_opcodes = { std::vector<spv::Op> candidate_opcodes = {
SpvOpIAdd, SpvOpISub, SpvOpLogicalNot, SpvOpSNegate, spv::Op::OpIAdd, spv::Op::OpISub, spv::Op::OpLogicalNot,
SpvOpConvertUToF, SpvOpConvertSToF, SpvOpBitcast}; spv::Op::OpSNegate, spv::Op::OpConvertUToF, spv::Op::OpConvertSToF,
spv::Op::OpBitcast};
do { do {
auto opcode = auto opcode =
GetFuzzerContext()->RemoveAtRandomIndex(&candidate_opcodes); GetFuzzerContext()->RemoveAtRandomIndex(&candidate_opcodes);
switch (opcode) { switch (opcode) {
case SpvOpConvertSToF: case spv::Op::OpConvertSToF:
case SpvOpConvertUToF: { case spv::Op::OpConvertUToF: {
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)) {
@ -144,7 +148,7 @@ void FuzzerPassAddEquationInstructions::Apply() {
{operand->result_id()}, instruction_descriptor)); {operand->result_id()}, instruction_descriptor));
return; return;
} }
case SpvOpBitcast: { case spv::Op::OpBitcast: {
const auto candidate_instructions = const auto candidate_instructions =
GetNumericalInstructions(available_instructions); GetNumericalInstructions(available_instructions);
@ -197,8 +201,8 @@ void FuzzerPassAddEquationInstructions::Apply() {
return; return;
} }
} break; } break;
case SpvOpIAdd: case spv::Op::OpIAdd:
case SpvOpISub: { case spv::Op::OpISub: {
// 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 =
@ -251,7 +255,7 @@ void FuzzerPassAddEquationInstructions::Apply() {
} }
break; break;
} }
case SpvOpLogicalNot: { case spv::Op::OpLogicalNot: {
// 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 =
@ -268,7 +272,7 @@ void FuzzerPassAddEquationInstructions::Apply() {
} }
break; break;
} }
case SpvOpSNegate: { case spv::Op::OpSNegate: {
// 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);

View File

@ -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(SpvOpFunctionCall, if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
inst_it)) { spv::Op::OpFunctionCall, 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() != SpvOpVariable || if (inst->opcode() != spv::Op::OpVariable ||
inst->opcode() != SpvOpFunctionParameter) { inst->opcode() != spv::Op::OpFunctionParameter) {
// 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 == SpvStorageClassFunction) { if (storage_class == spv::StorageClass::Function) {
// 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 == SpvStorageClassPrivate || assert((storage_class == spv::StorageClass::Private ||
storage_class == SpvStorageClassWorkgroup) && storage_class == spv::StorageClass::Workgroup) &&
"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 == SpvStorageClassPrivate storage_class == spv::StorageClass::Private
? FindOrCreateZeroConstant(pointee_type_id, false) ? FindOrCreateZeroConstant(pointee_type_id, false)
: 0, : 0,
true)); true));

View File

@ -29,16 +29,17 @@ FuzzerPassAddGlobalVariables::FuzzerPassAddGlobalVariables(
transformations, ignore_inapplicable_transformations) {} transformations, ignore_inapplicable_transformations) {}
void FuzzerPassAddGlobalVariables::Apply() { void FuzzerPassAddGlobalVariables::Apply() {
SpvStorageClass variable_storage_class = SpvStorageClassPrivate; spv::StorageClass variable_storage_class = spv::StorageClass::Private;
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 (entry_point.GetSingleWordInOperand(0) == SpvExecutionModelGLCompute) { if (spv::ExecutionModel(entry_point.GetSingleWordInOperand(0)) ==
spv::ExecutionModel::GLCompute) {
variable_storage_class = variable_storage_class =
GetFuzzerContext()->ChoosePercentage( GetFuzzerContext()->ChoosePercentage(
GetFuzzerContext()->GetChanceOfChoosingWorkgroupStorageClass()) GetFuzzerContext()->GetChanceOfChoosingWorkgroupStorageClass())
? SpvStorageClassWorkgroup ? spv::StorageClass::Workgroup
: SpvStorageClassPrivate; : spv::StorageClass::Private;
break; break;
} }
} }
@ -87,7 +88,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 == SpvStorageClassPrivate variable_storage_class == spv::StorageClass::Private
? FindOrCreateZeroConstant(basic_type, false) ? FindOrCreateZeroConstant(basic_type, false)
: 0, : 0,
true)); true));

View File

@ -34,10 +34,11 @@ 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(inst_it->opcode() == assert(
instruction_descriptor.target_instruction_opcode() && inst_it->opcode() ==
"The opcode of the instruction we might insert before must be " spv::Op(instruction_descriptor.target_instruction_opcode()) &&
"the same as the opcode in the descriptor for the instruction"); "The opcode of the instruction we might insert before must be "
"the same as the opcode in the descriptor for the instruction");
// Randomly decide whether to try inserting a load here. // Randomly decide whether to try inserting a load here.
if (!GetFuzzerContext()->ChoosePercentage( if (!GetFuzzerContext()->ChoosePercentage(
@ -47,10 +48,11 @@ 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(SpvOpLoad, inst_it)) { if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
inst_it)) {
return; return;
} }
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAtomicLoad, if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpAtomicLoad,
inst_it)) { inst_it)) {
return; return;
} }
@ -64,8 +66,8 @@ void FuzzerPassAddLoads::Apply() {
return false; return false;
} }
switch (instruction->opcode()) { switch (instruction->opcode()) {
case SpvOpConstantNull: case spv::Op::OpConstantNull:
case SpvOpUndef: case spv::Op::OpUndef:
// 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.
@ -75,7 +77,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() == SpvOpTypePointer; ->opcode() == spv::Op::OpTypePointer;
}); });
// At this point, |relevant_instructions| contains all the pointers // At this point, |relevant_instructions| contains all the pointers
@ -92,25 +94,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<SpvStorageClass>( auto storage_class = static_cast<spv::StorageClass>(
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 SpvStorageClassStorageBuffer: case spv::StorageClass::StorageBuffer:
case SpvStorageClassPhysicalStorageBuffer: case spv::StorageClass::PhysicalStorageBuffer:
case SpvStorageClassWorkgroup: case spv::StorageClass::Workgroup:
case SpvStorageClassCrossWorkgroup: case spv::StorageClass::CrossWorkgroup:
case SpvStorageClassAtomicCounter: case spv::StorageClass::AtomicCounter:
case SpvStorageClassImage: case spv::StorageClass::Image:
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(
{SpvScopeInvocation}, {uint32_t(spv::Scope::Invocation)},
FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()), FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()),
false); false);

View File

@ -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(SpvStorageClassFunction); GetAvailableBasicTypesAndPointers(spv::StorageClass::Function);
// 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, SpvStorageClassFunction, basic_type)); pointer_type, spv::StorageClass::Function, 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.

View File

@ -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() == SpvOpFunction || if (pair.second->opcode() == spv::Op::OpFunction ||
pair.second->opcode() == SpvOpUndef) { pair.second->opcode() == spv::Op::OpUndef) {
continue; continue;
} }

View File

@ -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 SpvStorageClassFunction: { case spv::StorageClass::Function: {
// 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 SpvStorageClassPrivate: case spv::StorageClass::Private:
case SpvStorageClassWorkgroup: { case spv::StorageClass::Workgroup: {
// 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 =

View File

@ -34,10 +34,11 @@ 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(inst_it->opcode() == assert(
instruction_descriptor.target_instruction_opcode() && inst_it->opcode() ==
"The opcode of the instruction we might insert before must be " spv::Op(instruction_descriptor.target_instruction_opcode()) &&
"the same as the opcode in the descriptor for the instruction"); "The opcode of the instruction we might insert before must be "
"the same as the opcode in the descriptor for the instruction");
// Randomly decide whether to try inserting a store here. // Randomly decide whether to try inserting a store here.
if (!GetFuzzerContext()->ChoosePercentage( if (!GetFuzzerContext()->ChoosePercentage(
@ -47,12 +48,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(SpvOpStore, if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpStore,
inst_it)) { inst_it)) {
return; return;
} }
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAtomicStore, if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
inst_it)) { spv::Op::OpAtomicStore, inst_it)) {
return; return;
} }
@ -67,7 +68,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() != SpvOpTypePointer) { if (type_inst->opcode() != spv::Op::OpTypePointer) {
// Not a pointer. // Not a pointer.
return false; return false;
} }
@ -76,8 +77,8 @@ void FuzzerPassAddStores::Apply() {
return false; return false;
} }
switch (instruction->opcode()) { switch (instruction->opcode()) {
case SpvOpConstantNull: case spv::Op::OpConstantNull:
case SpvOpUndef: case spv::Op::OpUndef:
// 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.
@ -126,24 +127,24 @@ void FuzzerPassAddStores::Apply() {
uint32_t memory_semantics_id = 0; uint32_t memory_semantics_id = 0;
auto storage_class = auto storage_class =
static_cast<SpvStorageClass>(GetIRContext() static_cast<spv::StorageClass>(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 SpvStorageClassStorageBuffer: case spv::StorageClass::StorageBuffer:
case SpvStorageClassPhysicalStorageBuffer: case spv::StorageClass::PhysicalStorageBuffer:
case SpvStorageClassWorkgroup: case spv::StorageClass::Workgroup:
case SpvStorageClassCrossWorkgroup: case spv::StorageClass::CrossWorkgroup:
case SpvStorageClassAtomicCounter: case spv::StorageClass::AtomicCounter:
case SpvStorageClassImage: case spv::StorageClass::Image:
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(
{SpvScopeInvocation}, {uint32_t(spv::Scope::Invocation)},
FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()), FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()),
false); false);

View File

@ -44,7 +44,8 @@ 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(SpvOpIAdd, inst_it)) { if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpIAdd,
inst_it)) {
return; return;
} }

View File

@ -35,10 +35,11 @@ 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(instruction_iterator->opcode() == assert(
instruction_descriptor.target_instruction_opcode() && instruction_iterator->opcode() ==
"The opcode of the instruction we might insert before must be " spv::Op(instruction_descriptor.target_instruction_opcode()) &&
"the same as the opcode in the descriptor for the instruction"); "The opcode of the instruction we might insert before must be "
"the same as the opcode in the descriptor for the instruction");
// Randomly decide whether to try adding an OpVectorShuffle instruction. // Randomly decide whether to try adding an OpVectorShuffle instruction.
if (!GetFuzzerContext()->ChoosePercentage( if (!GetFuzzerContext()->ChoosePercentage(
@ -49,7 +50,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(
SpvOpVectorShuffle, instruction_iterator)) { spv::Op::OpVectorShuffle, instruction_iterator)) {
return; return;
} }

View File

@ -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() == SpvOpBranchConditional && if (instruction->opcode() == spv::Op::OpBranchConditional &&
GetFuzzerContext()->ChoosePercentage( GetFuzzerContext()->ChoosePercentage(
GetFuzzerContext()->GetChanceOfAdjustingBranchWeights())) { GetFuzzerContext()->GetChanceOfAdjustingBranchWeights())) {
ApplyTransformation(TransformationAdjustBranchWeights( ApplyTransformation(TransformationAdjustBranchWeights(

View File

@ -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<uint32_t> basic_function_control_masks = { std::vector<spv::FunctionControlMask> basic_function_control_masks = {
SpvFunctionControlMaskNone, SpvFunctionControlInlineMask, spv::FunctionControlMask::MaskNone, spv::FunctionControlMask::Inline,
SpvFunctionControlDontInlineMask}; spv::FunctionControlMask::DontInline};
uint32_t new_function_control_mask = uint32_t new_function_control_mask =
basic_function_control_masks[GetFuzzerContext()->RandomIndex( uint32_t(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 :
{SpvFunctionControlPureMask, SpvFunctionControlConstMask}) { {spv::FunctionControlMask::Pure, spv::FunctionControlMask::Const}) {
if ((existing_function_control_mask & mask_bit) && if ((existing_function_control_mask & uint32_t(mask_bit)) &&
GetFuzzerContext()->ChooseEven()) { GetFuzzerContext()->ChooseEven()) {
new_function_control_mask |= mask_bit; new_function_control_mask |= uint32_t(mask_bit);
} }
} }

View File

@ -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() != SpvOpLoopMerge) { if (merge_inst->opcode() != spv::Op::OpLoopMerge) {
continue; continue;
} }
@ -48,9 +48,10 @@ 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 = {SpvLoopControlMaskNone, std::vector<uint32_t> basic_masks = {
SpvLoopControlUnrollMask, uint32_t(spv::LoopControlMask::MaskNone),
SpvLoopControlDontUnrollMask}; uint32_t(spv::LoopControlMask::Unroll),
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)];
@ -58,19 +59,20 @@ 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 : for (auto mask_bit : {spv::LoopControlMask::DependencyInfinite,
{SpvLoopControlDependencyInfiniteMask, spv::LoopControlMask::DependencyLength,
SpvLoopControlDependencyLengthMask, spv::LoopControlMask::MinIterations,
SpvLoopControlMinIterationsMask, SpvLoopControlMaxIterationsMask, spv::LoopControlMask::MaxIterations,
SpvLoopControlIterationMultipleMask}) { spv::LoopControlMask::IterationMultiple}) {
if ((existing_mask & mask_bit) && GetFuzzerContext()->ChooseEven()) { if ((existing_mask & uint32_t(mask_bit)) &&
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 |= mask_bit; new_mask |= uint32_t(mask_bit);
} }
} }
@ -81,14 +83,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 & SpvLoopControlDontUnrollMask)) { if (!(new_mask & uint32_t(spv::LoopControlMask::DontUnroll))) {
// 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 |= SpvLoopControlPeelCountMask; new_mask |= uint32_t(spv::LoopControlMask::PeelCount);
// 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();
@ -97,7 +99,7 @@ void FuzzerPassAdjustLoopControls::Apply() {
if (TransformationSetLoopControl::PartialCountIsSupported( if (TransformationSetLoopControl::PartialCountIsSupported(
GetIRContext()) && GetIRContext()) &&
GetFuzzerContext()->ChooseEven()) { GetFuzzerContext()->ChooseEven()) {
new_mask |= SpvLoopControlPartialCountMask; new_mask |= uint32_t(spv::LoopControlMask::PartialCount);
partial_count = partial_count =
GetFuzzerContext()->GetRandomLoopControlPartialCount(); GetFuzzerContext()->GetRandomLoopControlPartialCount();
} }

View File

@ -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 SpvOpCopyMemory: case spv::Op::OpCopyMemory:
case SpvOpCopyMemorySized: case spv::Op::OpCopyMemorySized:
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,24 +75,26 @@ 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>(SpvMemoryAccessMaskNone); : static_cast<uint32_t>(spv::MemoryAccessMask::MaskNone);
// 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 = !(existing_mask & SpvMemoryAccessVolatileMask) && bool add_volatile =
GetFuzzerContext()->ChooseEven(); !(existing_mask & uint32_t(spv::MemoryAccessMask::Volatile)) &&
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 | (add_volatile ? SpvMemoryAccessVolatileMask (existing_mask |
: SpvMemoryAccessMaskNone)) ^ (add_volatile ? uint32_t(spv::MemoryAccessMask::Volatile)
(toggle_nontemporal ? SpvMemoryAccessNontemporalMask : uint32_t(spv::MemoryAccessMask::MaskNone))) ^
: SpvMemoryAccessMaskNone); (toggle_nontemporal ? uint32_t(spv::MemoryAccessMask::Nontemporal)
: 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);

View File

@ -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() != SpvOpSelectionMerge) { if (merge_inst->opcode() != spv::Op::OpSelectionMerge) {
continue; continue;
} }
@ -48,13 +48,14 @@ 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 : for (auto control : {spv::SelectionControlMask::MaskNone,
{SpvSelectionControlMaskNone, SpvSelectionControlFlattenMask, spv::SelectionControlMask::Flatten,
SpvSelectionControlDontFlattenMask}) { spv::SelectionControlMask::DontFlatten}) {
if (control == merge_inst->GetSingleWordOperand(1)) { if (control ==
spv::SelectionControlMask(merge_inst->GetSingleWordOperand(1))) {
continue; continue;
} }
choices.push_back(control); choices.push_back(uint32_t(control));
} }
// Apply the transformation and add it to the output transformation // Apply the transformation and add it to the output transformation

View File

@ -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(SpvOpCompositeExtract, !fuzzerutil::CanInsertOpcodeBeforeInstruction(
use_inst) && spv::Op::OpCompositeExtract, use_inst) &&
use_inst->opcode() != SpvOpPhi) { use_inst->opcode() != spv::Op::OpPhi) {
// 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() != SpvOpPhi) { if (use_inst->opcode() != spv::Op::OpPhi) {
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(
SpvOp opcode, uint32_t use_in_operand_index, spv::Op 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 =

View File

@ -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(SpvOp opcode, bool DataDescriptorsHaveCompatibleTypes(spv::Op 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);

View File

@ -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(
SpvOpCompositeConstruct, inst_it)) { spv::Op::OpCompositeConstruct, 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 SpvOpTypeArray: case spv::Op::OpTypeArray:
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 SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
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 SpvOpTypeStruct: case spv::Op::OpTypeStruct:
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 SpvOpTypeVector: case spv::Op::OpTypeVector:
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() == SpvOpTypeArray && assert(array_type_instruction.opcode() == spv::Op::OpTypeArray &&
"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() == SpvOpTypeMatrix && assert(matrix_type_instruction.opcode() == spv::Op::OpTypeMatrix &&
"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() == SpvOpTypeStruct && assert(struct_type_instruction.opcode() == spv::Op::OpTypeStruct &&
"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() == SpvOpTypeVector && assert(vector_type_instruction.opcode() == spv::Op::OpTypeVector &&
"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,

View File

@ -35,10 +35,11 @@ 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(inst_it->opcode() == assert(
instruction_descriptor.target_instruction_opcode() && inst_it->opcode() ==
"The opcode of the instruction we might insert before must be " spv::Op(instruction_descriptor.target_instruction_opcode()) &&
"the same as the opcode in the descriptor for the instruction"); "The opcode of the instruction we might insert before must be "
"the same as the opcode in the descriptor for the instruction");
if (GetTransformationContext()->GetFactManager()->BlockIsDead( if (GetTransformationContext()->GetFactManager()->BlockIsDead(
block->id())) { block->id())) {
@ -48,7 +49,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(SpvOpCopyObject, if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpCopyObject,
inst_it)) { inst_it)) {
return; return;
} }

View File

@ -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<SpvCapability>(capability_inst.GetSingleWordInOperand(0)); static_cast<spv::Capability>(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.
} }
SpvStorageClass FuzzerPassDonateModules::AdaptStorageClass( spv::StorageClass FuzzerPassDonateModules::AdaptStorageClass(
SpvStorageClass donor_storage_class) { spv::StorageClass donor_storage_class) {
switch (donor_storage_class) { switch (donor_storage_class) {
case SpvStorageClassFunction: case spv::StorageClass::Function:
case SpvStorageClassPrivate: case spv::StorageClass::Private:
case SpvStorageClassWorkgroup: case spv::StorageClass::Workgroup:
// We leave these alone // We leave these alone
return donor_storage_class; return donor_storage_class;
case SpvStorageClassInput: case spv::StorageClass::Input:
case SpvStorageClassOutput: case spv::StorageClass::Output:
case SpvStorageClassUniform: case spv::StorageClass::Uniform:
case SpvStorageClassUniformConstant: case spv::StorageClass::UniformConstant:
case SpvStorageClassPushConstant: case spv::StorageClass::PushConstant:
case SpvStorageClassImage: case spv::StorageClass::Image:
case SpvStorageClassStorageBuffer: case spv::StorageClass::StorageBuffer:
// We change these to Private // We change these to Private
return SpvStorageClassPrivate; return spv::StorageClass::Private;
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 SpvStorageClassMax; return spv::StorageClass::Max;
} }
} }
@ -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 SpvOpTypeImage: case spv::Op::OpTypeImage:
case SpvOpTypeSampledImage: case spv::Op::OpTypeSampledImage:
case SpvOpTypeSampler: case spv::Op::OpTypeSampler:
// 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 SpvOpTypeVoid: { case spv::Op::OpTypeVoid: {
// 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 SpvOpTypeBool: { case spv::Op::OpTypeBool: {
// 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 SpvOpTypeInt: { case spv::Op::OpTypeInt: {
// 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 SpvOpTypeFloat: { case spv::Op::OpTypeFloat: {
// Similar to SpvOpTypeInt. // Similar to spv::Op::OpTypeInt.
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 SpvOpTypeVector: { case spv::Op::OpTypeVector: {
// 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 SpvOpTypeMatrix: { case spv::Op::OpTypeMatrix: {
// Similar to SpvOpTypeVector. // Similar to spv::Op::OpTypeVector.
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 SpvOpTypeArray: { case spv::Op::OpTypeArray: {
// 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 SpvOpTypeRuntimeArray: { case spv::Op::OpTypeRuntimeArray: {
// 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 SpvOpTypeStruct: { case spv::Op::OpTypeStruct: {
// Similar to SpvOpTypeArray. // Similar to spv::Op::OpTypeArray.
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 SpvOpTypePointer: { case spv::Op::OpTypePointer: {
// Similar to SpvOpTypeArray. // Similar to spv::Op::OpTypeArray.
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<SpvStorageClass>( AdaptStorageClass(static_cast<spv::StorageClass>(
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 SpvOpTypeFunction: { case spv::Op::OpTypeFunction: {
// 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,10 +425,11 @@ void FuzzerPassDonateModules::HandleTypeOrValue(
argument_type_ids)); argument_type_ids));
} }
} break; } break;
case SpvOpSpecConstantOp: { case spv::Op::OpSpecConstantOp: {
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 = static_cast<SpvOp>(type_or_value.GetSingleWordInOperand(0)); auto opcode =
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.
@ -447,20 +448,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 SpvOpSpecConstantTrue: case spv::Op::OpSpecConstantTrue:
case SpvOpSpecConstantFalse: case spv::Op::OpSpecConstantFalse:
case SpvOpConstantTrue: case spv::Op::OpConstantTrue:
case SpvOpConstantFalse: { case spv::Op::OpConstantFalse: {
// 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() == SpvOpConstantTrue || auto value = type_or_value.opcode() == spv::Op::OpConstantTrue ||
type_or_value.opcode() == SpvOpSpecConstantTrue; type_or_value.opcode() == spv::Op::OpSpecConstantTrue;
ApplyTransformation( ApplyTransformation(
TransformationAddConstantBoolean(new_result_id, value, false)); TransformationAddConstantBoolean(new_result_id, value, false));
} break; } break;
case SpvOpSpecConstant: case spv::Op::OpSpecConstant:
case SpvOpConstant: { case spv::Op::OpConstant: {
// 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();
@ -472,8 +473,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 SpvOpSpecConstantComposite: case spv::Op::OpSpecConstantComposite:
case SpvOpConstantComposite: { case spv::Op::OpConstantComposite: {
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.");
@ -495,7 +496,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 SpvOpConstantNull: { case spv::Op::OpConstantNull: {
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.
@ -509,7 +510,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 SpvOpVariable: { case spv::Op::OpVariable: {
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.
@ -536,11 +537,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;
SpvStorageClass storage_class = spv::StorageClass storage_class =
static_cast<SpvStorageClass>(type_or_value.GetSingleWordInOperand( static_cast<spv::StorageClass>(type_or_value.GetSingleWordInOperand(
0)) == SpvStorageClassWorkgroup 0)) == spv::StorageClass::Workgroup
? SpvStorageClassWorkgroup ? spv::StorageClass::Workgroup
: SpvStorageClassPrivate; : spv::StorageClass::Private;
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
@ -551,7 +552,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 == SpvStorageClassWorkgroup initializer_id = storage_class == spv::StorageClass::Workgroup
? 0 ? 0
: FindOrCreateZeroConstant( : FindOrCreateZeroConstant(
fuzzerutil::GetPointeeTypeIdFromPointerType( fuzzerutil::GetPointeeTypeIdFromPointerType(
@ -566,7 +567,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 SpvOpUndef: { case spv::Op::OpUndef: {
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.
@ -638,7 +639,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() == SpvOpArrayLength) { if (instruction->opcode() == spv::Op::OpArrayLength) {
// 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);
@ -682,70 +683,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 SpvOpAtomicLoad: case spv::Op::OpAtomicLoad:
case SpvOpAtomicStore: case spv::Op::OpAtomicStore:
case SpvOpAtomicExchange: case spv::Op::OpAtomicExchange:
case SpvOpAtomicCompareExchange: case spv::Op::OpAtomicCompareExchange:
case SpvOpAtomicCompareExchangeWeak: case spv::Op::OpAtomicCompareExchangeWeak:
case SpvOpAtomicIIncrement: case spv::Op::OpAtomicIIncrement:
case SpvOpAtomicIDecrement: case spv::Op::OpAtomicIDecrement:
case SpvOpAtomicIAdd: case spv::Op::OpAtomicIAdd:
case SpvOpAtomicISub: case spv::Op::OpAtomicISub:
case SpvOpAtomicSMin: case spv::Op::OpAtomicSMin:
case SpvOpAtomicUMin: case spv::Op::OpAtomicUMin:
case SpvOpAtomicSMax: case spv::Op::OpAtomicSMax:
case SpvOpAtomicUMax: case spv::Op::OpAtomicUMax:
case SpvOpAtomicAnd: case spv::Op::OpAtomicAnd:
case SpvOpAtomicOr: case spv::Op::OpAtomicOr:
case SpvOpAtomicXor: case spv::Op::OpAtomicXor:
// 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 SpvOpImageSampleImplicitLod: case spv::Op::OpImageSampleImplicitLod:
case SpvOpImageSampleExplicitLod: case spv::Op::OpImageSampleExplicitLod:
case SpvOpImageSampleDrefImplicitLod: case spv::Op::OpImageSampleDrefImplicitLod:
case SpvOpImageSampleDrefExplicitLod: case spv::Op::OpImageSampleDrefExplicitLod:
case SpvOpImageSampleProjImplicitLod: case spv::Op::OpImageSampleProjImplicitLod:
case SpvOpImageSampleProjExplicitLod: case spv::Op::OpImageSampleProjExplicitLod:
case SpvOpImageSampleProjDrefImplicitLod: case spv::Op::OpImageSampleProjDrefImplicitLod:
case SpvOpImageSampleProjDrefExplicitLod: case spv::Op::OpImageSampleProjDrefExplicitLod:
case SpvOpImageFetch: case spv::Op::OpImageFetch:
case SpvOpImageGather: case spv::Op::OpImageGather:
case SpvOpImageDrefGather: case spv::Op::OpImageDrefGather:
case SpvOpImageRead: case spv::Op::OpImageRead:
case SpvOpImageWrite: case spv::Op::OpImageWrite:
case SpvOpImageSparseSampleImplicitLod: case spv::Op::OpImageSparseSampleImplicitLod:
case SpvOpImageSparseSampleExplicitLod: case spv::Op::OpImageSparseSampleExplicitLod:
case SpvOpImageSparseSampleDrefImplicitLod: case spv::Op::OpImageSparseSampleDrefImplicitLod:
case SpvOpImageSparseSampleDrefExplicitLod: case spv::Op::OpImageSparseSampleDrefExplicitLod:
case SpvOpImageSparseSampleProjImplicitLod: case spv::Op::OpImageSparseSampleProjImplicitLod:
case SpvOpImageSparseSampleProjExplicitLod: case spv::Op::OpImageSparseSampleProjExplicitLod:
case SpvOpImageSparseSampleProjDrefImplicitLod: case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
case SpvOpImageSparseSampleProjDrefExplicitLod: case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
case SpvOpImageSparseFetch: case spv::Op::OpImageSparseFetch:
case SpvOpImageSparseGather: case spv::Op::OpImageSparseGather:
case SpvOpImageSparseDrefGather: case spv::Op::OpImageSparseDrefGather:
case SpvOpImageSparseRead: case spv::Op::OpImageSparseRead:
case SpvOpImageSampleFootprintNV: case spv::Op::OpImageSampleFootprintNV:
case SpvOpImage: case spv::Op::OpImage:
case SpvOpImageQueryFormat: case spv::Op::OpImageQueryFormat:
case SpvOpImageQueryLevels: case spv::Op::OpImageQueryLevels:
case SpvOpImageQueryLod: case spv::Op::OpImageQueryLod:
case SpvOpImageQueryOrder: case spv::Op::OpImageQueryOrder:
case SpvOpImageQuerySamples: case spv::Op::OpImageQuerySamples:
case SpvOpImageQuerySize: case spv::Op::OpImageQuerySize:
case SpvOpImageQuerySizeLod: case spv::Op::OpImageQuerySizeLod:
case SpvOpSampledImage: case spv::Op::OpSampledImage:
// 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 SpvOpLoad: case spv::Op::OpLoad:
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 SpvOpTypeImage: case spv::Op::OpTypeImage:
case SpvOpTypeSampledImage: case spv::Op::OpTypeSampledImage:
case SpvOpTypeSampler: case spv::Op::OpTypeSampler:
// Again, we ignore instructions that relate to accessing images. // Again, we ignore instructions that relate to accessing images.
return false; return false;
default: default:
@ -783,13 +784,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 SpvOpTypeArray: case spv::Op::OpTypeArray:
case SpvOpTypeBool: case spv::Op::OpTypeBool:
case SpvOpTypeFloat: case spv::Op::OpTypeFloat:
case SpvOpTypeInt: case spv::Op::OpTypeInt:
case SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
case SpvOpTypeStruct: case spv::Op::OpTypeStruct:
case SpvOpTypeVector: case spv::Op::OpTypeVector:
return true; return true;
default: default:
return false; return false;
@ -800,7 +801,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() == SpvOpArrayLength && assert(instruction.opcode() == spv::Op::OpArrayLength &&
"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));
@ -809,12 +810,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() == SpvOpTypePointer && assert(pointer_to_struct_instruction->opcode() == spv::Op::OpTypePointer &&
"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() == SpvOpTypeStruct && assert(donated_struct_type_instruction->opcode() == spv::Op::OpTypeStruct &&
"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 &&
@ -825,7 +826,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() == SpvOpTypeArray && assert(fixed_size_array_type_instruction->opcode() == spv::Op::OpTypeArray &&
"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);
@ -837,7 +838,8 @@ void FuzzerPassDonateModules::HandleOpArrayLength(
} }
donated_instructions->push_back(MakeInstructionMessage( donated_instructions->push_back(MakeInstructionMessage(
SpvOpCopyObject, original_id_to_donated_id->at(instruction.type_id()), spv::Op::OpCopyObject,
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}}})));
} }
@ -892,7 +894,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(
SpvOpCopyObject, remapped_type_id, spv::Op::OpCopyObject, 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}}})));
} }
@ -926,8 +928,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() == SpvOpLabel || ->opcode() == spv::Op::OpLabel ||
instruction.opcode() == SpvOpPhi) && instruction.opcode() == spv::Op::OpPhi) &&
"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()});
@ -942,7 +944,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() == SpvOpVariable && if (instruction.opcode() == spv::Op::OpVariable &&
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(
@ -1017,7 +1019,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() != SpvOpPhi) { if (inst.opcode() != spv::Op::OpPhi) {
break; break;
} }
@ -1070,7 +1072,8 @@ 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, SpvStorageClassFunction); // Needed for adding loop limiters 32, false,
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,
@ -1107,8 +1110,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 SpvOpAccessChain: case spv::Op::OpAccessChain:
case SpvOpInBoundsAccessChain: { case spv::Op::OpInBoundsAccessChain: {
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()));
@ -1118,7 +1121,8 @@ 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 && pointer_type->opcode() == SpvOpTypePointer && assert(pointer_type &&
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 =
@ -1138,7 +1142,8 @@ 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() == SpvOpTypeRuntimeArray) { if (should_be_composite_type->opcode() ==
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
@ -1148,7 +1153,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() == SpvOpTypeArray && assert(fixed_size_array_type->opcode() == spv::Op::OpTypeArray &&
"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.
@ -1163,12 +1168,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() == SpvOpTypeInt); assert(index_type_inst->opcode() == spv::Op::OpTypeInt);
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() != SpvOpConstant) { if (index_inst->opcode() != spv::Op::OpConstant) {
// 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.
@ -1194,7 +1199,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() != SpvOpTypeVoid && if (function_return_type_inst->opcode() != spv::Op::OpTypeVoid &&
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()),

View File

@ -45,7 +45,8 @@ 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 SpvStorageClass AdaptStorageClass(SpvStorageClass donor_storage_class); static spv::StorageClass AdaptStorageClass(
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

View File

@ -40,8 +40,8 @@ void FuzzerPassExpandVectorReductions::Apply() {
} }
// |instruction| must be OpAny or OpAll. // |instruction| must be OpAny or OpAll.
if (instruction.opcode() != SpvOpAny && if (instruction.opcode() != spv::Op::OpAny &&
instruction.opcode() != SpvOpAll) { instruction.opcode() != spv::Op::OpAll) {
continue; continue;
} }

View File

@ -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() == SpvOpSelectionMerge && block.GetMergeInst()->opcode() == spv::Op::OpSelectionMerge &&
block.terminator()->opcode() == SpvOpBranchConditional && block.terminator()->opcode() == spv::Op::OpBranchConditional &&
!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 SpvOpTypeBool: case spv::Op::OpTypeBool:
case SpvOpTypeInt: case spv::Op::OpTypeInt:
case SpvOpTypeFloat: case spv::Op::OpTypeFloat:
case SpvOpTypePointer: case spv::Op::OpTypePointer:
case SpvOpTypeVector: case spv::Op::OpTypeVector:
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 SpvOpTypeVector: { case spv::Op::OpTypeVector: {
uint32_t dimension = uint32_t dimension =
type_instruction->GetSingleWordInOperand(1); type_instruction->GetSingleWordInOperand(1);
switch (dimension) { switch (dimension) {

View File

@ -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() != SpvOpBranch) && function_call_block->terminator()->opcode() != spv::Op::OpBranch) &&
!MaybeApplyTransformation(TransformationSplitBlock( !MaybeApplyTransformation(TransformationSplitBlock(
MakeInstructionDescriptor(GetIRContext(), MakeInstructionDescriptor(GetIRContext(),
function_call_instruction->NextNode()), function_call_instruction->NextNode()),

View File

@ -47,18 +47,20 @@ void FuzzerPassMakeVectorOperationsDynamic::Apply() {
} }
// Make sure |instruction| has only one indexing operand. // Make sure |instruction| has only one indexing operand.
assert(instruction.NumInOperands() == assert(
(instruction.opcode() == SpvOpCompositeExtract ? 2 : 3) && instruction.NumInOperands() ==
"FuzzerPassMakeVectorOperationsDynamic: the composite " (instruction.opcode() == spv::Op::OpCompositeExtract ? 2 : 3) &&
"instruction must have " "FuzzerPassMakeVectorOperationsDynamic: the composite "
"only one indexing operand."); "instruction must have "
"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() == SpvOpCompositeExtract ? 1 : 2)}, instruction.opcode() == spv::Op::OpCompositeExtract ? 1
: 2)},
32, GetFuzzerContext()->ChooseEven(), false))); 32, GetFuzzerContext()->ChooseEven(), false)));
} }
} }

View File

@ -64,11 +64,11 @@ void FuzzerPassMergeFunctionReturns::Apply() {
[this, function]( [this, function](
opt::BasicBlock* /*unused*/, opt::BasicBlock::iterator inst_it, opt::BasicBlock* /*unused*/, opt::BasicBlock::iterator inst_it,
const protobufs::InstructionDescriptor& instruction_descriptor) { const protobufs::InstructionDescriptor& instruction_descriptor) {
const SpvOp opcode = inst_it->opcode(); const spv::Op opcode = inst_it->opcode();
switch (opcode) { switch (opcode) {
case SpvOpKill: case spv::Op::OpKill:
case SpvOpUnreachable: case spv::Op::OpUnreachable:
case SpvOpTerminateInvocation: { case spv::Op::OpTerminateInvocation: {
// This is an early termination instruction - we need to wrap it // This is an early termination instruction - we need to wrap it
// so that it becomes a return. // so that it becomes a return.
if (TransformationWrapEarlyTerminatorInFunction:: if (TransformationWrapEarlyTerminatorInFunction::
@ -85,7 +85,7 @@ void FuzzerPassMergeFunctionReturns::Apply() {
GetIRContext()->get_def_use_mgr()->GetDef( GetIRContext()->get_def_use_mgr()->GetDef(
function->type_id()); function->type_id());
uint32_t returned_value_id; uint32_t returned_value_id;
if (function_return_type->opcode() == SpvOpTypeVoid) { if (function_return_type->opcode() == spv::Op::OpTypeVoid) {
// No value is needed. // No value is needed.
returned_value_id = 0; returned_value_id = 0;
} else if (fuzzerutil::CanCreateConstant( } else if (fuzzerutil::CanCreateConstant(
@ -130,7 +130,7 @@ void FuzzerPassMergeFunctionReturns::Apply() {
// If the entry block does not branch unconditionally to another block, // If the entry block does not branch unconditionally to another block,
// split it. // split it.
if (function->entry()->terminator()->opcode() != SpvOpBranch) { if (function->entry()->terminator()->opcode() != spv::Op::OpBranch) {
SplitBlockAfterOpPhiOrOpVariable(function->entry()->id()); SplitBlockAfterOpPhiOrOpVariable(function->entry()->id());
} }
@ -149,9 +149,9 @@ void FuzzerPassMergeFunctionReturns::Apply() {
if (GetIRContext() if (GetIRContext()
->get_instr_block(merge_block) ->get_instr_block(merge_block)
->WhileEachInst([](opt::Instruction* inst) { ->WhileEachInst([](opt::Instruction* inst) {
return inst->opcode() == SpvOpLabel || return inst->opcode() == spv::Op::OpLabel ||
inst->opcode() == SpvOpPhi || inst->opcode() == spv::Op::OpPhi ||
inst->opcode() == SpvOpBranch; inst->opcode() == spv::Op::OpBranch;
})) { })) {
actual_merge_blocks.emplace_back(merge_block); actual_merge_blocks.emplace_back(merge_block);
continue; continue;
@ -324,7 +324,8 @@ FuzzerPassMergeFunctionReturns::GetInfoNeededForMergeBlocks(
bool FuzzerPassMergeFunctionReturns::IsEarlyTerminatorWrapper( bool FuzzerPassMergeFunctionReturns::IsEarlyTerminatorWrapper(
const opt::Function& function) const { const opt::Function& function) const {
for (SpvOp opcode : {SpvOpKill, SpvOpUnreachable, SpvOpTerminateInvocation}) { for (spv::Op opcode : {spv::Op::OpKill, spv::Op::OpUnreachable,
spv::Op::OpTerminateInvocation}) {
if (TransformationWrapEarlyTerminatorInFunction::MaybeGetWrapperFunction( if (TransformationWrapEarlyTerminatorInFunction::MaybeGetWrapperFunction(
GetIRContext(), opcode) == &function) { GetIRContext(), opcode) == &function) {
return true; return true;

View File

@ -39,7 +39,8 @@ void FuzzerPassMutatePointers::Apply() {
return; return;
} }
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, inst_it)) { if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
inst_it)) {
return; return;
} }

View File

@ -37,21 +37,21 @@ FuzzerPassObfuscateConstants::FuzzerPassObfuscateConstants(
void FuzzerPassObfuscateConstants::ObfuscateBoolConstantViaConstantPair( void FuzzerPassObfuscateConstants::ObfuscateBoolConstantViaConstantPair(
uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use, uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use,
const std::vector<SpvOp>& greater_than_opcodes, const std::vector<spv::Op>& greater_than_opcodes,
const std::vector<SpvOp>& less_than_opcodes, uint32_t constant_id_1, const std::vector<spv::Op>& less_than_opcodes, uint32_t constant_id_1,
uint32_t constant_id_2, bool first_constant_is_larger) { uint32_t constant_id_2, bool first_constant_is_larger) {
auto bool_constant_opcode = GetIRContext() auto bool_constant_opcode = GetIRContext()
->get_def_use_mgr() ->get_def_use_mgr()
->GetDef(bool_constant_use.id_of_interest()) ->GetDef(bool_constant_use.id_of_interest())
->opcode(); ->opcode();
assert((bool_constant_opcode == SpvOpConstantFalse || assert((bool_constant_opcode == spv::Op::OpConstantFalse ||
bool_constant_opcode == SpvOpConstantTrue) && bool_constant_opcode == spv::Op::OpConstantTrue) &&
"Precondition: this must be a usage of a boolean constant."); "Precondition: this must be a usage of a boolean constant.");
// Pick an opcode at random. First randomly decide whether to generate // Pick an opcode at random. First randomly decide whether to generate
// a 'greater than' or 'less than' kind of opcode, and then select a // a 'greater than' or 'less than' kind of opcode, and then select a
// random opcode from the resulting subset. // random opcode from the resulting subset.
SpvOp comparison_opcode; spv::Op comparison_opcode;
if (GetFuzzerContext()->ChooseEven()) { if (GetFuzzerContext()->ChooseEven()) {
comparison_opcode = greater_than_opcodes[GetFuzzerContext()->RandomIndex( comparison_opcode = greater_than_opcodes[GetFuzzerContext()->RandomIndex(
greater_than_opcodes)]; greater_than_opcodes)];
@ -68,9 +68,9 @@ void FuzzerPassObfuscateConstants::ObfuscateBoolConstantViaConstantPair(
comparison_opcode) != greater_than_opcodes.end(); comparison_opcode) != greater_than_opcodes.end();
uint32_t lhs_id; uint32_t lhs_id;
uint32_t rhs_id; uint32_t rhs_id;
if ((bool_constant_opcode == SpvOpConstantTrue && if ((bool_constant_opcode == spv::Op::OpConstantTrue &&
first_constant_is_larger == is_greater_than_opcode) || first_constant_is_larger == is_greater_than_opcode) ||
(bool_constant_opcode == SpvOpConstantFalse && (bool_constant_opcode == spv::Op::OpConstantFalse &&
first_constant_is_larger != is_greater_than_opcode)) { first_constant_is_larger != is_greater_than_opcode)) {
lhs_id = constant_id_1; lhs_id = constant_id_1;
rhs_id = constant_id_2; rhs_id = constant_id_2;
@ -147,12 +147,12 @@ void FuzzerPassObfuscateConstants::ObfuscateBoolConstantViaFloatConstantPair(
first_constant_is_larger = first_constant_is_larger =
float_constant_1->GetDouble() > float_constant_2->GetDouble(); float_constant_1->GetDouble() > float_constant_2->GetDouble();
} }
std::vector<SpvOp> greater_than_opcodes{ std::vector<spv::Op> greater_than_opcodes{
SpvOpFOrdGreaterThan, SpvOpFOrdGreaterThanEqual, SpvOpFUnordGreaterThan, spv::Op::OpFOrdGreaterThan, spv::Op::OpFOrdGreaterThanEqual,
SpvOpFUnordGreaterThanEqual}; spv::Op::OpFUnordGreaterThan, spv::Op::OpFUnordGreaterThanEqual};
std::vector<SpvOp> less_than_opcodes{ std::vector<spv::Op> less_than_opcodes{
SpvOpFOrdGreaterThan, SpvOpFOrdGreaterThanEqual, SpvOpFUnordGreaterThan, spv::Op::OpFOrdGreaterThan, spv::Op::OpFOrdGreaterThanEqual,
SpvOpFUnordGreaterThanEqual}; spv::Op::OpFUnordGreaterThan, spv::Op::OpFUnordGreaterThanEqual};
ObfuscateBoolConstantViaConstantPair( ObfuscateBoolConstantViaConstantPair(
depth, bool_constant_use, greater_than_opcodes, less_than_opcodes, depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
@ -190,9 +190,10 @@ void FuzzerPassObfuscateConstants::
first_constant_is_larger = first_constant_is_larger =
signed_int_constant_1->GetS64() > signed_int_constant_2->GetS64(); signed_int_constant_1->GetS64() > signed_int_constant_2->GetS64();
} }
std::vector<SpvOp> greater_than_opcodes{SpvOpSGreaterThan, std::vector<spv::Op> greater_than_opcodes{spv::Op::OpSGreaterThan,
SpvOpSGreaterThanEqual}; spv::Op::OpSGreaterThanEqual};
std::vector<SpvOp> less_than_opcodes{SpvOpSLessThan, SpvOpSLessThanEqual}; std::vector<spv::Op> less_than_opcodes{spv::Op::OpSLessThan,
spv::Op::OpSLessThanEqual};
ObfuscateBoolConstantViaConstantPair( ObfuscateBoolConstantViaConstantPair(
depth, bool_constant_use, greater_than_opcodes, less_than_opcodes, depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
@ -232,9 +233,10 @@ void FuzzerPassObfuscateConstants::
first_constant_is_larger = first_constant_is_larger =
unsigned_int_constant_1->GetU64() > unsigned_int_constant_2->GetU64(); unsigned_int_constant_1->GetU64() > unsigned_int_constant_2->GetU64();
} }
std::vector<SpvOp> greater_than_opcodes{SpvOpUGreaterThan, std::vector<spv::Op> greater_than_opcodes{spv::Op::OpUGreaterThan,
SpvOpUGreaterThanEqual}; spv::Op::OpUGreaterThanEqual};
std::vector<SpvOp> less_than_opcodes{SpvOpULessThan, SpvOpULessThanEqual}; std::vector<spv::Op> less_than_opcodes{spv::Op::OpULessThan,
spv::Op::OpULessThanEqual};
ObfuscateBoolConstantViaConstantPair( ObfuscateBoolConstantViaConstantPair(
depth, bool_constant_use, greater_than_opcodes, less_than_opcodes, depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
@ -379,7 +381,7 @@ void FuzzerPassObfuscateConstants::ObfuscateScalarConstant(
uniform_descriptor.index()); uniform_descriptor.index());
assert(element_type_id && "Type of uniform variable is invalid"); assert(element_type_id && "Type of uniform variable is invalid");
FindOrCreatePointerType(element_type_id, SpvStorageClassUniform); FindOrCreatePointerType(element_type_id, spv::StorageClass::Uniform);
// Create, apply and record a transformation to replace the constant use with // Create, apply and record a transformation to replace the constant use with
// the result of a load from the chosen uniform. // the result of a load from the chosen uniform.
@ -394,11 +396,11 @@ void FuzzerPassObfuscateConstants::ObfuscateConstant(
->get_def_use_mgr() ->get_def_use_mgr()
->GetDef(constant_use.id_of_interest()) ->GetDef(constant_use.id_of_interest())
->opcode()) { ->opcode()) {
case SpvOpConstantTrue: case spv::Op::OpConstantTrue:
case SpvOpConstantFalse: case spv::Op::OpConstantFalse:
ObfuscateBoolConstant(depth, constant_use); ObfuscateBoolConstant(depth, constant_use);
break; break;
case SpvOpConstant: case spv::Op::OpConstant:
ObfuscateScalarConstant(depth, constant_use); ObfuscateScalarConstant(depth, constant_use);
break; break;
default: default:
@ -410,7 +412,7 @@ void FuzzerPassObfuscateConstants::ObfuscateConstant(
void FuzzerPassObfuscateConstants::MaybeAddConstantIdUse( void FuzzerPassObfuscateConstants::MaybeAddConstantIdUse(
const opt::Instruction& inst, uint32_t in_operand_index, const opt::Instruction& inst, uint32_t in_operand_index,
uint32_t base_instruction_result_id, uint32_t base_instruction_result_id,
const std::map<SpvOp, uint32_t>& skipped_opcode_count, const std::map<spv::Op, uint32_t>& skipped_opcode_count,
std::vector<protobufs::IdUseDescriptor>* constant_uses) { std::vector<protobufs::IdUseDescriptor>* constant_uses) {
if (inst.GetInOperand(in_operand_index).type != SPV_OPERAND_TYPE_ID) { if (inst.GetInOperand(in_operand_index).type != SPV_OPERAND_TYPE_ID) {
// The operand is not an id, so it cannot be a constant id. // The operand is not an id, so it cannot be a constant id.
@ -420,15 +422,15 @@ void FuzzerPassObfuscateConstants::MaybeAddConstantIdUse(
auto operand_definition = auto operand_definition =
GetIRContext()->get_def_use_mgr()->GetDef(operand_id); GetIRContext()->get_def_use_mgr()->GetDef(operand_id);
switch (operand_definition->opcode()) { switch (operand_definition->opcode()) {
case SpvOpConstantFalse: case spv::Op::OpConstantFalse:
case SpvOpConstantTrue: case spv::Op::OpConstantTrue:
case SpvOpConstant: { case spv::Op::OpConstant: {
// The operand is a constant id, so make an id use descriptor and record // The operand is a constant id, so make an id use descriptor and record
// it. // it.
protobufs::IdUseDescriptor id_use_descriptor; protobufs::IdUseDescriptor id_use_descriptor;
id_use_descriptor.set_id_of_interest(operand_id); id_use_descriptor.set_id_of_interest(operand_id);
id_use_descriptor.mutable_enclosing_instruction() id_use_descriptor.mutable_enclosing_instruction()
->set_target_instruction_opcode(inst.opcode()); ->set_target_instruction_opcode(uint32_t(inst.opcode()));
id_use_descriptor.mutable_enclosing_instruction() id_use_descriptor.mutable_enclosing_instruction()
->set_base_instruction_result_id(base_instruction_result_id); ->set_base_instruction_result_id(base_instruction_result_id);
id_use_descriptor.mutable_enclosing_instruction() id_use_descriptor.mutable_enclosing_instruction()
@ -461,7 +463,7 @@ void FuzzerPassObfuscateConstants::Apply() {
// opcode need to be skipped in order to find the instruction of interest // opcode need to be skipped in order to find the instruction of interest
// from the base instruction. We maintain a mapping that records a skip // from the base instruction. We maintain a mapping that records a skip
// count for each relevant opcode. // count for each relevant opcode.
std::map<SpvOp, uint32_t> skipped_opcode_count; std::map<spv::Op, uint32_t> skipped_opcode_count;
// Go through each instruction in the block. // Go through each instruction in the block.
for (auto& inst : block) { for (auto& inst : block) {
@ -478,7 +480,7 @@ void FuzzerPassObfuscateConstants::Apply() {
// The instruction must not be an OpVariable, the only id that an // The instruction must not be an OpVariable, the only id that an
// OpVariable uses is an initializer id, which has to remain // OpVariable uses is an initializer id, which has to remain
// constant. // constant.
if (inst.opcode() != SpvOpVariable) { if (inst.opcode() != spv::Op::OpVariable) {
// Consider each operand of the instruction, and add a constant id // Consider each operand of the instruction, and add a constant id
// use for the operand if relevant. // use for the operand if relevant.
for (uint32_t in_operand_index = 0; for (uint32_t in_operand_index = 0;

View File

@ -85,8 +85,8 @@ class FuzzerPassObfuscateConstants : public FuzzerPass {
// (similar for |less_than_opcodes|). // (similar for |less_than_opcodes|).
void ObfuscateBoolConstantViaConstantPair( void ObfuscateBoolConstantViaConstantPair(
uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use, uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use,
const std::vector<SpvOp>& greater_than_opcodes, const std::vector<spv::Op>& greater_than_opcodes,
const std::vector<SpvOp>& less_than_opcodes, uint32_t constant_id_1, const std::vector<spv::Op>& less_than_opcodes, uint32_t constant_id_1,
uint32_t constant_id_2, bool first_constant_is_larger); uint32_t constant_id_2, bool first_constant_is_larger);
// A helper method to determine whether input operand |in_operand_index| of // A helper method to determine whether input operand |in_operand_index| of
@ -96,7 +96,7 @@ class FuzzerPassObfuscateConstants : public FuzzerPass {
void MaybeAddConstantIdUse( void MaybeAddConstantIdUse(
const opt::Instruction& inst, uint32_t in_operand_index, const opt::Instruction& inst, uint32_t in_operand_index,
uint32_t base_instruction_result_id, uint32_t base_instruction_result_id,
const std::map<SpvOp, uint32_t>& skipped_opcode_count, const std::map<spv::Op, uint32_t>& skipped_opcode_count,
std::vector<protobufs::IdUseDescriptor>* constant_uses); std::vector<protobufs::IdUseDescriptor>* constant_uses);
// Returns a vector of unique words that denote constants. Every such constant // Returns a vector of unique words that denote constants. Every such constant

View File

@ -137,12 +137,12 @@ FuzzerPassOutlineFunctions::MaybeGetEntryBlockSuitableForOutlining(
"The entry block cannot be a loop header at this point."); "The entry block cannot be a loop header at this point.");
// If the entry block starts with OpPhi or OpVariable, try to split it. // If the entry block starts with OpPhi or OpVariable, try to split it.
if (entry_block->begin()->opcode() == SpvOpPhi || if (entry_block->begin()->opcode() == spv::Op::OpPhi ||
entry_block->begin()->opcode() == SpvOpVariable) { entry_block->begin()->opcode() == spv::Op::OpVariable) {
// Find the first non-OpPhi and non-OpVariable instruction. // Find the first non-OpPhi and non-OpVariable instruction.
auto non_phi_or_var_inst = &*entry_block->begin(); auto non_phi_or_var_inst = &*entry_block->begin();
while (non_phi_or_var_inst->opcode() == SpvOpPhi || while (non_phi_or_var_inst->opcode() == spv::Op::OpPhi ||
non_phi_or_var_inst->opcode() == SpvOpVariable) { non_phi_or_var_inst->opcode() == spv::Op::OpVariable) {
non_phi_or_var_inst = non_phi_or_var_inst->NextNode(); non_phi_or_var_inst = non_phi_or_var_inst->NextNode();
} }
@ -175,7 +175,7 @@ FuzzerPassOutlineFunctions::MaybeGetExitBlockSuitableForOutlining(
// Find the first non-OpPhi instruction, after which to split. // Find the first non-OpPhi instruction, after which to split.
auto split_before = &*exit_block->begin(); auto split_before = &*exit_block->begin();
while (split_before->opcode() == SpvOpPhi) { while (split_before->opcode() == spv::Op::OpPhi) {
split_before = split_before->NextNode(); split_before = split_before->NextNode();
} }

View File

@ -47,7 +47,7 @@ void FuzzerPassPermuteFunctionVariables::Apply() {
std::vector<opt::Instruction*> variables; std::vector<opt::Instruction*> variables;
for (auto& instruction : *first_block) { for (auto& instruction : *first_block) {
if (instruction.opcode() == SpvOpVariable) { if (instruction.opcode() == spv::Op::OpVariable) {
variables.push_back(&instruction); variables.push_back(&instruction);
} }
} }

View File

@ -40,7 +40,7 @@ void FuzzerPassPermutePhiOperands::Apply() {
const protobufs::InstructionDescriptor& /*unused*/) { const protobufs::InstructionDescriptor& /*unused*/) {
const auto& inst = *inst_it; const auto& inst = *inst_it;
if (inst.opcode() != SpvOpPhi) { if (inst.opcode() != spv::Op::OpPhi) {
return; return;
} }

View File

@ -35,10 +35,11 @@ void FuzzerPassPushIdsThroughVariables::Apply() {
opt::BasicBlock::iterator instruction_iterator, opt::BasicBlock::iterator instruction_iterator,
const protobufs::InstructionDescriptor& instruction_descriptor) const protobufs::InstructionDescriptor& instruction_descriptor)
-> void { -> void {
assert(instruction_iterator->opcode() == assert(
instruction_descriptor.target_instruction_opcode() && instruction_iterator->opcode() ==
"The opcode of the instruction we might insert before must be " spv::Op(instruction_descriptor.target_instruction_opcode()) &&
"the same as the opcode in the descriptor for the instruction"); "The opcode of the instruction we might insert before must be "
"the same as the opcode in the descriptor for the instruction");
// Randomly decide whether to try pushing an id through a variable. // Randomly decide whether to try pushing an id through a variable.
if (!GetFuzzerContext()->ChoosePercentage( if (!GetFuzzerContext()->ChoosePercentage(
@ -55,16 +56,16 @@ void FuzzerPassPushIdsThroughVariables::Apply() {
// It must be valid to insert OpStore and OpLoad instructions // It must be valid to insert OpStore and OpLoad instructions
// before the instruction to insert before. // before the instruction to insert before.
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction( if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
SpvOpStore, instruction_iterator) || spv::Op::OpStore, instruction_iterator) ||
!fuzzerutil::CanInsertOpcodeBeforeInstruction( !fuzzerutil::CanInsertOpcodeBeforeInstruction(
SpvOpLoad, instruction_iterator)) { spv::Op::OpLoad, instruction_iterator)) {
return; return;
} }
// Randomly decides whether a global or local variable will be added. // Randomly decides whether a global or local variable will be added.
auto variable_storage_class = GetFuzzerContext()->ChooseEven() auto variable_storage_class = GetFuzzerContext()->ChooseEven()
? SpvStorageClassPrivate ? spv::StorageClass::Private
: SpvStorageClassFunction; : spv::StorageClass::Function;
// Gets the available basic and pointer types. // Gets the available basic and pointer types.
auto basic_type_ids_and_pointers = auto basic_type_ids_and_pointers =
@ -127,13 +128,13 @@ void FuzzerPassPushIdsThroughVariables::Apply() {
GetIRContext()->get_def_use_mgr()->GetDef(basic_type_id); GetIRContext()->get_def_use_mgr()->GetDef(basic_type_id);
assert(type_inst); assert(type_inst);
switch (type_inst->opcode()) { switch (type_inst->opcode()) {
case SpvOpTypeBool: case spv::Op::OpTypeBool:
case SpvOpTypeFloat: case spv::Op::OpTypeFloat:
case SpvOpTypeInt: case spv::Op::OpTypeInt:
case SpvOpTypeArray: case spv::Op::OpTypeArray:
case SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
case SpvOpTypeVector: case spv::Op::OpTypeVector:
case SpvOpTypeStruct: case spv::Op::OpTypeStruct:
break; break;
default: default:
return; return;
@ -150,7 +151,8 @@ void FuzzerPassPushIdsThroughVariables::Apply() {
value_instructions)] value_instructions)]
->result_id(), ->result_id(),
GetFuzzerContext()->GetFreshId(), GetFuzzerContext()->GetFreshId(), GetFuzzerContext()->GetFreshId(), GetFuzzerContext()->GetFreshId(),
variable_storage_class, initializer_id, instruction_descriptor)); uint32_t(variable_storage_class), initializer_id,
instruction_descriptor));
}); });
} }

View File

@ -38,13 +38,13 @@ void FuzzerPassReplaceBranchesFromDeadBlocksWithExits::Apply() {
// to be executed with the Fragment execution model. We conservatively only // to be executed with the Fragment execution model. We conservatively only
// allow OpKill if every entry point in the module has the Fragment execution // allow OpKill if every entry point in the module has the Fragment execution
// model. // model.
auto fragment_execution_model_guaranteed = auto fragment_execution_model_guaranteed = std::all_of(
std::all_of(GetIRContext()->module()->entry_points().begin(), GetIRContext()->module()->entry_points().begin(),
GetIRContext()->module()->entry_points().end(), GetIRContext()->module()->entry_points().end(),
[](const opt::Instruction& entry_point) -> bool { [](const opt::Instruction& entry_point) -> bool {
return entry_point.GetSingleWordInOperand(0) == return spv::ExecutionModel(entry_point.GetSingleWordInOperand(0)) ==
SpvExecutionModelFragment; spv::ExecutionModel::Fragment;
}); });
// Transformations of this type can disable one another. To avoid ordering // Transformations of this type can disable one another. To avoid ordering
// bias, we therefore build a set of candidate transformations to apply, and // bias, we therefore build a set of candidate transformations to apply, and
@ -71,20 +71,20 @@ void FuzzerPassReplaceBranchesFromDeadBlocksWithExits::Apply() {
// Whether we can use OpKill depends on the execution model, and which of // Whether we can use OpKill depends on the execution model, and which of
// OpReturn and OpReturnValue we can use depends on the return type of the // OpReturn and OpReturnValue we can use depends on the return type of the
// enclosing function. // enclosing function.
std::vector<SpvOp> opcodes = {SpvOpUnreachable}; std::vector<spv::Op> opcodes = {spv::Op::OpUnreachable};
if (fragment_execution_model_guaranteed) { if (fragment_execution_model_guaranteed) {
opcodes.emplace_back(SpvOpKill); opcodes.emplace_back(spv::Op::OpKill);
} }
auto function_return_type = auto function_return_type =
GetIRContext()->get_type_mgr()->GetType(function.type_id()); GetIRContext()->get_type_mgr()->GetType(function.type_id());
if (function_return_type->AsVoid()) { if (function_return_type->AsVoid()) {
opcodes.emplace_back(SpvOpReturn); opcodes.emplace_back(spv::Op::OpReturn);
} else if (fuzzerutil::CanCreateConstant(GetIRContext(), } else if (fuzzerutil::CanCreateConstant(GetIRContext(),
function.type_id())) { function.type_id())) {
// For simplicity we only allow OpReturnValue if the function return // For simplicity we only allow OpReturnValue if the function return
// type is a type for which we can create a constant. This allows us a // type is a type for which we can create a constant. This allows us a
// zero of the given type as a default return value. // zero of the given type as a default return value.
opcodes.emplace_back(SpvOpReturnValue); opcodes.emplace_back(spv::Op::OpReturnValue);
} }
// Choose one of the available terminator opcodes at random and create a // Choose one of the available terminator opcodes at random and create a
// candidate transformation. // candidate transformation.
@ -92,7 +92,7 @@ void FuzzerPassReplaceBranchesFromDeadBlocksWithExits::Apply() {
candidate_transformations.emplace_back( candidate_transformations.emplace_back(
TransformationReplaceBranchFromDeadBlockWithExit( TransformationReplaceBranchFromDeadBlockWithExit(
block.id(), opcode, block.id(), opcode,
opcode == SpvOpReturnValue opcode == spv::Op::OpReturnValue
? FindOrCreateZeroConstant(function.type_id(), true) ? FindOrCreateZeroConstant(function.type_id(), true)
: 0)); : 0));
} }

View File

@ -41,7 +41,7 @@ void FuzzerPassReplaceCopyMemoriesWithLoadsStores::Apply() {
} }
// The instruction must be OpCopyMemory. // The instruction must be OpCopyMemory.
if (instruction->opcode() != SpvOpCopyMemory) { if (instruction->opcode() != spv::Op::OpCopyMemory) {
return; return;
} }

View File

@ -40,7 +40,7 @@ void FuzzerPassReplaceCopyObjectsWithStoresLoads::Apply() {
return; return;
} }
// The instruction must be OpCopyObject. // The instruction must be OpCopyObject.
if (instruction->opcode() != SpvOpCopyObject) { if (instruction->opcode() != spv::Op::OpCopyObject) {
return; return;
} }
// The opcode of the type_id instruction cannot be a OpTypePointer, // The opcode of the type_id instruction cannot be a OpTypePointer,
@ -48,21 +48,22 @@ void FuzzerPassReplaceCopyObjectsWithStoresLoads::Apply() {
if (GetIRContext() if (GetIRContext()
->get_def_use_mgr() ->get_def_use_mgr()
->GetDef(instruction->type_id()) ->GetDef(instruction->type_id())
->opcode() == SpvOpTypePointer) { ->opcode() == spv::Op::OpTypePointer) {
return; return;
} }
// It must be valid to insert OpStore and OpLoad instructions // It must be valid to insert OpStore and OpLoad instructions
// before the instruction OpCopyObject. // before the instruction OpCopyObject.
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore, if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpStore,
instruction) || instruction) ||
!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, instruction)) { !fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
instruction)) {
return; return;
} }
// Randomly decides whether a global or local variable will be added. // Randomly decides whether a global or local variable will be added.
auto variable_storage_class = GetFuzzerContext()->ChooseEven() auto variable_storage_class = GetFuzzerContext()->ChooseEven()
? SpvStorageClassPrivate ? spv::StorageClass::Private
: SpvStorageClassFunction; : spv::StorageClass::Function;
// Find or create a constant to initialize the variable from. The type of // Find or create a constant to initialize the variable from. The type of
// |instruction| must be such that the function FindOrCreateConstant can be // |instruction| must be such that the function FindOrCreateConstant can be
@ -79,7 +80,7 @@ void FuzzerPassReplaceCopyObjectsWithStoresLoads::Apply() {
// Apply the transformation replacing OpCopyObject with Store and Load. // Apply the transformation replacing OpCopyObject with Store and Load.
ApplyTransformation(TransformationReplaceCopyObjectWithStoreLoad( ApplyTransformation(TransformationReplaceCopyObjectWithStoreLoad(
instruction->result_id(), GetFuzzerContext()->GetFreshId(), instruction->result_id(), GetFuzzerContext()->GetFreshId(),
variable_storage_class, variable_initializer_id)); uint32_t(variable_storage_class), variable_initializer_id));
}); });
} }

View File

@ -73,7 +73,7 @@ void FuzzerPassReplaceIrrelevantIds::Apply() {
// we cannot use these as replacements. // we cannot use these as replacements.
for (const auto& pair : GetIRContext()->get_def_use_mgr()->id_to_defs()) { for (const auto& pair : GetIRContext()->get_def_use_mgr()->id_to_defs()) {
uint32_t type_id = pair.second->type_id(); uint32_t type_id = pair.second->type_id();
if (pair.second->opcode() != SpvOpFunction && type_id && if (pair.second->opcode() != spv::Op::OpFunction && type_id &&
types_to_ids.count(type_id)) { types_to_ids.count(type_id)) {
types_to_ids[type_id].push_back(pair.first); types_to_ids[type_id].push_back(pair.first);
} }

View File

@ -50,9 +50,9 @@ void FuzzerPassReplaceLoadsStoresWithCopyMemories::Apply() {
std::unordered_map<uint32_t, opt::Instruction*> current_op_loads; std::unordered_map<uint32_t, opt::Instruction*> current_op_loads;
for (auto& instruction : block) { for (auto& instruction : block) {
// Add a potential OpLoad instruction. // Add a potential OpLoad instruction.
if (instruction.opcode() == SpvOpLoad) { if (instruction.opcode() == spv::Op::OpLoad) {
current_op_loads[instruction.result_id()] = &instruction; current_op_loads[instruction.result_id()] = &instruction;
} else if (instruction.opcode() == SpvOpStore) { } else if (instruction.opcode() == spv::Op::OpStore) {
if (current_op_loads.find(instruction.GetSingleWordOperand(1)) != if (current_op_loads.find(instruction.GetSingleWordOperand(1)) !=
current_op_loads.end()) { current_op_loads.end()) {
// We have found the matching OpLoad instruction to the current // We have found the matching OpLoad instruction to the current
@ -73,7 +73,7 @@ void FuzzerPassReplaceLoadsStoresWithCopyMemories::Apply() {
opt::Instruction* source_id = opt::Instruction* source_id =
GetIRContext()->get_def_use_mgr()->GetDef( GetIRContext()->get_def_use_mgr()->GetDef(
it->second->GetSingleWordOperand(2)); it->second->GetSingleWordOperand(2));
SpvStorageClass storage_class = spv::StorageClass storage_class =
fuzzerutil::GetStorageClassFromPointerType( fuzzerutil::GetStorageClassFromPointerType(
GetIRContext(), source_id->type_id()); GetIRContext(), source_id->type_id());
if (!TransformationReplaceLoadStoreWithCopyMemory:: if (!TransformationReplaceLoadStoreWithCopyMemory::

View File

@ -50,7 +50,7 @@ void FuzzerPassReplaceOpPhiIdsFromDeadPredecessors::Apply() {
block->id(), [this, &function, block, &transformations]( block->id(), [this, &function, block, &transformations](
opt::Instruction* instruction, uint32_t) { opt::Instruction* instruction, uint32_t) {
// Only consider OpPhi instructions. // Only consider OpPhi instructions.
if (instruction->opcode() != SpvOpPhi) { if (instruction->opcode() != spv::Op::OpPhi) {
return; return;
} }

View File

@ -52,7 +52,7 @@ void FuzzerPassReplaceOpSelectsWithConditionalBranches::Apply() {
for (auto& instruction : block) { for (auto& instruction : block) {
// We only care about OpSelect instructions. // We only care about OpSelect instructions.
if (instruction.opcode() != SpvOpSelect) { if (instruction.opcode() != spv::Op::OpSelect) {
continue; continue;
} }
@ -69,7 +69,7 @@ void FuzzerPassReplaceOpSelectsWithConditionalBranches::Apply() {
->get_def_use_mgr() ->get_def_use_mgr()
->GetDef(fuzzerutil::GetTypeId( ->GetDef(fuzzerutil::GetTypeId(
GetIRContext(), instruction.GetSingleWordInOperand(0))) GetIRContext(), instruction.GetSingleWordInOperand(0)))
->opcode() != SpvOpTypeBool) { ->opcode() != spv::Op::OpTypeBool) {
continue; continue;
} }
@ -136,7 +136,7 @@ void FuzzerPassReplaceOpSelectsWithConditionalBranches::Apply() {
bool FuzzerPassReplaceOpSelectsWithConditionalBranches:: bool FuzzerPassReplaceOpSelectsWithConditionalBranches::
InstructionNeedsSplitBefore(opt::Instruction* instruction) { InstructionNeedsSplitBefore(opt::Instruction* instruction) {
assert(instruction && instruction->opcode() == SpvOpSelect && assert(instruction && instruction->opcode() == spv::Op::OpSelect &&
"The instruction must be OpSelect."); "The instruction must be OpSelect.");
auto block = GetIRContext()->get_instr_block(instruction); auto block = GetIRContext()->get_instr_block(instruction);
@ -163,7 +163,7 @@ bool FuzzerPassReplaceOpSelectsWithConditionalBranches::
auto predecessor = GetIRContext()->get_instr_block( auto predecessor = GetIRContext()->get_instr_block(
GetIRContext()->cfg()->preds(block->id())[0]); GetIRContext()->cfg()->preds(block->id())[0]);
return predecessor->MergeBlockIdIfAny() || return predecessor->MergeBlockIdIfAny() ||
predecessor->terminator()->opcode() != SpvOpBranch; predecessor->terminator()->opcode() != spv::Op::OpBranch;
} }
} // namespace fuzz } // namespace fuzz

View File

@ -72,7 +72,8 @@ void FuzzerPassReplaceParameterWithGlobal::Apply() {
assert(replaced_param && "Unable to find a parameter to replace"); assert(replaced_param && "Unable to find a parameter to replace");
// Make sure type id for the global variable exists in the module. // Make sure type id for the global variable exists in the module.
FindOrCreatePointerType(replaced_param->type_id(), SpvStorageClassPrivate); FindOrCreatePointerType(replaced_param->type_id(),
spv::StorageClass::Private);
// Make sure initializer for the global variable exists in the module. // Make sure initializer for the global variable exists in the module.
FindOrCreateZeroConstant(replaced_param->type_id(), false); FindOrCreateZeroConstant(replaced_param->type_id(), false);

View File

@ -65,7 +65,7 @@ void FuzzerPassSplitBlocks::Apply() {
// 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<SpvOp, uint32_t> skip_count; std::map<spv::Op, 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
@ -78,7 +78,7 @@ void FuzzerPassSplitBlocks::Apply() {
base = inst.result_id(); base = inst.result_id();
skip_count.clear(); skip_count.clear();
} }
const SpvOp opcode = inst.opcode(); const spv::Op opcode = inst.opcode();
instruction_descriptors.emplace_back(MakeInstructionDescriptor( instruction_descriptors.emplace_back(MakeInstructionDescriptor(
base, opcode, skip_count.count(opcode) ? skip_count.at(opcode) : 0)); base, opcode, skip_count.count(opcode) ? skip_count.at(opcode) : 0));
if (!inst.HasResultId()) { if (!inst.HasResultId()) {

View File

@ -39,7 +39,7 @@ void FuzzerPassSwapBranchConditionalOperands::Apply() {
const protobufs::InstructionDescriptor& instruction_descriptor) { const protobufs::InstructionDescriptor& instruction_descriptor) {
const auto& inst = *inst_it; const auto& inst = *inst_it;
if (inst.opcode() != SpvOpBranchConditional) { if (inst.opcode() != spv::Op::OpBranchConditional) {
return; return;
} }

View File

@ -36,8 +36,9 @@ void FuzzerPassToggleAccessChainInstruction::Apply() {
// probabilistically applied. // probabilistically applied.
context->module()->ForEachInst([this, context->module()->ForEachInst([this,
context](opt::Instruction* instruction) { context](opt::Instruction* instruction) {
SpvOp opcode = instruction->opcode(); spv::Op opcode = instruction->opcode();
if ((opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain) && if ((opcode == spv::Op::OpAccessChain ||
opcode == spv::Op::OpInBoundsAccessChain) &&
GetFuzzerContext()->ChoosePercentage( GetFuzzerContext()->ChoosePercentage(
GetFuzzerContext()->GetChanceOfTogglingAccessChainInstruction())) { GetFuzzerContext()->GetChanceOfTogglingAccessChainInstruction())) {
auto instructionDescriptor = auto instructionDescriptor =

View File

@ -52,7 +52,7 @@ void FuzzerPassWrapVectorSynonym::Apply() {
// It must be valid to insert an OpCompositeConstruct instruction // It must be valid to insert an OpCompositeConstruct instruction
// before |instruction_iterator|. // before |instruction_iterator|.
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction( if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
SpvOpCompositeConstruct, instruction_iterator)) { spv::Op::OpCompositeConstruct, instruction_iterator)) {
return; return;
} }

File diff suppressed because it is too large Load Diff

View File

@ -111,7 +111,7 @@ opt::BasicBlock::iterator GetIteratorForInstruction(
// Determines whether it is OK to insert an instruction with opcode |opcode| // Determines whether it is OK to insert an instruction with opcode |opcode|
// before |instruction_in_block|. // before |instruction_in_block|.
bool CanInsertOpcodeBeforeInstruction( bool CanInsertOpcodeBeforeInstruction(
SpvOp opcode, const opt::BasicBlock::iterator& instruction_in_block); spv::Op opcode, const opt::BasicBlock::iterator& instruction_in_block);
// Determines whether it is OK to make a synonym of |inst|. // Determines whether it is OK to make a synonym of |inst|.
// |transformation_context| is used to verify that the result id of |inst| // |transformation_context| is used to verify that the result id of |inst|
@ -170,8 +170,8 @@ uint32_t GetBoundForCompositeIndex(const opt::Instruction& composite_type_inst,
opt::IRContext* ir_context); opt::IRContext* ir_context);
// Returns memory semantics mask for specific storage class. // Returns memory semantics mask for specific storage class.
SpvMemorySemanticsMask GetMemorySemanticsForStorageClass( spv::MemorySemanticsMask GetMemorySemanticsForStorageClass(
SpvStorageClass storage_class); spv::StorageClass storage_class);
// Returns true if and only if |context| is valid, according to the validator // Returns true if and only if |context| is valid, according to the validator
// instantiated with |validator_options|. |consumer| is used for error // instantiated with |validator_options|. |consumer| is used for error
@ -258,18 +258,18 @@ uint32_t GetPointeeTypeIdFromPointerType(opt::IRContext* context,
// Given |pointer_type_inst|, which must be an OpTypePointer instruction, // Given |pointer_type_inst|, which must be an OpTypePointer instruction,
// returns the associated storage class. // returns the associated storage class.
SpvStorageClass GetStorageClassFromPointerType( spv::StorageClass GetStorageClassFromPointerType(
opt::Instruction* pointer_type_inst); opt::Instruction* pointer_type_inst);
// Given |pointer_type_id|, which must be the id of a pointer type, returns the // Given |pointer_type_id|, which must be the id of a pointer type, returns the
// associated storage class. // associated storage class.
SpvStorageClass GetStorageClassFromPointerType(opt::IRContext* context, spv::StorageClass GetStorageClassFromPointerType(opt::IRContext* context,
uint32_t pointer_type_id); uint32_t pointer_type_id);
// Returns the id of a pointer with pointee type |pointee_type_id| and storage // Returns the id of a pointer with pointee type |pointee_type_id| and storage
// class |storage_class|, if it exists, and 0 otherwise. // class |storage_class|, if it exists, and 0 otherwise.
uint32_t MaybeGetPointerType(opt::IRContext* context, uint32_t pointee_type_id, uint32_t MaybeGetPointerType(opt::IRContext* context, uint32_t pointee_type_id,
SpvStorageClass storage_class); spv::StorageClass storage_class);
// Given an instruction |inst| and an operand absolute index |absolute_index|, // Given an instruction |inst| and an operand absolute index |absolute_index|,
// returns the index of the operand restricted to the input operands. // returns the index of the operand restricted to the input operands.
@ -309,7 +309,7 @@ void AddVariableIdToEntryPointInterfaces(opt::IRContext* context, uint32_t id);
// Returns a pointer to the new global variable instruction. // Returns a pointer to the new global variable instruction.
opt::Instruction* AddGlobalVariable(opt::IRContext* context, uint32_t result_id, opt::Instruction* AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
uint32_t type_id, uint32_t type_id,
SpvStorageClass storage_class, spv::StorageClass storage_class,
uint32_t initializer_id); uint32_t initializer_id);
// Adds an instruction to the start of |function_id|, of the form: // Adds an instruction to the start of |function_id|, of the form:
@ -541,7 +541,7 @@ MapToRepeatedUInt32Pair(const std::map<uint32_t, uint32_t>& data);
// opcode |opcode| can be inserted, or nullptr if there is no such instruction. // opcode |opcode| can be inserted, or nullptr if there is no such instruction.
opt::Instruction* GetLastInsertBeforeInstruction(opt::IRContext* ir_context, opt::Instruction* GetLastInsertBeforeInstruction(opt::IRContext* ir_context,
uint32_t block_id, uint32_t block_id,
SpvOp opcode); spv::Op opcode);
// Checks whether various conditions hold related to the acceptability of // Checks whether various conditions hold related to the acceptability of
// replacing the id use at |use_in_operand_index| of |use_instruction| with a // replacing the id use at |use_in_operand_index| of |use_instruction| with a
@ -608,14 +608,14 @@ opt::Module::iterator GetFunctionIterator(opt::IRContext* ir_context,
// behaviour depending on the signedness of the operand at // behaviour depending on the signedness of the operand at
// |use_in_operand_index|. // |use_in_operand_index|.
// Assumes that the operand must be the id of an integer scalar or vector. // Assumes that the operand must be the id of an integer scalar or vector.
bool IsAgnosticToSignednessOfOperand(SpvOp opcode, bool IsAgnosticToSignednessOfOperand(spv::Op opcode,
uint32_t use_in_operand_index); uint32_t use_in_operand_index);
// Returns true if |type_id_1| and |type_id_2| represent compatible types // Returns true if |type_id_1| and |type_id_2| represent compatible types
// given the context of the instruction with |opcode| (i.e. we can replace // given the context of the instruction with |opcode| (i.e. we can replace
// an operand of |opcode| of the first type with an id of the second type // an operand of |opcode| of the first type with an id of the second type
// and vice-versa). // and vice-versa).
bool TypesAreCompatible(opt::IRContext* ir_context, SpvOp opcode, bool TypesAreCompatible(opt::IRContext* ir_context, spv::Op opcode,
uint32_t use_in_operand_index, uint32_t type_id_1, uint32_t use_in_operand_index, uint32_t type_id_1,
uint32_t type_id_2); uint32_t type_id_2);

View File

@ -40,8 +40,9 @@ opt::Instruction* FindInstruction(
"The skipped instruction count should only be incremented " "The skipped instruction count should only be incremented "
"after the instruction base has been found."); "after the instruction base has been found.");
} }
if (found_base && instruction.opcode() == if (found_base &&
instruction_descriptor.target_instruction_opcode()) { instruction.opcode() ==
spv::Op(instruction_descriptor.target_instruction_opcode())) {
if (num_ignored == instruction_descriptor.num_opcodes_to_ignore()) { if (num_ignored == instruction_descriptor.num_opcodes_to_ignore()) {
return &instruction; return &instruction;
} }
@ -52,11 +53,11 @@ opt::Instruction* FindInstruction(
} }
protobufs::InstructionDescriptor MakeInstructionDescriptor( protobufs::InstructionDescriptor MakeInstructionDescriptor(
uint32_t base_instruction_result_id, SpvOp target_instruction_opcode, uint32_t base_instruction_result_id, spv::Op target_instruction_opcode,
uint32_t num_opcodes_to_ignore) { uint32_t num_opcodes_to_ignore) {
protobufs::InstructionDescriptor result; protobufs::InstructionDescriptor result;
result.set_base_instruction_result_id(base_instruction_result_id); result.set_base_instruction_result_id(base_instruction_result_id);
result.set_target_instruction_opcode(target_instruction_opcode); result.set_target_instruction_opcode(uint32_t(target_instruction_opcode));
result.set_num_opcodes_to_ignore(num_opcodes_to_ignore); result.set_num_opcodes_to_ignore(num_opcodes_to_ignore);
return result; return result;
} }
@ -64,7 +65,7 @@ protobufs::InstructionDescriptor MakeInstructionDescriptor(
protobufs::InstructionDescriptor MakeInstructionDescriptor( protobufs::InstructionDescriptor MakeInstructionDescriptor(
const opt::BasicBlock& block, const opt::BasicBlock& block,
const opt::BasicBlock::const_iterator& inst_it) { const opt::BasicBlock::const_iterator& inst_it) {
const SpvOp opcode = const spv::Op opcode =
inst_it->opcode(); // The opcode of the instruction being described. inst_it->opcode(); // The opcode of the instruction being described.
uint32_t skip_count = 0; // The number of these opcodes we have skipped when uint32_t skip_count = 0; // The number of these opcodes we have skipped when
// searching backwards. // searching backwards.

View File

@ -32,7 +32,7 @@ opt::Instruction* FindInstruction(
// components. See the protobuf definition for details of what these // components. See the protobuf definition for details of what these
// components mean. // components mean.
protobufs::InstructionDescriptor MakeInstructionDescriptor( protobufs::InstructionDescriptor MakeInstructionDescriptor(
uint32_t base_instruction_result_id, SpvOp target_instruction_opcode, uint32_t base_instruction_result_id, spv::Op target_instruction_opcode,
uint32_t num_opcodes_to_ignore); uint32_t num_opcodes_to_ignore);
// Returns an instruction descriptor that describing the instruction at // Returns an instruction descriptor that describing the instruction at

View File

@ -20,10 +20,10 @@ namespace spvtools {
namespace fuzz { namespace fuzz {
protobufs::Instruction MakeInstructionMessage( protobufs::Instruction MakeInstructionMessage(
SpvOp opcode, uint32_t result_type_id, uint32_t result_id, spv::Op opcode, uint32_t result_type_id, uint32_t result_id,
const opt::Instruction::OperandList& input_operands) { const opt::Instruction::OperandList& input_operands) {
protobufs::Instruction result; protobufs::Instruction result;
result.set_opcode(opcode); result.set_opcode(uint32_t(opcode));
result.set_result_type_id(result_type_id); result.set_result_type_id(result_type_id);
result.set_result_id(result_id); result.set_result_id(result_id);
for (auto& operand : input_operands) { for (auto& operand : input_operands) {
@ -71,7 +71,7 @@ std::unique_ptr<opt::Instruction> InstructionFromMessage(
} }
// Create and return the instruction. // Create and return the instruction.
return MakeUnique<opt::Instruction>( return MakeUnique<opt::Instruction>(
ir_context, static_cast<SpvOp>(instruction_message.opcode()), ir_context, static_cast<spv::Op>(instruction_message.opcode()),
instruction_message.result_type_id(), instruction_message.result_id(), instruction_message.result_type_id(), instruction_message.result_id(),
in_operands); in_operands);
} }

View File

@ -26,7 +26,7 @@ namespace fuzz {
// Creates an Instruction protobuf message from its component parts. // Creates an Instruction protobuf message from its component parts.
protobufs::Instruction MakeInstructionMessage( protobufs::Instruction MakeInstructionMessage(
SpvOp opcode, uint32_t result_type_id, uint32_t result_id, spv::Op opcode, uint32_t result_type_id, uint32_t result_id,
const opt::Instruction::OperandList& input_operands); const opt::Instruction::OperandList& input_operands);
// Creates an Instruction protobuf message from a parsed instruction. // Creates an Instruction protobuf message from a parsed instruction.

View File

@ -63,7 +63,7 @@ bool TransformationAccessChain::IsApplicable(
} }
// The type must indeed be a pointer. // The type must indeed be a pointer.
auto pointer_type = ir_context->get_def_use_mgr()->GetDef(pointer->type_id()); auto pointer_type = ir_context->get_def_use_mgr()->GetDef(pointer->type_id());
if (pointer_type->opcode() != SpvOpTypePointer) { if (pointer_type->opcode() != spv::Op::OpTypePointer) {
return false; return false;
} }
@ -75,7 +75,7 @@ bool TransformationAccessChain::IsApplicable(
return false; return false;
} }
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction( if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
SpvOpAccessChain, instruction_to_insert_before)) { spv::Op::OpAccessChain, instruction_to_insert_before)) {
return false; return false;
} }
@ -83,8 +83,8 @@ bool TransformationAccessChain::IsApplicable(
// we do not want to allow accessing such pointers. This might be acceptable // we do not want to allow accessing such pointers. This might be acceptable
// in dead blocks, but we conservatively avoid it. // in dead blocks, but we conservatively avoid it.
switch (pointer->opcode()) { switch (pointer->opcode()) {
case SpvOpConstantNull: case spv::Op::OpConstantNull:
case SpvOpUndef: case spv::Op::OpUndef:
assert( assert(
false && false &&
"Access chains should not be created from null/undefined pointers"); "Access chains should not be created from null/undefined pointers");
@ -117,7 +117,7 @@ bool TransformationAccessChain::IsApplicable(
// Check whether the object is a struct. // Check whether the object is a struct.
if (ir_context->get_def_use_mgr()->GetDef(subobject_type_id)->opcode() == if (ir_context->get_def_use_mgr()->GetDef(subobject_type_id)->opcode() ==
SpvOpTypeStruct) { spv::Op::OpTypeStruct) {
// It is a struct: we need to retrieve the integer value. // It is a struct: we need to retrieve the integer value.
bool successful; bool successful;
@ -202,7 +202,7 @@ bool TransformationAccessChain::IsApplicable(
// associated with pointers to isomorphic structs being regarded as the same. // associated with pointers to isomorphic structs being regarded as the same.
return fuzzerutil::MaybeGetPointerType( return fuzzerutil::MaybeGetPointerType(
ir_context, subobject_type_id, ir_context, subobject_type_id,
static_cast<SpvStorageClass>( static_cast<spv::StorageClass>(
pointer_type->GetSingleWordInOperand(0))) != 0; pointer_type->GetSingleWordInOperand(0))) != 0;
} }
@ -243,7 +243,7 @@ void TransformationAccessChain::Apply(
// Check whether the object is a struct. // Check whether the object is a struct.
if (ir_context->get_def_use_mgr()->GetDef(subobject_type_id)->opcode() == if (ir_context->get_def_use_mgr()->GetDef(subobject_type_id)->opcode() ==
SpvOpTypeStruct) { spv::Op::OpTypeStruct) {
// It is a struct: we need to retrieve the integer value. // It is a struct: we need to retrieve the integer value.
index_value = index_value =
@ -290,7 +290,8 @@ void TransformationAccessChain::Apply(
// %fresh_ids.first = OpULessThanEqual %bool %int_id %bound_minus_one. // %fresh_ids.first = OpULessThanEqual %bool %int_id %bound_minus_one.
fuzzerutil::UpdateModuleIdBound(ir_context, fresh_ids.first()); fuzzerutil::UpdateModuleIdBound(ir_context, fresh_ids.first());
auto comparison_instruction = MakeUnique<opt::Instruction>( auto comparison_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpULessThanEqual, bool_type_id, fresh_ids.first(), ir_context, spv::Op::OpULessThanEqual, bool_type_id,
fresh_ids.first(),
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {index_instruction->result_id()}}, {{SPV_OPERAND_TYPE_ID, {index_instruction->result_id()}},
{SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}})); {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}}));
@ -306,7 +307,7 @@ void TransformationAccessChain::Apply(
// %bound_minus_one // %bound_minus_one
fuzzerutil::UpdateModuleIdBound(ir_context, fresh_ids.second()); fuzzerutil::UpdateModuleIdBound(ir_context, fresh_ids.second());
auto select_instruction = MakeUnique<opt::Instruction>( auto select_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpSelect, int_type_inst->result_id(), ir_context, spv::Op::OpSelect, int_type_inst->result_id(),
fresh_ids.second(), fresh_ids.second(),
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {fresh_ids.first()}}, {{SPV_OPERAND_TYPE_ID, {fresh_ids.first()}},
@ -334,13 +335,14 @@ void TransformationAccessChain::Apply(
// of the original pointer. // of the original pointer.
uint32_t result_type = fuzzerutil::MaybeGetPointerType( uint32_t result_type = fuzzerutil::MaybeGetPointerType(
ir_context, subobject_type_id, ir_context, subobject_type_id,
static_cast<SpvStorageClass>(pointer_type->GetSingleWordInOperand(0))); static_cast<spv::StorageClass>(pointer_type->GetSingleWordInOperand(0)));
// Add the access chain instruction to the module, and update the module's // Add the access chain instruction to the module, and update the module's
// id bound. // id bound.
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id()); fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
auto access_chain_instruction = MakeUnique<opt::Instruction>( auto access_chain_instruction =
ir_context, SpvOpAccessChain, result_type, message_.fresh_id(), operands); MakeUnique<opt::Instruction>(ir_context, spv::Op::OpAccessChain,
result_type, message_.fresh_id(), operands);
auto access_chain_instruction_ptr = access_chain_instruction.get(); auto access_chain_instruction_ptr = access_chain_instruction.get();
instruction_to_insert_before->InsertBefore( instruction_to_insert_before->InsertBefore(
std::move(access_chain_instruction)); std::move(access_chain_instruction));
@ -367,7 +369,7 @@ std::pair<bool, uint32_t> TransformationAccessChain::GetStructIndexValue(
opt::IRContext* ir_context, uint32_t index_id, opt::IRContext* ir_context, uint32_t index_id,
uint32_t object_type_id) const { uint32_t object_type_id) const {
assert(ir_context->get_def_use_mgr()->GetDef(object_type_id)->opcode() == assert(ir_context->get_def_use_mgr()->GetDef(object_type_id)->opcode() ==
SpvOpTypeStruct && spv::Op::OpTypeStruct &&
"Precondition: the type must be a struct type."); "Precondition: the type must be a struct type.");
if (!ValidIndexToComposite(ir_context, index_id, object_type_id)) { if (!ValidIndexToComposite(ir_context, index_id, object_type_id)) {
return {false, 0}; return {false, 0};
@ -408,14 +410,14 @@ bool TransformationAccessChain::ValidIndexToComposite(
// The index type must be 32-bit integer. // The index type must be 32-bit integer.
auto index_type = auto index_type =
ir_context->get_def_use_mgr()->GetDef(index_instruction->type_id()); ir_context->get_def_use_mgr()->GetDef(index_instruction->type_id());
if (index_type->opcode() != SpvOpTypeInt || if (index_type->opcode() != spv::Op::OpTypeInt ||
index_type->GetSingleWordInOperand(0) != 32) { index_type->GetSingleWordInOperand(0) != 32) {
return false; return false;
} }
// If the object being traversed is a struct, the id must correspond to an // If the object being traversed is a struct, the id must correspond to an
// in-bound constant. // in-bound constant.
if (object_type_def->opcode() == SpvOpTypeStruct) { if (object_type_def->opcode() == spv::Op::OpTypeStruct) {
if (!spvOpcodeIsConstant(index_instruction->opcode())) { if (!spvOpcodeIsConstant(index_instruction->opcode())) {
return false; return false;
} }

View File

@ -87,10 +87,10 @@ void TransformationAddBitInstructionSynonym::Apply(
// synonym fact. The helper function should take care of invalidating // synonym fact. The helper function should take care of invalidating
// analyses before adding facts. // analyses before adding facts.
switch (bit_instruction->opcode()) { switch (bit_instruction->opcode()) {
case SpvOpBitwiseOr: case spv::Op::OpBitwiseOr:
case SpvOpBitwiseXor: case spv::Op::OpBitwiseXor:
case SpvOpBitwiseAnd: case spv::Op::OpBitwiseAnd:
case SpvOpNot: case spv::Op::OpNot:
AddOpBitwiseOrOpNotSynonym(ir_context, transformation_context, AddOpBitwiseOrOpNotSynonym(ir_context, transformation_context,
bit_instruction); bit_instruction);
break; break;
@ -106,10 +106,10 @@ bool TransformationAddBitInstructionSynonym::IsInstructionSupported(
// Right now we only support certain operations. When this issue is addressed // Right now we only support certain operations. When this issue is addressed
// the following conditional can use the function |spvOpcodeIsBit|. // the following conditional can use the function |spvOpcodeIsBit|.
// |instruction| must be defined and must be a supported bit instruction. // |instruction| must be defined and must be a supported bit instruction.
if (!instruction || (instruction->opcode() != SpvOpBitwiseOr && if (!instruction || (instruction->opcode() != spv::Op::OpBitwiseOr &&
instruction->opcode() != SpvOpBitwiseXor && instruction->opcode() != spv::Op::OpBitwiseXor &&
instruction->opcode() != SpvOpBitwiseAnd && instruction->opcode() != spv::Op::OpBitwiseAnd &&
instruction->opcode() != SpvOpNot)) { instruction->opcode() != spv::Op::OpNot)) {
return false; return false;
} }
@ -119,7 +119,7 @@ bool TransformationAddBitInstructionSynonym::IsInstructionSupported(
return false; return false;
} }
if (instruction->opcode() == SpvOpNot) { if (instruction->opcode() == spv::Op::OpNot) {
auto operand = instruction->GetInOperand(0).words[0]; auto operand = instruction->GetInOperand(0).words[0];
auto operand_inst = ir_context->get_def_use_mgr()->GetDef(operand); auto operand_inst = ir_context->get_def_use_mgr()->GetDef(operand);
auto operand_type = auto operand_type =
@ -171,10 +171,10 @@ uint32_t TransformationAddBitInstructionSynonym::GetRequiredFreshIdCount(
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3557): // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3557):
// Right now, only certain operations are supported. // Right now, only certain operations are supported.
switch (bit_instruction->opcode()) { switch (bit_instruction->opcode()) {
case SpvOpBitwiseOr: case spv::Op::OpBitwiseOr:
case SpvOpBitwiseXor: case spv::Op::OpBitwiseXor:
case SpvOpBitwiseAnd: case spv::Op::OpBitwiseAnd:
case SpvOpNot: case spv::Op::OpNot:
return (2 + bit_instruction->NumInOperands()) * return (2 + bit_instruction->NumInOperands()) *
ir_context->get_type_mgr() ir_context->get_type_mgr()
->GetType(bit_instruction->type_id()) ->GetType(bit_instruction->type_id())
@ -220,7 +220,7 @@ void TransformationAddBitInstructionSynonym::AddOpBitwiseOrOpNotSynonym(
for (auto operand = bit_instruction->begin() + 2; for (auto operand = bit_instruction->begin() + 2;
operand != bit_instruction->end(); operand++) { operand != bit_instruction->end(); operand++) {
auto bit_extract = auto bit_extract =
opt::Instruction(ir_context, SpvOpBitFieldUExtract, opt::Instruction(ir_context, spv::Op::OpBitFieldUExtract,
bit_instruction->type_id(), *fresh_id++, bit_instruction->type_id(), *fresh_id++,
{{SPV_OPERAND_TYPE_ID, operand->words}, {{SPV_OPERAND_TYPE_ID, operand->words},
{SPV_OPERAND_TYPE_ID, {offset}}, {SPV_OPERAND_TYPE_ID, {offset}},
@ -246,12 +246,13 @@ void TransformationAddBitInstructionSynonym::AddOpBitwiseOrOpNotSynonym(
// first two bits of the result. // first two bits of the result.
uint32_t offset = fuzzerutil::MaybeGetIntegerConstant( uint32_t offset = fuzzerutil::MaybeGetIntegerConstant(
ir_context, *transformation_context, {1}, 32, false, false); ir_context, *transformation_context, {1}, 32, false, false);
auto bit_insert = opt::Instruction( auto bit_insert =
ir_context, SpvOpBitFieldInsert, bit_instruction->type_id(), *fresh_id++, opt::Instruction(ir_context, spv::Op::OpBitFieldInsert,
{{SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[0]}}, bit_instruction->type_id(), *fresh_id++,
{SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[1]}}, {{SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[0]}},
{SPV_OPERAND_TYPE_ID, {offset}}, {SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[1]}},
{SPV_OPERAND_TYPE_ID, {count}}}); {SPV_OPERAND_TYPE_ID, {offset}},
{SPV_OPERAND_TYPE_ID, {count}}});
bit_instruction->InsertBefore(MakeUnique<opt::Instruction>(bit_insert)); bit_instruction->InsertBefore(MakeUnique<opt::Instruction>(bit_insert));
fuzzerutil::UpdateModuleIdBound(ir_context, bit_insert.result_id()); fuzzerutil::UpdateModuleIdBound(ir_context, bit_insert.result_id());
@ -260,7 +261,7 @@ void TransformationAddBitInstructionSynonym::AddOpBitwiseOrOpNotSynonym(
offset = fuzzerutil::MaybeGetIntegerConstant( offset = fuzzerutil::MaybeGetIntegerConstant(
ir_context, *transformation_context, {i}, 32, false, false); ir_context, *transformation_context, {i}, 32, false, false);
bit_insert = opt::Instruction( bit_insert = opt::Instruction(
ir_context, SpvOpBitFieldInsert, bit_instruction->type_id(), ir_context, spv::Op::OpBitFieldInsert, bit_instruction->type_id(),
*fresh_id++, *fresh_id++,
{{SPV_OPERAND_TYPE_ID, {bit_insert.result_id()}}, {{SPV_OPERAND_TYPE_ID, {bit_insert.result_id()}},
{SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[i]}}, {SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[i]}},

View File

@ -43,7 +43,8 @@ void TransformationAddConstantBoolean::Apply(
// Add the boolean constant to the module, ensuring the module's id bound is // Add the boolean constant to the module, ensuring the module's id bound is
// high enough. // high enough.
auto new_instruction = MakeUnique<opt::Instruction>( auto new_instruction = MakeUnique<opt::Instruction>(
ir_context, message_.is_true() ? SpvOpConstantTrue : SpvOpConstantFalse, ir_context,
message_.is_true() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse,
fuzzerutil::MaybeGetBoolType(ir_context), message_.fresh_id(), fuzzerutil::MaybeGetBoolType(ir_context), message_.fresh_id(),
opt::Instruction::OperandList()); opt::Instruction::OperandList());
auto new_instruction_ptr = new_instruction.get(); auto new_instruction_ptr = new_instruction.get();

View File

@ -53,7 +53,7 @@ bool TransformationAddConstantComposite::IsApplicable(
// struct - whether its decorations are OK. // struct - whether its decorations are OK.
std::vector<uint32_t> constituent_type_ids; std::vector<uint32_t> constituent_type_ids;
switch (composite_type_instruction->opcode()) { switch (composite_type_instruction->opcode()) {
case SpvOpTypeArray: case spv::Op::OpTypeArray:
for (uint32_t index = 0; for (uint32_t index = 0;
index < index <
fuzzerutil::GetArraySize(*composite_type_instruction, ir_context); fuzzerutil::GetArraySize(*composite_type_instruction, ir_context);
@ -62,8 +62,8 @@ bool TransformationAddConstantComposite::IsApplicable(
composite_type_instruction->GetSingleWordInOperand(0)); composite_type_instruction->GetSingleWordInOperand(0));
} }
break; break;
case SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
case SpvOpTypeVector: case spv::Op::OpTypeVector:
for (uint32_t index = 0; for (uint32_t index = 0;
index < composite_type_instruction->GetSingleWordInOperand(1); index < composite_type_instruction->GetSingleWordInOperand(1);
index++) { index++) {
@ -71,7 +71,7 @@ bool TransformationAddConstantComposite::IsApplicable(
composite_type_instruction->GetSingleWordInOperand(0)); composite_type_instruction->GetSingleWordInOperand(0));
} }
break; break;
case SpvOpTypeStruct: case spv::Op::OpTypeStruct:
// We do not create constants of structs decorated with Block nor // We do not create constants of structs decorated with Block nor
// BufferBlock. The SPIR-V spec does not explicitly disallow this, but it // BufferBlock. The SPIR-V spec does not explicitly disallow this, but it
// seems like a strange thing to do, so we disallow it to avoid triggering // seems like a strange thing to do, so we disallow it to avoid triggering
@ -120,7 +120,7 @@ void TransformationAddConstantComposite::Apply(
in_operands.push_back({SPV_OPERAND_TYPE_ID, {constituent_id}}); in_operands.push_back({SPV_OPERAND_TYPE_ID, {constituent_id}});
} }
auto new_instruction = MakeUnique<opt::Instruction>( auto new_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpConstantComposite, message_.type_id(), ir_context, spv::Op::OpConstantComposite, message_.type_id(),
message_.fresh_id(), in_operands); message_.fresh_id(), in_operands);
auto new_instruction_ptr = new_instruction.get(); auto new_instruction_ptr = new_instruction.get();
ir_context->module()->AddGlobalValue(std::move(new_instruction)); ir_context->module()->AddGlobalValue(std::move(new_instruction));

View File

@ -48,8 +48,8 @@ bool TransformationAddConstantNull::IsApplicable(
void TransformationAddConstantNull::Apply( void TransformationAddConstantNull::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const { opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
auto new_instruction = MakeUnique<opt::Instruction>( auto new_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpConstantNull, message_.type_id(), message_.fresh_id(), ir_context, spv::Op::OpConstantNull, message_.type_id(),
opt::Instruction::OperandList()); message_.fresh_id(), opt::Instruction::OperandList());
auto new_instruction_ptr = new_instruction.get(); auto new_instruction_ptr = new_instruction.get();
ir_context->module()->AddGlobalValue(std::move(new_instruction)); ir_context->module()->AddGlobalValue(std::move(new_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id()); fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());

View File

@ -65,7 +65,7 @@ void TransformationAddConstantScalar::Apply(
opt::IRContext* ir_context, opt::IRContext* ir_context,
TransformationContext* transformation_context) const { TransformationContext* transformation_context) const {
auto new_instruction = MakeUnique<opt::Instruction>( auto new_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpConstant, message_.type_id(), message_.fresh_id(), ir_context, spv::Op::OpConstant, message_.type_id(), message_.fresh_id(),
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_LITERAL_INTEGER, {{SPV_OPERAND_TYPE_LITERAL_INTEGER,
std::vector<uint32_t>(message_.word().begin(), std::vector<uint32_t>(message_.word().begin(),

View File

@ -27,12 +27,12 @@ TransformationAddCopyMemory::TransformationAddCopyMemory(
TransformationAddCopyMemory::TransformationAddCopyMemory( TransformationAddCopyMemory::TransformationAddCopyMemory(
const protobufs::InstructionDescriptor& instruction_descriptor, const protobufs::InstructionDescriptor& instruction_descriptor,
uint32_t fresh_id, uint32_t source_id, SpvStorageClass storage_class, uint32_t fresh_id, uint32_t source_id, spv::StorageClass storage_class,
uint32_t initializer_id) { uint32_t initializer_id) {
*message_.mutable_instruction_descriptor() = instruction_descriptor; *message_.mutable_instruction_descriptor() = instruction_descriptor;
message_.set_fresh_id(fresh_id); message_.set_fresh_id(fresh_id);
message_.set_source_id(source_id); message_.set_source_id(source_id);
message_.set_storage_class(storage_class); message_.set_storage_class(uint32_t(storage_class));
message_.set_initializer_id(initializer_id); message_.set_initializer_id(initializer_id);
} }
@ -53,7 +53,8 @@ bool TransformationAddCopyMemory::IsApplicable(
// Check that we can insert OpCopyMemory before |instruction_descriptor|. // Check that we can insert OpCopyMemory before |instruction_descriptor|.
auto iter = fuzzerutil::GetIteratorForInstruction( auto iter = fuzzerutil::GetIteratorForInstruction(
ir_context->get_instr_block(inst), inst); ir_context->get_instr_block(inst), inst);
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyMemory, iter)) { if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpCopyMemory,
iter)) {
return false; return false;
} }
@ -65,8 +66,10 @@ bool TransformationAddCopyMemory::IsApplicable(
} }
// |storage_class| is either Function or Private. // |storage_class| is either Function or Private.
if (message_.storage_class() != SpvStorageClassFunction && if (spv::StorageClass(message_.storage_class()) !=
message_.storage_class() != SpvStorageClassPrivate) { spv::StorageClass::Function &&
spv::StorageClass(message_.storage_class()) !=
spv::StorageClass::Private) {
return false; return false;
} }
@ -76,7 +79,7 @@ bool TransformationAddCopyMemory::IsApplicable(
// OpTypePointer with |message_.storage_class| exists. // OpTypePointer with |message_.storage_class| exists.
if (!fuzzerutil::MaybeGetPointerType( if (!fuzzerutil::MaybeGetPointerType(
ir_context, pointee_type_id, ir_context, pointee_type_id,
static_cast<SpvStorageClass>(message_.storage_class()))) { static_cast<spv::StorageClass>(message_.storage_class()))) {
return false; return false;
} }
@ -103,20 +106,20 @@ void TransformationAddCopyMemory::Apply(
ir_context->get_instr_block(insert_before_inst); ir_context->get_instr_block(insert_before_inst);
// Add global or local variable to copy memory into. // Add global or local variable to copy memory into.
auto storage_class = static_cast<SpvStorageClass>(message_.storage_class()); auto storage_class = static_cast<spv::StorageClass>(message_.storage_class());
auto type_id = fuzzerutil::MaybeGetPointerType( auto type_id = fuzzerutil::MaybeGetPointerType(
ir_context, ir_context,
fuzzerutil::GetPointeeTypeIdFromPointerType( fuzzerutil::GetPointeeTypeIdFromPointerType(
ir_context, fuzzerutil::GetTypeId(ir_context, message_.source_id())), ir_context, fuzzerutil::GetTypeId(ir_context, message_.source_id())),
storage_class); storage_class);
if (storage_class == SpvStorageClassPrivate) { if (storage_class == spv::StorageClass::Private) {
opt::Instruction* new_global = opt::Instruction* new_global =
fuzzerutil::AddGlobalVariable(ir_context, message_.fresh_id(), type_id, fuzzerutil::AddGlobalVariable(ir_context, message_.fresh_id(), type_id,
storage_class, message_.initializer_id()); storage_class, message_.initializer_id());
ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_global); ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_global);
} else { } else {
assert(storage_class == SpvStorageClassFunction && assert(storage_class == spv::StorageClass::Function &&
"Storage class can be either Private or Function"); "Storage class can be either Private or Function");
opt::Function* enclosing_function = enclosing_block->GetParent(); opt::Function* enclosing_function = enclosing_block->GetParent();
opt::Instruction* new_local = fuzzerutil::AddLocalVariable( opt::Instruction* new_local = fuzzerutil::AddLocalVariable(
@ -130,7 +133,7 @@ void TransformationAddCopyMemory::Apply(
enclosing_block, insert_before_inst); enclosing_block, insert_before_inst);
auto new_instruction = MakeUnique<opt::Instruction>( auto new_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpCopyMemory, 0, 0, ir_context, spv::Op::OpCopyMemory, 0, 0,
opt::Instruction::OperandList{ opt::Instruction::OperandList{
{SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}, {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}},
{SPV_OPERAND_TYPE_ID, {message_.source_id()}}}); {SPV_OPERAND_TYPE_ID, {message_.source_id()}}});
@ -160,7 +163,8 @@ protobufs::Transformation TransformationAddCopyMemory::ToMessage() const {
bool TransformationAddCopyMemory::IsInstructionSupported( bool TransformationAddCopyMemory::IsInstructionSupported(
opt::IRContext* ir_context, opt::Instruction* inst) { opt::IRContext* ir_context, opt::Instruction* inst) {
if (!inst->result_id() || !inst->type_id() || if (!inst->result_id() || !inst->type_id() ||
inst->opcode() == SpvOpConstantNull || inst->opcode() == SpvOpUndef) { inst->opcode() == spv::Op::OpConstantNull ||
inst->opcode() == spv::Op::OpUndef) {
return false; return false;
} }

View File

@ -30,7 +30,7 @@ class TransformationAddCopyMemory : public Transformation {
TransformationAddCopyMemory( TransformationAddCopyMemory(
const protobufs::InstructionDescriptor& instruction_descriptor, const protobufs::InstructionDescriptor& instruction_descriptor,
uint32_t fresh_id, uint32_t source_id, SpvStorageClass storage_class, uint32_t fresh_id, uint32_t source_id, spv::StorageClass storage_class,
uint32_t initializer_id); uint32_t initializer_id);
// - |instruction_descriptor| must point to a valid instruction in the module. // - |instruction_descriptor| must point to a valid instruction in the module.

View File

@ -61,7 +61,7 @@ bool TransformationAddDeadBlock::IsApplicable(
} }
// It must end with OpBranch. // It must end with OpBranch.
if (existing_block->terminator()->opcode() != SpvOpBranch) { if (existing_block->terminator()->opcode() != spv::Op::OpBranch) {
return false; return false;
} }
@ -122,27 +122,27 @@ void TransformationAddDeadBlock::Apply(
auto enclosing_function = existing_block->GetParent(); auto enclosing_function = existing_block->GetParent();
std::unique_ptr<opt::BasicBlock> new_block = std::unique_ptr<opt::BasicBlock> new_block =
MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>( MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
ir_context, SpvOpLabel, 0, message_.fresh_id(), ir_context, spv::Op::OpLabel, 0, message_.fresh_id(),
opt::Instruction::OperandList())); opt::Instruction::OperandList()));
new_block->AddInstruction(MakeUnique<opt::Instruction>( new_block->AddInstruction(MakeUnique<opt::Instruction>(
ir_context, SpvOpBranch, 0, 0, ir_context, spv::Op::OpBranch, 0, 0,
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {successor_block_id}}}))); {{SPV_OPERAND_TYPE_ID, {successor_block_id}}})));
// Turn the original block into a selection merge, with its original successor // Turn the original block into a selection merge, with its original successor
// as the merge block. // as the merge block.
existing_block->terminator()->InsertBefore(MakeUnique<opt::Instruction>( existing_block->terminator()->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpSelectionMerge, 0, 0, ir_context, spv::Op::OpSelectionMerge, 0, 0,
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {successor_block_id}}, {{SPV_OPERAND_TYPE_ID, {successor_block_id}},
{SPV_OPERAND_TYPE_SELECTION_CONTROL, {SPV_OPERAND_TYPE_SELECTION_CONTROL,
{SpvSelectionControlMaskNone}}}))); {uint32_t(spv::SelectionControlMask::MaskNone)}}})));
// Change the original block's terminator to be a conditional branch on the // Change the original block's terminator to be a conditional branch on the
// given boolean, with the original successor and the new successor as branch // given boolean, with the original successor and the new successor as branch
// targets, and such that at runtime control will always transfer to the // targets, and such that at runtime control will always transfer to the
// original successor. // original successor.
existing_block->terminator()->SetOpcode(SpvOpBranchConditional); existing_block->terminator()->SetOpcode(spv::Op::OpBranchConditional);
existing_block->terminator()->SetInOperands( existing_block->terminator()->SetInOperands(
{{SPV_OPERAND_TYPE_ID, {bool_id}}, {{SPV_OPERAND_TYPE_ID, {bool_id}},
{SPV_OPERAND_TYPE_ID, {SPV_OPERAND_TYPE_ID,

View File

@ -142,7 +142,7 @@ bool TransformationAddDeadBreak::IsApplicable(
} }
// Check that |message_.from_block| ends with an unconditional branch. // Check that |message_.from_block| ends with an unconditional branch.
if (bb_from->terminator()->opcode() != SpvOpBranch) { if (bb_from->terminator()->opcode() != spv::Op::OpBranch) {
// The block associated with the id does not end with an unconditional // The block associated with the id does not end with an unconditional
// branch. // branch.
return false; return false;

View File

@ -55,7 +55,7 @@ bool TransformationAddDeadContinue::IsApplicable(
} }
// Check that |message_.from_block| ends with an unconditional branch. // Check that |message_.from_block| ends with an unconditional branch.
if (bb_from->terminator()->opcode() != SpvOpBranch) { if (bb_from->terminator()->opcode() != spv::Op::OpBranch) {
// The block associated with the id does not end with an unconditional // The block associated with the id does not end with an unconditional
// branch. // branch.
return false; return false;

View File

@ -28,17 +28,17 @@ TransformationAddEarlyTerminatorWrapper::
TransformationAddEarlyTerminatorWrapper:: TransformationAddEarlyTerminatorWrapper::
TransformationAddEarlyTerminatorWrapper(uint32_t function_fresh_id, TransformationAddEarlyTerminatorWrapper(uint32_t function_fresh_id,
uint32_t label_fresh_id, uint32_t label_fresh_id,
SpvOp opcode) { spv::Op opcode) {
message_.set_function_fresh_id(function_fresh_id); message_.set_function_fresh_id(function_fresh_id);
message_.set_label_fresh_id(label_fresh_id); message_.set_label_fresh_id(label_fresh_id);
message_.set_opcode(opcode); message_.set_opcode(uint32_t(opcode));
} }
bool TransformationAddEarlyTerminatorWrapper::IsApplicable( bool TransformationAddEarlyTerminatorWrapper::IsApplicable(
opt::IRContext* ir_context, const TransformationContext& /*unused*/) const { opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
assert((message_.opcode() == SpvOpKill || assert((spv::Op(message_.opcode()) == spv::Op::OpKill ||
message_.opcode() == SpvOpUnreachable || spv::Op(message_.opcode()) == spv::Op::OpUnreachable ||
message_.opcode() == SpvOpTerminateInvocation) && spv::Op(message_.opcode()) == spv::Op::OpTerminateInvocation) &&
"Invalid opcode."); "Invalid opcode.");
if (!fuzzerutil::IsFreshId(ir_context, message_.function_fresh_id())) { if (!fuzzerutil::IsFreshId(ir_context, message_.function_fresh_id())) {
@ -66,26 +66,29 @@ void TransformationAddEarlyTerminatorWrapper::Apply(
// %label_fresh_id = OpLabel // %label_fresh_id = OpLabel
// OpKill|Unreachable|TerminateInvocation // OpKill|Unreachable|TerminateInvocation
auto basic_block = MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>( auto basic_block = MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
ir_context, SpvOpLabel, 0, message_.label_fresh_id(), ir_context, spv::Op::OpLabel, 0, message_.label_fresh_id(),
opt::Instruction::OperandList())); opt::Instruction::OperandList()));
basic_block->AddInstruction(MakeUnique<opt::Instruction>( basic_block->AddInstruction(MakeUnique<opt::Instruction>(
ir_context, static_cast<SpvOp>(message_.opcode()), 0, 0, ir_context, static_cast<spv::Op>(message_.opcode()), 0, 0,
opt::Instruction::OperandList())); opt::Instruction::OperandList()));
// Create a zero-argument void function. // Create a zero-argument void function.
auto void_type_id = fuzzerutil::MaybeGetVoidType(ir_context); auto void_type_id = fuzzerutil::MaybeGetVoidType(ir_context);
auto function = MakeUnique<opt::Function>(MakeUnique<opt::Instruction>( auto function = MakeUnique<opt::Function>(MakeUnique<opt::Instruction>(
ir_context, SpvOpFunction, void_type_id, message_.function_fresh_id(), ir_context, spv::Op::OpFunction, void_type_id,
message_.function_fresh_id(),
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}}, {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
{uint32_t(spv::FunctionControlMask::MaskNone)}},
{SPV_OPERAND_TYPE_TYPE_ID, {SPV_OPERAND_TYPE_TYPE_ID,
{fuzzerutil::FindFunctionType(ir_context, {void_type_id})}}}))); {fuzzerutil::FindFunctionType(ir_context, {void_type_id})}}})));
// Add the basic block to the function as the sole block, and add the function // Add the basic block to the function as the sole block, and add the function
// to the module. // to the module.
function->AddBasicBlock(std::move(basic_block)); function->AddBasicBlock(std::move(basic_block));
function->SetFunctionEnd(MakeUnique<opt::Instruction>( function->SetFunctionEnd(
ir_context, SpvOpFunctionEnd, 0, 0, opt::Instruction::OperandList())); MakeUnique<opt::Instruction>(ir_context, spv::Op::OpFunctionEnd, 0, 0,
opt::Instruction::OperandList()));
ir_context->module()->AddFunction(std::move(function)); ir_context->module()->AddFunction(std::move(function));
ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);

View File

@ -30,7 +30,7 @@ class TransformationAddEarlyTerminatorWrapper : public Transformation {
TransformationAddEarlyTerminatorWrapper(uint32_t function_fresh_id, TransformationAddEarlyTerminatorWrapper(uint32_t function_fresh_id,
uint32_t label_fresh_id, uint32_t label_fresh_id,
SpvOp opcode); spv::Op opcode);
// - |message_.function_fresh_id| and |message_.label_fresh_id| must be fresh // - |message_.function_fresh_id| and |message_.label_fresh_id| must be fresh
// and distinct. // and distinct.

View File

@ -178,7 +178,7 @@ void TransformationAddFunction::Apply(
} }
ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone); ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
assert(message_.instruction(0).opcode() == SpvOpFunction && assert(spv::Op(message_.instruction(0).opcode()) == spv::Op::OpFunction &&
"The first instruction of an 'add function' transformation must be " "The first instruction of an 'add function' transformation must be "
"OpFunction."); "OpFunction.");
@ -189,7 +189,7 @@ void TransformationAddFunction::Apply(
} else { } else {
// Inform the fact manager that all blocks in the function are dead. // Inform the fact manager that all blocks in the function are dead.
for (auto& inst : message_.instruction()) { for (auto& inst : message_.instruction()) {
if (inst.opcode() == SpvOpLabel) { if (spv::Op(inst.opcode()) == spv::Op::OpLabel) {
transformation_context->GetFactManager()->AddFactBlockIsDead( transformation_context->GetFactManager()->AddFactBlockIsDead(
inst.result_id()); inst.result_id());
} }
@ -202,16 +202,16 @@ void TransformationAddFunction::Apply(
// parameters to other functions knowing that it is OK if they get // parameters to other functions knowing that it is OK if they get
// over-written. // over-written.
for (auto& instruction : message_.instruction()) { for (auto& instruction : message_.instruction()) {
switch (instruction.opcode()) { switch (spv::Op(instruction.opcode())) {
case SpvOpFunctionParameter: case spv::Op::OpFunctionParameter:
if (ir_context->get_def_use_mgr() if (ir_context->get_def_use_mgr()
->GetDef(instruction.result_type_id()) ->GetDef(instruction.result_type_id())
->opcode() == SpvOpTypePointer) { ->opcode() == spv::Op::OpTypePointer) {
transformation_context->GetFactManager() transformation_context->GetFactManager()
->AddFactValueOfPointeeIsIrrelevant(instruction.result_id()); ->AddFactValueOfPointeeIsIrrelevant(instruction.result_id());
} }
break; break;
case SpvOpVariable: case spv::Op::OpVariable:
transformation_context->GetFactManager() transformation_context->GetFactManager()
->AddFactValueOfPointeeIsIrrelevant(instruction.result_id()); ->AddFactValueOfPointeeIsIrrelevant(instruction.result_id());
break; break;
@ -239,7 +239,7 @@ bool TransformationAddFunction::TryToAddFunction(
// A function must start with OpFunction. // A function must start with OpFunction.
auto function_begin = message_.instruction(0); auto function_begin = message_.instruction(0);
if (function_begin.opcode() != SpvOpFunction) { if (spv::Op(function_begin.opcode()) != spv::Op::OpFunction) {
return false; return false;
} }
@ -256,8 +256,8 @@ bool TransformationAddFunction::TryToAddFunction(
// Iterate through all function parameter instructions, adding parameters to // Iterate through all function parameter instructions, adding parameters to
// the new function. // the new function.
while (instruction_index < num_instructions && while (instruction_index < num_instructions &&
message_.instruction(instruction_index).opcode() == spv::Op(message_.instruction(instruction_index).opcode()) ==
SpvOpFunctionParameter) { spv::Op::OpFunctionParameter) {
new_function->AddParameter(InstructionFromMessage( new_function->AddParameter(InstructionFromMessage(
ir_context, message_.instruction(instruction_index))); ir_context, message_.instruction(instruction_index)));
instruction_index++; instruction_index++;
@ -265,16 +265,19 @@ bool TransformationAddFunction::TryToAddFunction(
// After the parameters, there needs to be a label. // After the parameters, there needs to be a label.
if (instruction_index == num_instructions || if (instruction_index == num_instructions ||
message_.instruction(instruction_index).opcode() != SpvOpLabel) { spv::Op(message_.instruction(instruction_index).opcode()) !=
spv::Op::OpLabel) {
return false; return false;
} }
// Iterate through the instructions block by block until the end of the // Iterate through the instructions block by block until the end of the
// function is reached. // function is reached.
while (instruction_index < num_instructions && while (instruction_index < num_instructions &&
message_.instruction(instruction_index).opcode() != SpvOpFunctionEnd) { spv::Op(message_.instruction(instruction_index).opcode()) !=
spv::Op::OpFunctionEnd) {
// Invariant: we should always be at a label instruction at this point. // Invariant: we should always be at a label instruction at this point.
assert(message_.instruction(instruction_index).opcode() == SpvOpLabel); assert(spv::Op(message_.instruction(instruction_index).opcode()) ==
spv::Op::OpLabel);
// Make a basic block using the label instruction. // Make a basic block using the label instruction.
std::unique_ptr<opt::BasicBlock> block = std::unique_ptr<opt::BasicBlock> block =
@ -285,9 +288,10 @@ bool TransformationAddFunction::TryToAddFunction(
// of the function, adding each such instruction to the block. // of the function, adding each such instruction to the block.
instruction_index++; instruction_index++;
while (instruction_index < num_instructions && while (instruction_index < num_instructions &&
message_.instruction(instruction_index).opcode() != spv::Op(message_.instruction(instruction_index).opcode()) !=
SpvOpFunctionEnd && spv::Op::OpFunctionEnd &&
message_.instruction(instruction_index).opcode() != SpvOpLabel) { spv::Op(message_.instruction(instruction_index).opcode()) !=
spv::Op::OpLabel) {
block->AddInstruction(InstructionFromMessage( block->AddInstruction(InstructionFromMessage(
ir_context, message_.instruction(instruction_index))); ir_context, message_.instruction(instruction_index)));
instruction_index++; instruction_index++;
@ -298,7 +302,8 @@ bool TransformationAddFunction::TryToAddFunction(
// Having considered all the blocks, we should be at the last instruction and // Having considered all the blocks, we should be at the last instruction and
// it needs to be OpFunctionEnd. // it needs to be OpFunctionEnd.
if (instruction_index != num_instructions - 1 || if (instruction_index != num_instructions - 1 ||
message_.instruction(instruction_index).opcode() != SpvOpFunctionEnd) { spv::Op(message_.instruction(instruction_index).opcode()) !=
spv::Op::OpFunctionEnd) {
return false; return false;
} }
// Set the function's final instruction, add the function to the module and // Set the function's final instruction, add the function to the module and
@ -339,20 +344,20 @@ bool TransformationAddFunction::TryToMakeFunctionLivesafe(
for (auto& block : *added_function) { for (auto& block : *added_function) {
for (auto& inst : block) { for (auto& inst : block) {
switch (inst.opcode()) { switch (inst.opcode()) {
case SpvOpKill: case spv::Op::OpKill:
case SpvOpUnreachable: case spv::Op::OpUnreachable:
if (!TryToTurnKillOrUnreachableIntoReturn(ir_context, added_function, if (!TryToTurnKillOrUnreachableIntoReturn(ir_context, added_function,
&inst)) { &inst)) {
return false; return false;
} }
break; break;
case SpvOpAccessChain: case spv::Op::OpAccessChain:
case SpvOpInBoundsAccessChain: case spv::Op::OpInBoundsAccessChain:
if (!TryToClampAccessChainIndices(ir_context, &inst)) { if (!TryToClampAccessChainIndices(ir_context, &inst)) {
return false; return false;
} }
break; break;
case SpvOpFunctionCall: case spv::Op::OpFunctionCall:
// A livesafe function my only call other livesafe functions. // A livesafe function my only call other livesafe functions.
if (!transformation_context.GetFactManager()->FunctionIsLivesafe( if (!transformation_context.GetFactManager()->FunctionIsLivesafe(
inst.GetSingleWordInOperand(0))) { inst.GetSingleWordInOperand(0))) {
@ -404,7 +409,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
auto loop_limit_constant_id_instr = auto loop_limit_constant_id_instr =
ir_context->get_def_use_mgr()->GetDef(message_.loop_limit_constant_id()); ir_context->get_def_use_mgr()->GetDef(message_.loop_limit_constant_id());
if (!loop_limit_constant_id_instr || if (!loop_limit_constant_id_instr ||
loop_limit_constant_id_instr->opcode() != SpvOpConstant) { loop_limit_constant_id_instr->opcode() != spv::Op::OpConstant) {
// The loop limit constant id instruction must exist and have an // The loop limit constant id instruction must exist and have an
// appropriate opcode. // appropriate opcode.
return false; return false;
@ -412,7 +417,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
auto loop_limit_type = ir_context->get_def_use_mgr()->GetDef( auto loop_limit_type = ir_context->get_def_use_mgr()->GetDef(
loop_limit_constant_id_instr->type_id()); loop_limit_constant_id_instr->type_id());
if (loop_limit_type->opcode() != SpvOpTypeInt || if (loop_limit_type->opcode() != spv::Op::OpTypeInt ||
loop_limit_type->GetSingleWordInOperand(0) != 32) { loop_limit_type->GetSingleWordInOperand(0) != 32) {
// The type of the loop limit constant must be 32-bit integer. It // The type of the loop limit constant must be 32-bit integer. It
// doesn't actually matter whether the integer is signed or not. // doesn't actually matter whether the integer is signed or not.
@ -457,7 +462,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
// Look for pointer-to-unsigned int type. // Look for pointer-to-unsigned int type.
opt::analysis::Pointer pointer_to_unsigned_int_type( opt::analysis::Pointer pointer_to_unsigned_int_type(
registered_unsigned_int_type, SpvStorageClassFunction); registered_unsigned_int_type, spv::StorageClass::Function);
uint32_t pointer_to_unsigned_int_type_id = uint32_t pointer_to_unsigned_int_type_id =
ir_context->get_type_mgr()->GetId(&pointer_to_unsigned_int_type); ir_context->get_type_mgr()->GetId(&pointer_to_unsigned_int_type);
if (!pointer_to_unsigned_int_type_id) { if (!pointer_to_unsigned_int_type_id) {
@ -477,13 +482,13 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
// Declare the loop limiter variable at the start of the function's entry // Declare the loop limiter variable at the start of the function's entry
// block, via an instruction of the form: // block, via an instruction of the form:
// %loop_limiter_var = SpvOpVariable %ptr_to_uint Function %zero // %loop_limiter_var = spv::Op::OpVariable %ptr_to_uint Function %zero
added_function->begin()->begin()->InsertBefore(MakeUnique<opt::Instruction>( added_function->begin()->begin()->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpVariable, pointer_to_unsigned_int_type_id, ir_context, spv::Op::OpVariable, pointer_to_unsigned_int_type_id,
message_.loop_limiter_variable_id(), message_.loop_limiter_variable_id(),
opt::Instruction::OperandList( opt::Instruction::OperandList({{SPV_OPERAND_TYPE_STORAGE_CLASS,
{{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}, {uint32_t(spv::StorageClass::Function)}},
{SPV_OPERAND_TYPE_ID, {zero_id}}}))); {SPV_OPERAND_TYPE_ID, {zero_id}}})));
// Update the module's id bound since we have added the loop limiter // Update the module's id bound since we have added the loop limiter
// variable id. // variable id.
fuzzerutil::UpdateModuleIdBound(ir_context, fuzzerutil::UpdateModuleIdBound(ir_context,
@ -589,10 +594,11 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
auto back_edge_block = ir_context->cfg()->block(back_edge_block_id); auto back_edge_block = ir_context->cfg()->block(back_edge_block_id);
auto back_edge_block_terminator = back_edge_block->terminator(); auto back_edge_block_terminator = back_edge_block->terminator();
bool compare_using_greater_than_equal; bool compare_using_greater_than_equal;
if (back_edge_block_terminator->opcode() == SpvOpBranch) { if (back_edge_block_terminator->opcode() == spv::Op::OpBranch) {
compare_using_greater_than_equal = true; compare_using_greater_than_equal = true;
} else { } else {
assert(back_edge_block_terminator->opcode() == SpvOpBranchConditional); assert(back_edge_block_terminator->opcode() ==
spv::Op::OpBranchConditional);
assert(((back_edge_block_terminator->GetSingleWordInOperand(1) == assert(((back_edge_block_terminator->GetSingleWordInOperand(1) ==
loop_header->id() && loop_header->id() &&
back_edge_block_terminator->GetSingleWordInOperand(2) == back_edge_block_terminator->GetSingleWordInOperand(2) ==
@ -613,7 +619,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
// Add a load from the loop limiter variable, of the form: // Add a load from the loop limiter variable, of the form:
// %t1 = OpLoad %uint32 %loop_limiter // %t1 = OpLoad %uint32 %loop_limiter
new_instructions.push_back(MakeUnique<opt::Instruction>( new_instructions.push_back(MakeUnique<opt::Instruction>(
ir_context, SpvOpLoad, unsigned_int_type_id, ir_context, spv::Op::OpLoad, unsigned_int_type_id,
loop_limiter_info.load_id(), loop_limiter_info.load_id(),
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}}}))); {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}}})));
@ -621,7 +627,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
// Increment the loaded value: // Increment the loaded value:
// %t2 = OpIAdd %uint32 %t1 %one // %t2 = OpIAdd %uint32 %t1 %one
new_instructions.push_back(MakeUnique<opt::Instruction>( new_instructions.push_back(MakeUnique<opt::Instruction>(
ir_context, SpvOpIAdd, unsigned_int_type_id, ir_context, spv::Op::OpIAdd, unsigned_int_type_id,
loop_limiter_info.increment_id(), loop_limiter_info.increment_id(),
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_id()}}, {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_id()}},
@ -630,7 +636,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
// Store the incremented value back to the loop limiter variable: // Store the incremented value back to the loop limiter variable:
// OpStore %loop_limiter %t2 // OpStore %loop_limiter %t2
new_instructions.push_back(MakeUnique<opt::Instruction>( new_instructions.push_back(MakeUnique<opt::Instruction>(
ir_context, SpvOpStore, 0, 0, ir_context, spv::Op::OpStore, 0, 0,
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}}, {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}},
{SPV_OPERAND_TYPE_ID, {loop_limiter_info.increment_id()}}}))); {SPV_OPERAND_TYPE_ID, {loop_limiter_info.increment_id()}}})));
@ -641,17 +647,18 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
// %t3 = OpULessThan %bool %t1 %loop_limit // %t3 = OpULessThan %bool %t1 %loop_limit
new_instructions.push_back(MakeUnique<opt::Instruction>( new_instructions.push_back(MakeUnique<opt::Instruction>(
ir_context, ir_context,
compare_using_greater_than_equal ? SpvOpUGreaterThanEqual compare_using_greater_than_equal ? spv::Op::OpUGreaterThanEqual
: SpvOpULessThan, : spv::Op::OpULessThan,
bool_type_id, loop_limiter_info.compare_id(), bool_type_id, loop_limiter_info.compare_id(),
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_id()}}, {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_id()}},
{SPV_OPERAND_TYPE_ID, {message_.loop_limit_constant_id()}}}))); {SPV_OPERAND_TYPE_ID, {message_.loop_limit_constant_id()}}})));
if (back_edge_block_terminator->opcode() == SpvOpBranchConditional) { if (back_edge_block_terminator->opcode() == spv::Op::OpBranchConditional) {
new_instructions.push_back(MakeUnique<opt::Instruction>( new_instructions.push_back(MakeUnique<opt::Instruction>(
ir_context, ir_context,
compare_using_greater_than_equal ? SpvOpLogicalOr : SpvOpLogicalAnd, compare_using_greater_than_equal ? spv::Op::OpLogicalOr
: spv::Op::OpLogicalAnd,
bool_type_id, loop_limiter_info.logical_op_id(), bool_type_id, loop_limiter_info.logical_op_id(),
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {{SPV_OPERAND_TYPE_ID,
@ -669,11 +676,11 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
back_edge_block_terminator->InsertBefore(std::move(new_instructions)); back_edge_block_terminator->InsertBefore(std::move(new_instructions));
} }
if (back_edge_block_terminator->opcode() == SpvOpBranchConditional) { if (back_edge_block_terminator->opcode() == spv::Op::OpBranchConditional) {
back_edge_block_terminator->SetInOperand( back_edge_block_terminator->SetInOperand(
0, {loop_limiter_info.logical_op_id()}); 0, {loop_limiter_info.logical_op_id()});
} else { } else {
assert(back_edge_block_terminator->opcode() == SpvOpBranch && assert(back_edge_block_terminator->opcode() == spv::Op::OpBranch &&
"Back-edge terminator must be OpBranch or OpBranchConditional"); "Back-edge terminator must be OpBranch or OpBranchConditional");
// Check that, if the merge block starts with OpPhi instructions, suitable // Check that, if the merge block starts with OpPhi instructions, suitable
@ -689,7 +696,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
// Augment OpPhi instructions at the loop merge with the given ids. // Augment OpPhi instructions at the loop merge with the given ids.
uint32_t phi_index = 0; uint32_t phi_index = 0;
for (auto& inst : *merge_block) { for (auto& inst : *merge_block) {
if (inst.opcode() != SpvOpPhi) { if (inst.opcode() != spv::Op::OpPhi) {
break; break;
} }
assert(phi_index < assert(phi_index <
@ -702,7 +709,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
} }
// Add the new edge, by changing OpBranch to OpBranchConditional. // Add the new edge, by changing OpBranch to OpBranchConditional.
back_edge_block_terminator->SetOpcode(SpvOpBranchConditional); back_edge_block_terminator->SetOpcode(spv::Op::OpBranchConditional);
back_edge_block_terminator->SetInOperands(opt::Instruction::OperandList( back_edge_block_terminator->SetInOperands(opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {loop_limiter_info.compare_id()}}, {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.compare_id()}},
{SPV_OPERAND_TYPE_ID, {loop_header->MergeBlockId()}}, {SPV_OPERAND_TYPE_ID, {loop_header->MergeBlockId()}},
@ -724,18 +731,18 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn( bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn(
opt::IRContext* ir_context, opt::Function* added_function, opt::IRContext* ir_context, opt::Function* added_function,
opt::Instruction* kill_or_unreachable_inst) const { opt::Instruction* kill_or_unreachable_inst) const {
assert((kill_or_unreachable_inst->opcode() == SpvOpKill || assert((kill_or_unreachable_inst->opcode() == spv::Op::OpKill ||
kill_or_unreachable_inst->opcode() == SpvOpUnreachable) && kill_or_unreachable_inst->opcode() == spv::Op::OpUnreachable) &&
"Precondition: instruction must be OpKill or OpUnreachable."); "Precondition: instruction must be OpKill or OpUnreachable.");
// Get the function's return type. // Get the function's return type.
auto function_return_type_inst = auto function_return_type_inst =
ir_context->get_def_use_mgr()->GetDef(added_function->type_id()); ir_context->get_def_use_mgr()->GetDef(added_function->type_id());
if (function_return_type_inst->opcode() == SpvOpTypeVoid) { if (function_return_type_inst->opcode() == spv::Op::OpTypeVoid) {
// The function has void return type, so change this instruction to // The function has void return type, so change this instruction to
// OpReturn. // OpReturn.
kill_or_unreachable_inst->SetOpcode(SpvOpReturn); kill_or_unreachable_inst->SetOpcode(spv::Op::OpReturn);
} else { } else {
// The function has non-void return type, so change this instruction // The function has non-void return type, so change this instruction
// to OpReturnValue, using the value id provided with the // to OpReturnValue, using the value id provided with the
@ -749,7 +756,7 @@ bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn(
->type_id() != function_return_type_inst->result_id()) { ->type_id() != function_return_type_inst->result_id()) {
return false; return false;
} }
kill_or_unreachable_inst->SetOpcode(SpvOpReturnValue); kill_or_unreachable_inst->SetOpcode(spv::Op::OpReturnValue);
kill_or_unreachable_inst->SetInOperands( kill_or_unreachable_inst->SetInOperands(
{{SPV_OPERAND_TYPE_ID, {message_.kill_unreachable_return_value_id()}}}); {{SPV_OPERAND_TYPE_ID, {message_.kill_unreachable_return_value_id()}}});
} }
@ -758,8 +765,8 @@ bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn(
bool TransformationAddFunction::TryToClampAccessChainIndices( bool TransformationAddFunction::TryToClampAccessChainIndices(
opt::IRContext* ir_context, opt::Instruction* access_chain_inst) const { opt::IRContext* ir_context, opt::Instruction* access_chain_inst) const {
assert((access_chain_inst->opcode() == SpvOpAccessChain || assert((access_chain_inst->opcode() == spv::Op::OpAccessChain ||
access_chain_inst->opcode() == SpvOpInBoundsAccessChain) && access_chain_inst->opcode() == spv::Op::OpInBoundsAccessChain) &&
"Precondition: instruction must be OpAccessChain or " "Precondition: instruction must be OpAccessChain or "
"OpInBoundsAccessChain."); "OpInBoundsAccessChain.");
@ -793,7 +800,7 @@ bool TransformationAddFunction::TryToClampAccessChainIndices(
assert(base_object && "The base object must exist."); assert(base_object && "The base object must exist.");
auto pointer_type = auto pointer_type =
ir_context->get_def_use_mgr()->GetDef(base_object->type_id()); ir_context->get_def_use_mgr()->GetDef(base_object->type_id());
assert(pointer_type && pointer_type->opcode() == SpvOpTypePointer && assert(pointer_type && 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 = ir_context->get_def_use_mgr()->GetDef( auto should_be_composite_type = ir_context->get_def_use_mgr()->GetDef(
pointer_type->GetSingleWordInOperand(1)); pointer_type->GetSingleWordInOperand(1));
@ -824,18 +831,18 @@ bool TransformationAddFunction::TryToClampAccessChainIndices(
auto index_inst = ir_context->get_def_use_mgr()->GetDef(index_id); auto index_inst = ir_context->get_def_use_mgr()->GetDef(index_id);
auto index_type_inst = auto index_type_inst =
ir_context->get_def_use_mgr()->GetDef(index_inst->type_id()); ir_context->get_def_use_mgr()->GetDef(index_inst->type_id());
assert(index_type_inst->opcode() == SpvOpTypeInt); assert(index_type_inst->opcode() == spv::Op::OpTypeInt);
assert(index_type_inst->GetSingleWordInOperand(0) == 32); assert(index_type_inst->GetSingleWordInOperand(0) == 32);
opt::analysis::Integer* index_int_type = opt::analysis::Integer* index_int_type =
ir_context->get_type_mgr() ir_context->get_type_mgr()
->GetType(index_type_inst->result_id()) ->GetType(index_type_inst->result_id())
->AsInteger(); ->AsInteger();
if (index_inst->opcode() != SpvOpConstant || if (index_inst->opcode() != spv::Op::OpConstant ||
index_inst->GetSingleWordInOperand(0) >= bound) { index_inst->GetSingleWordInOperand(0) >= bound) {
// The index is either non-constant or an out-of-bounds constant, so we // The index is either non-constant or an out-of-bounds constant, so we
// need to clamp it. // need to clamp it.
assert(should_be_composite_type->opcode() != SpvOpTypeStruct && assert(should_be_composite_type->opcode() != spv::Op::OpTypeStruct &&
"Access chain indices into structures are required to be " "Access chain indices into structures are required to be "
"constants."); "constants.");
opt::analysis::IntConstant bound_minus_one(index_int_type, {bound - 1}); opt::analysis::IntConstant bound_minus_one(index_int_type, {bound - 1});
@ -866,7 +873,7 @@ bool TransformationAddFunction::TryToClampAccessChainIndices(
// Compare the index with the bound via an instruction of the form: // Compare the index with the bound via an instruction of the form:
// %t1 = OpULessThanEqual %bool %index %bound_minus_one // %t1 = OpULessThanEqual %bool %index %bound_minus_one
new_instructions.push_back(MakeUnique<opt::Instruction>( new_instructions.push_back(MakeUnique<opt::Instruction>(
ir_context, SpvOpULessThanEqual, bool_type_id, compare_id, ir_context, spv::Op::OpULessThanEqual, bool_type_id, compare_id,
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {index_inst->result_id()}}, {{SPV_OPERAND_TYPE_ID, {index_inst->result_id()}},
{SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}}))); {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}})));
@ -874,7 +881,8 @@ bool TransformationAddFunction::TryToClampAccessChainIndices(
// Select the index if in-bounds, otherwise one less than the bound: // Select the index if in-bounds, otherwise one less than the bound:
// %t2 = OpSelect %int_type %t1 %index %bound_minus_one // %t2 = OpSelect %int_type %t1 %index %bound_minus_one
new_instructions.push_back(MakeUnique<opt::Instruction>( new_instructions.push_back(MakeUnique<opt::Instruction>(
ir_context, SpvOpSelect, index_type_inst->result_id(), select_id, ir_context, spv::Op::OpSelect, index_type_inst->result_id(),
select_id,
opt::Instruction::OperandList( opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {compare_id}}, {{SPV_OPERAND_TYPE_ID, {compare_id}},
{SPV_OPERAND_TYPE_ID, {index_inst->result_id()}}, {SPV_OPERAND_TYPE_ID, {index_inst->result_id()}},
@ -899,20 +907,20 @@ opt::Instruction* TransformationAddFunction::FollowCompositeIndex(
uint32_t index_id) { uint32_t index_id) {
uint32_t sub_object_type_id; uint32_t sub_object_type_id;
switch (composite_type_inst.opcode()) { switch (composite_type_inst.opcode()) {
case SpvOpTypeArray: case spv::Op::OpTypeArray:
case SpvOpTypeRuntimeArray: case spv::Op::OpTypeRuntimeArray:
sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0); sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0);
break; break;
case SpvOpTypeMatrix: case spv::Op::OpTypeMatrix:
case SpvOpTypeVector: case spv::Op::OpTypeVector:
sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0); sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0);
break; break;
case SpvOpTypeStruct: { case spv::Op::OpTypeStruct: {
auto index_inst = ir_context->get_def_use_mgr()->GetDef(index_id); auto index_inst = ir_context->get_def_use_mgr()->GetDef(index_id);
assert(index_inst->opcode() == SpvOpConstant); assert(index_inst->opcode() == spv::Op::OpConstant);
assert(ir_context->get_def_use_mgr() assert(ir_context->get_def_use_mgr()
->GetDef(index_inst->type_id()) ->GetDef(index_inst->type_id())
->opcode() == SpvOpTypeInt); ->opcode() == spv::Op::OpTypeInt);
assert(ir_context->get_def_use_mgr() assert(ir_context->get_def_use_mgr()
->GetDef(index_inst->type_id()) ->GetDef(index_inst->type_id())
->GetSingleWordInOperand(0) == 32); ->GetSingleWordInOperand(0) == 32);

View File

@ -39,14 +39,14 @@ bool TransformationAddGlobalUndef::IsApplicable(
auto type = ir_context->get_def_use_mgr()->GetDef(message_.type_id()); auto type = ir_context->get_def_use_mgr()->GetDef(message_.type_id());
// The type must exist, and must not be a function or pointer type. // The type must exist, and must not be a function or pointer type.
return type != nullptr && opt::IsTypeInst(type->opcode()) && return type != nullptr && opt::IsTypeInst(type->opcode()) &&
type->opcode() != SpvOpTypeFunction && type->opcode() != spv::Op::OpTypeFunction &&
type->opcode() != SpvOpTypePointer; type->opcode() != spv::Op::OpTypePointer;
} }
void TransformationAddGlobalUndef::Apply( void TransformationAddGlobalUndef::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const { opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
auto new_instruction = MakeUnique<opt::Instruction>( auto new_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpUndef, message_.type_id(), message_.fresh_id(), ir_context, spv::Op::OpUndef, message_.type_id(), message_.fresh_id(),
opt::Instruction::OperandList()); opt::Instruction::OperandList());
auto new_instruction_ptr = new_instruction.get(); auto new_instruction_ptr = new_instruction.get();
ir_context->module()->AddGlobalValue(std::move(new_instruction)); ir_context->module()->AddGlobalValue(std::move(new_instruction));

View File

@ -24,11 +24,11 @@ TransformationAddGlobalVariable::TransformationAddGlobalVariable(
: message_(std::move(message)) {} : message_(std::move(message)) {}
TransformationAddGlobalVariable::TransformationAddGlobalVariable( TransformationAddGlobalVariable::TransformationAddGlobalVariable(
uint32_t fresh_id, uint32_t type_id, SpvStorageClass storage_class, uint32_t fresh_id, uint32_t type_id, spv::StorageClass storage_class,
uint32_t initializer_id, bool value_is_irrelevant) { uint32_t initializer_id, bool value_is_irrelevant) {
message_.set_fresh_id(fresh_id); message_.set_fresh_id(fresh_id);
message_.set_type_id(type_id); message_.set_type_id(type_id);
message_.set_storage_class(storage_class); message_.set_storage_class(uint32_t(storage_class));
message_.set_initializer_id(initializer_id); message_.set_initializer_id(initializer_id);
message_.set_value_is_irrelevant(value_is_irrelevant); message_.set_value_is_irrelevant(value_is_irrelevant);
} }
@ -41,10 +41,10 @@ bool TransformationAddGlobalVariable::IsApplicable(
} }
// The storage class must be Private or Workgroup. // The storage class must be Private or Workgroup.
auto storage_class = static_cast<SpvStorageClass>(message_.storage_class()); auto storage_class = static_cast<spv::StorageClass>(message_.storage_class());
switch (storage_class) { switch (storage_class) {
case SpvStorageClassPrivate: case spv::StorageClass::Private:
case SpvStorageClassWorkgroup: case spv::StorageClass::Workgroup:
break; break;
default: default:
assert(false && "Unsupported storage class."); assert(false && "Unsupported storage class.");
@ -66,7 +66,7 @@ bool TransformationAddGlobalVariable::IsApplicable(
} }
if (message_.initializer_id()) { if (message_.initializer_id()) {
// An initializer is not allowed if the storage class is Workgroup. // An initializer is not allowed if the storage class is Workgroup.
if (storage_class == SpvStorageClassWorkgroup) { if (storage_class == spv::StorageClass::Workgroup) {
assert(false && assert(false &&
"By construction this transformation should not have an " "By construction this transformation should not have an "
"initializer when Workgroup storage class is used."); "initializer when Workgroup storage class is used.");
@ -95,7 +95,7 @@ void TransformationAddGlobalVariable::Apply(
TransformationContext* transformation_context) const { TransformationContext* transformation_context) const {
opt::Instruction* new_instruction = fuzzerutil::AddGlobalVariable( opt::Instruction* new_instruction = fuzzerutil::AddGlobalVariable(
ir_context, message_.fresh_id(), message_.type_id(), ir_context, message_.fresh_id(), message_.type_id(),
static_cast<SpvStorageClass>(message_.storage_class()), static_cast<spv::StorageClass>(message_.storage_class()),
message_.initializer_id()); message_.initializer_id());
// Inform the def-use manager about the new instruction. // Inform the def-use manager about the new instruction.

View File

@ -29,7 +29,7 @@ class TransformationAddGlobalVariable : public Transformation {
protobufs::TransformationAddGlobalVariable message); protobufs::TransformationAddGlobalVariable message);
TransformationAddGlobalVariable(uint32_t fresh_id, uint32_t type_id, TransformationAddGlobalVariable(uint32_t fresh_id, uint32_t type_id,
SpvStorageClass storage_class, spv::StorageClass storage_class,
uint32_t initializer_id, uint32_t initializer_id,
bool value_is_irrelevant); bool value_is_irrelevant);

View File

@ -73,7 +73,7 @@ bool TransformationAddImageSampleUnusedComponents::IsApplicable(
// It must be an OpCompositeConstruct instruction such that it can be checked // It must be an OpCompositeConstruct instruction such that it can be checked
// that the original components are present. // that the original components are present.
if (coordinate_with_unused_components_instruction->opcode() != if (coordinate_with_unused_components_instruction->opcode() !=
SpvOpCompositeConstruct) { spv::Op::OpCompositeConstruct) {
return false; return false;
} }

View File

@ -43,8 +43,10 @@ bool TransformationAddLocalVariable::IsApplicable(
// function storage class. // function storage class.
auto type_instruction = auto type_instruction =
ir_context->get_def_use_mgr()->GetDef(message_.type_id()); ir_context->get_def_use_mgr()->GetDef(message_.type_id());
if (!type_instruction || type_instruction->opcode() != SpvOpTypePointer || if (!type_instruction ||
type_instruction->GetSingleWordInOperand(0) != SpvStorageClassFunction) { type_instruction->opcode() != spv::Op::OpTypePointer ||
spv::StorageClass(type_instruction->GetSingleWordInOperand(0)) !=
spv::StorageClass::Function) {
return false; return false;
} }
// The initializer must... // The initializer must...

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